Trailing Newline-teken verwijderen van FGETS () Invoer

Ik probeer wat gegevens van de gebruiker te krijgen en stuur het naar een andere functie in GCC. De code is zoiets.

printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}

Ik merk echter dat het een nieuwe lijn \nteken op het einde heeft. Dus als ik Johninvoert, verzenden het John\n. Hoe verwijder ik dat \nen stuur een goede string.


1, Autoriteit 100%

de elegante manier:

Name[strcspn(Name, "\n")] = 0;

De enigszins Ugly Way:

char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
    *pos = '\0';
else
    /* input too long for buffer, flag error */

de enigszins vreemde manier:

strtok(Name, "\n");

Merk op dat de functie strtokniet werkt zoals verwacht als de gebruiker een lege reeks invoert (d.w.z. drukt alleen enter). Het laat de \nteken intact.

Er zijn natuurlijk ook anderen.


2, Autoriteit 255%

Misschien maakt de eenvoudigste oplossing gebruik van een van mijn favoriete kleine functies, strcspn():

buffer[strcspn(buffer, "\n")] = 0;

Als u wilt dat het ook '\r'(zeg, als de stroom binair is):

buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...

De functie telt het aantal tekens totdat het een '\r'of een '\n'raakt (met andere woorden, het vindt de eerste '\r'of '\n'). Als het niets raakt, stopt het bij de '\0'(waarbij de lengte van de string wordt geretourneerd).

Merk op dat dit prima werkt, zelfs als er geen nieuwe regel is, omdat strcspnstopt bij een '\0'. In dat geval vervangt de hele regel gewoon '\0'door '\0'.


Antwoord 3, autoriteit 42%

size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';

Antwoord 4, autoriteit 5%

Direct om de ‘\n’ uit de fgets-uitvoer te verwijderen als elke regel ‘\n’ heeft

line[strlen(line) - 1] = '\0';

Anders:

void remove_newline_ch(char *line)
{
    int new_line = strlen(line) -1;
    if (line[new_line] == '\n')
        line[new_line] = '\0';
}

Antwoord 5

Voor enkelvoudig ‘\n’ trimmen,

void remove_new_line(char* string)
{
    size_t length = strlen(string);
    if((length > 0) && (string[length-1] == '\n'))
    {
        string[length-1] ='\0';
    }
}

voor meerdere ‘\n’ trimmen,

void remove_multi_new_line(char* string)
{
  size_t length = strlen(string);
  while((length>0) && (string[length-1] == '\n'))
  {
      --length;
      string[length] ='\0';
  }
}

Antwoord 6

Mijn Newbie-manier 😉 Laat me alsjeblieft weten of dat klopt. Het lijkt te werken voor al mijn gevallen:

#define IPT_SIZE 5
int findNULL(char* arr)
{
    for (int i = 0; i < strlen(arr); i++)
    {
        if (*(arr+i) == '\n')
        {
            return i;
        }
    }
    return 0;
}
int main()
{
    char *input = malloc(IPT_SIZE + 1 * sizeof(char)), buff;
    int counter = 0;
    //prompt user for the input:
    printf("input string no longer than %i characters: ", IPT_SIZE);
    do
    {
        fgets(input, 1000, stdin);
        *(input + findNULL(input)) = '\0';
        if (strlen(input) > IPT_SIZE)
        {
            printf("error! the given string is too large. try again...\n");
            counter++;
        }
        //if the counter exceeds 3, exit the program (custom function):
        errorMsgExit(counter, 3); 
    }
    while (strlen(input) > IPT_SIZE);
//rest of the program follows
free(input)
return 0;
}

7

Als het gebruik van getlineis, is een optie – het niet verwaarlozen van de veiligheidskwesties en als u aanwijzingen wilt zetten – kunt u stringfuncties vermijden als de getlineretourneert het aantal tekens . Zoiets als onderstaande

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *fname, *lname;
    size_t size = 32, nchar; // Max size of strings and number of characters read
    fname = malloc(size * sizeof *fname);
    lname = malloc(size * sizeof *lname);
    if (NULL == fname || NULL == lname)
    {
        printf("Error in memory allocation.");
        exit(1);
    }
    printf("Enter first name ");
    nchar = getline(&fname, &size, stdin);
    if (nchar == -1) // getline return -1 on failure to read a line.
    {
        printf("Line couldn't be read..");
        // This if block could be repeated for next getline too
        exit(1);
    }
    printf("Number of characters read :%zu\n", nchar);
    fname[nchar - 1] = '\0';
    printf("Enter last name ");
    nchar = getline(&lname, &size, stdin);
    printf("Number of characters read :%zu\n", nchar);
    lname[nchar - 1] = '\0';
    printf("Name entered %s %s\n", fname, lname);
    return 0;
}

Opmerking: de [ beveiligingsproblemen]met getlinemogen echter niet worden verwaarloosd.


Antwoord 8

In het algemeen, in plaats van gegevens bij te snijden die u niet wilt, moet u deze in de eerste plaats niet schrijven. Als je de nieuwe regel niet in de buffer wilt, gebruik dan geen fgets. Gebruik in plaats daarvan getcof fgetcof scanf. Misschien zoiets als:

#include <stdio.h>
int
main(void)
{
        char Name[256];
        char fmt[32];
        sprintf(fmt, "%%%zd[^\n]", sizeof Name - 1);
        if( scanf(fmt, Name) == 1 ) {
                printf("Name = %s\n", Name);
        }
        return 0;
}

Houd er rekening mee dat deze specifieke benadering de nieuwe regel ongelezen laat, dus u kunt een opmaakreeks zoals "%255[^\n]%*c"gebruiken om deze te verwijderen (bijv. sprintf(fmt, "%%%zd[^\n]%%*c", sizeof Name - 1);), of misschien volg de scanf met een getchar().


Antwoord 9

Tim Čas one liner is geweldig voor strings die worden verkregen door een oproep naar fgets, omdat je weet dat ze aan het einde een enkele nieuwe regel bevatten.

Als u zich in een andere context bevindt en tekenreeksen wilt afhandelen die meer dan één nieuwe regel kunnen bevatten, zoekt u misschien naar strrspn. Het is geen POSIX, wat betekent dat je het niet op alle Unices zult vinden. Ik heb er een geschreven voor mijn eigen behoeften.

/* Returns the length of the segment leading to the last 
   characters of s in accept. */
size_t strrspn (const char *s, const char *accept)
{
  const char *ch;
  size_t len = strlen(s);
more: 
  if (len > 0) {
    for (ch = accept ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        len--;
        goto more;
      }
    }
  }
  return len;
}

Voor degenen die op zoek zijn naar een Perl-chomp-equivalent in C, denk ik dat dit het is (chomp verwijdert alleen de achterste nieuwe regel).

line[strrspn(string, "\r\n")] = 0;

De strrcspn-functie:

/* Returns the length of the segment leading to the last 
   character of reject in s. */
size_t strrcspn (const char *s, const char *reject)
{
  const char *ch;
  size_t len = strlen(s);
  size_t origlen = len;
  while (len > 0) {
    for (ch = reject ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        return len;
      }
    }
    len--;
  }
  return origlen;
}

Antwoord 10

De onderstaande functie is een onderdeel van de stringverwerkingsbibliotheek die ik onderhoud op Github. Het verwijdert en ongewenste tekens uit een string, precies wat je wilt

int zstring_search_chr(const char *token,char s){
    if (!token || s=='\0')
        return 0;
    for (;*token; token++)
        if (*token == s)
            return 1;
    return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
    char *src = str , *dst = str;
    while(*src)
        if(zstring_search_chr(bad,*src))
            src++;
        else
            *dst++ = *src++;  /* assign first, then incement */
    *dst='\0';
        return str;
}

Een voorbeeldgebruik kan zijn

Example Usage
      char s[]="this is a trial string to test the function.";
      char const *d=" .";
      printf("%s\n",zstring_remove_chr(s,d));
  Example Output
      thisisatrialstringtotestthefunction

Misschien wil je andere beschikbare functies bekijken of zelfs bijdragen aan het project 🙂
https://github.com/fnoyanisi/zString


Antwoord 11

for(int i = 0; i < strlen(Name); i++ )
{
    if(Name[i] == '\n') Name[i] = '\0';
}

Je zou het eens moeten proberen. Deze code loopt in feite door de string totdat deze de ‘\n’ vindt. Als het is gevonden, wordt de ‘\n’ vervangen door de null-tekenbeëindiging ‘\0’

Merk op dat je karakters vergelijkt en geen strings in deze regel, dan is het niet nodig om strcmp():

te gebruiken

if(Name[i] == '\n') Name[i] = '\0';

aangezien u enkele aanhalingstekens gebruikt en geen dubbele aanhalingstekens. Hier iseen link over single vs dubbele aanhalingstekens als je meer wilt weten

Other episodes