Usuwanie końcowego znaku nowej linii z wprowadzania fgets ()


235

Próbuję pobrać dane od użytkownika i wysłać je do innej funkcji w gcc. Kod jest mniej więcej taki.

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

Uważam jednak, że ma on \nna końcu znak nowej linii . Więc jeśli Johnwejdę, wyśle ​​to John\n. Jak to usunąć \ni wysłać odpowiedni ciąg.


21
if (!fgets(Name, sizeof Name, stdin))(przynajmniej nie używaj dwóch negacji,! i! =)

4
@Roger Pate „nie używaj dwóch negacji” -> hmmm, jeśli kopiemy głęboko, „nie” i „negacja” są zarówno negacjami . ;-). Być może „Użyj if (fgets(Name, sizeof Name, stdin)) {.
chux - Przywróć Monikę

3
@chux, jestem pewien, że miałeś na myśliif (fgets(Name, sizeof Name, stdin) == NULL ) {
R Sahu

@RSahu True : pesky !:
chux - Przywróć Monikę

Odpowiedzi:


154

Nieco brzydki sposób:

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

Nieco dziwny sposób:

strtok(Name, "\n");

Zauważ, że strtokfunkcja nie działa zgodnie z oczekiwaniami, jeśli użytkownik wprowadzi pusty ciąg znaków (tzn. Naciśnie tylko Enter). Pozostawia \npostać nietkniętą.

Oczywiście są też inni.


7
Każda biblioteka środowiska wykonawczego C, która jest świadoma wątków (to znaczy większość tych, które są ukierunkowane na platformę wielowątkową), strtok()będzie bezpieczna dla wątków (użyje lokalnej pamięci wątków dla stanu „połączenia”). To powiedziawszy, ogólnie lepiej jest używać niestandardowego (ale dość powszechnego) strtok_r()wariantu.
Michael Burr

2
Zobacz moją odpowiedź na całkowicie bezpieczny wątek i wariant ponownego wysyłania, podobny do twojego strtokpodejścia (i działa z pustymi danymi wejściowymi). W rzeczywistości dobrym sposobem na wdrożenie strtokjest użycie strcspni strspn.
Tim Čas,

2
Ważne jest, aby zająć się sprawą else, jeśli jesteś w środowisku, w którym istnieje ryzyko przekroczenia długich linii. Ciche obcięcie danych wejściowych może powodować bardzo szkodliwe błędy.
Malcolm McLean

2
Jeśli lubisz jedno-linijki i używasz glibc, spróbuj *strchrnul(Name, '\n') = '\0';.
twobit

Kiedy strchr(Name, '\n') == NULLoprócz „zbyt długich danych wejściowych dla bufora, błędu flagi” istnieją inne możliwości: Ostatni tekst stdinnie zakończył się znakiem '\n'lub został odczytany rzadko osadzony znak null.
chux - Przywróć Monikę

439

Być może najprostsze rozwiązanie wykorzystuje jedną z moich ulubionych mało znanych funkcji strcspn():

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

Jeśli chcesz, aby również obsługiwał '\r'(powiedzmy, jeśli strumień jest binarny):

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

Funkcja zlicza liczbę znaków, aż trafi na a '\r'lub a '\n'(innymi słowy, znajdzie pierwszy '\r'lub '\n'). Jeśli niczego nie trafi, zatrzymuje się na '\0'(zwracając długość łańcucha).

Zauważ, że działa to dobrze, nawet jeśli nie ma nowej linii, ponieważ strcspnkończy się na '\0'. W takim przypadku cała linia po prostu zastępuje '\0'się '\0'.


30
Nawet obsługuje to rzadki bufferniż zaczyna się '\0'coś, co powoduje smutek dla buffer[strlen(buffer) - 1] = '\0';podejścia.
chux - Przywróć Monikę

5
@chux: Tak, chciałbym, żeby więcej osób wiedziało strcspn(). Jedna z bardziej przydatnych funkcji w bibliotece, IMO. Postanowiłem dziś napisać i opublikować kilka popularnych hacków typu C; strtok_rrealizacja użyciu strcspni strspnbył jednym z pierwszych: codepad.org/2lBkZk0w ( Ostrzeżenie: Nie mogę zagwarantować, że to bez błędów; został on napisany w pośpiechu i prawdopodobnie ma kilka). Nie wiem jeszcze, gdzie je opublikuję, ale zamierzam zrobić to w duchu słynnych „nieco kręcących się hacków”.
Tim Čas,

4
Spojrzał na sposoby na solidne wykończeniefgets() . To strcspn()wydaje się być jedynie słuszny-liner. strlenjest szybszy - choć nie tak prosty.
chux - Przywróć Monikę

6
@sidbushes: Pytanie, zarówno w tytule, jak i treści, pyta o końcowy znak nowej linii od fgets()wejścia . Który zawsze jest także pierwszą nową linią.
Tim Čas

9
@sidbushes: Rozumiem, skąd pochodzisz, ale nie mogę ponosić odpowiedzialności za wyniki wyszukiwania Google dla określonych haseł. Porozmawiaj z Google, a nie ze mną.
Tim Čas

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

8
Prawdopodobnie wyrzuci wyjątek, jeśli ciąg znaków będzie pusty, prawda? Jak indeks poza zakresem.
Edward Olamisan

1
@EdwardOlamisan, łańcuch nigdy nie będzie jednak pusty.
James Morris

5
@James Morris W nietypowych przypadkach fgets(buf, size, ....)-> strlen(buf) == 0. 1) fgets()czyta się jako pierwszy chara '\0'. 2) size == 13) fgets()zwraca, NULLwtedy bufzawartość może być dowolna. (Kod OP sprawdza, czy ma wartość NULL) Sugeruj:size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
Chux - Przywróć Monikę

2
Co jeśli ciąg jest pusty? lnwyniesie -1, z wyjątkiem faktu, że nie size_tjest podpisany, a zatem zapis do losowej pamięci. Myślę, że chcesz użyć ssize_ti sprawdź ln> 0.
dniu

2
@ legends2k: Wyszukiwanie wartości czasu kompilacji (szczególnie wartości zerowej jak w in strlen) może być zaimplementowane znacznie wydajniej niż zwykłe wyszukiwanie char-by-char. Z tego powodu uważam to rozwiązanie za lepsze niż oparte na nim strchrlub strcspnoparte.
AnT

17

Poniżej znajduje się szybkie podejście do usunięcia potencjału '\n'z ciągu zapisanego przez fgets().
Używa strlen(), z 2 testami.

char buffer[100];
if (fgets(buffer, sizeof buffer, stdin) != NULL) {

  size_t len = strlen(buffer);
  if (len > 0 && buffer[len-1] == '\n') {
    buffer[--len] = '\0';
  }

Teraz użyj bufferilen w razie potrzeby.

Ta metoda ma dodatkową zaletę lenwartości dla kolejnego kodu. Może być łatwo szybszy niż strchr(Name, '\n'). Ref YMMV, ale obie metody pracy.


buffer, z oryginału fgets()nie będzie zawierał w "\n"pewnych okolicznościach:
A) Linia była zbyt długa, bufferdlatego zapisano ją tylko charprzed nią . Nieprzeczytane znaki pozostają w strumieniu. B) Ostatni wiersz w pliku nie kończył się na'\n'buffer
'\n' .

Jeśli dane wejściowe mają '\0'gdzieś osadzone znaki zerowe , podawana przez strlen()nie długość nie uwzględni '\n'lokalizacji.


Niektóre inne problemy z odpowiedziami:

  1. strtok(buffer, "\n");nie usuwa '\n'kiedy bufferjest "\n". Z tej odpowiedzi - poprawionej po tej odpowiedzi w celu ostrzeżenia o tym ograniczeniu.

  2. Następujące przypadki zawodzą w rzadkich przypadkach, gdy pierwszy charodczyt fgets()jest '\0'. Dzieje się tak, gdy dane wejściowe zaczynają się od osadzenia '\0'. Wtedy buffer[len -1]staje się buffer[SIZE_MAX]dostęp do pamięci z pewnością poza uzasadnionym zakresie buffer. Coś, co haker może spróbować znaleźć w niemądrym czytaniu plików tekstowych UTF16. Taki był stan odpowiedzi, kiedy ta odpowiedź została napisana. Później edytor nieobsługujący OP zmodyfikował go, aby uwzględnić kod podobny do sprawdzania tej odpowiedzi "".

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
  3. sprintf(buffer,"%s",buffer);jest niezdefiniowane zachowanie: Ref . Ponadto nie zapisuje żadnych początkowych, oddzielających ani końcowych białych znaków. Teraz usunięte .

  4. [Edytuj ze względu na dobrą późniejszą odpowiedź ] Nie ma żadnych problemów z 1 wkładką buffer[strcspn(buffer, "\n")] = 0;poza wydajnością w porównaniu do strlen()podejścia. Wydajność przycinania zwykle nie stanowi problemu, ponieważ kod wykonuje operacje we / wy - czarna dziura czasu procesora. Jeśli następujący kod wymaga długości łańcucha lub jest wysoce świadomy wydajności, użyj tego strlen()podejścia. W przeciwnym razie strcspn()jest to dobra alternatywa.


Dziękuję za pomocną odpowiedź. Czy możemy użyć, strlen(buffer)gdy rozmiar bufora jest dynamicznie przydzielany za pomocą malloc?
rrz0

@ Rrz0 buffer = malloc(allocation_size); length = strlen(buffer);jest zły - dane w pamięci wskazywane przez buffersą nieznane. buffer = malloc(allocation_size_4_or_more); strcpy(buffer, "abc"); length = strlen(buffer);jest OK
chux - Przywróć Monikę

dzięki za to!! biorę kurs CS i to było bardzo pomocne dla jednego z zadań. podałem twoją odpowiedź w kodzie źródłowym.
Nathaniel Hoyt

8

Bezpośrednio, aby usunąć „\ n” z wyjścia fgets, jeśli każda linia ma „\ n”

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

Inaczej:

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

1
Zauważ, że bezpieczniej byłoby używać strnlenzamiast strlen.
Mike Mertsock,

3
Komentarz do pierwszej odpowiedzi w połączonym pytaniu stwierdza: „Zauważ, że strlen (), strcmp () i strdup () są bezpieczne. Alternatywy„ n ”zapewniają dodatkową funkcjonalność.”
Étienne,

4
@esker nie, nie zrobiłby tego. wstawienie nnie magicznie zwiększa bezpieczeństwa, w tym przypadku w rzeczywistości uczyniłoby kod bardziej niebezpiecznym. Podobnie z strncpyniezwykle niebezpieczną funkcją. Wpis, do którego linkujesz, to zła rada.
MM

3
To kończy się niepowodzeniem w przypadku pustego ciągu ( ""). strlen()Zwraca również size_tnie int.
alk

4
jest to niebezpieczne dla pustego łańcucha, zapisze w indeksie -1. Nie używaj tego.
Jean-François Fabre

3

W przypadku przycinania pojedynczego „\ n”,

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

do wielokrotnego przycinania „\ n”,

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

1
ifPo co się zagnieżdżać, skoro można po prostu napisać jeden warunek &&? Ta whilepętla ma dziwną strukturę; może po prostu być while (length > 0 && string[length-1] == '\n') { --length; string[length] = '\0'; }.
melpomene

@melpomene dzięki za sugestię. Zaktualizuj kod.
BEPP

1
Sugeruję, że pierwsza funkcja jest bardziej naturalny sposób definiuje się jako: size_t length = strlen(string); if (length > 0 && string[length-1] == '\n') { string[length-1] = '\0'; }. To również lepiej odzwierciedla drugą definicję (tylko użycie ifzamiast while).
melpomene

@elpomene dzięki. To ma sens. Zaktualizowałem kod.
BEPP

1

Mój nowy sposób ;-) Daj mi znać, jeśli to prawda. Wygląda na to, że działa we wszystkich moich przypadkach:

#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;
}

1

Kroki, aby usunąć znak nowej linii w możliwie najbardziej oczywisty sposób:

  1. Określ długość łańcucha wewnątrz NAMEza pomocą strlen()nagłówka string.h. Zauważ, że strlen()nie liczy się zakończenie \0.
size_t sl = strlen(NAME);

  1. Sprawdź, czy ciąg zaczyna się od, czy zawiera tylko jeden \0znak (pusty ciąg). W takim przypadku slbyłoby, 0ponieważ, strlen()jak powiedziałem powyżej, nie liczy się \0i zatrzymuje przy pierwszym wystąpieniu:
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. Sprawdź, czy ostatni znak właściwego ciągu jest znakiem nowego wiersza '\n'. W takim przypadku zamień \nna \0. Pamiętaj, że liczenie indeksów zaczyna się od, 0więc będziemy musieli zrobić NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

Zauważ, że jeśli naciśniesz Enter tylko na fgets()żądanie łańcucha (treść łańcucha składała się tylko ze znaku nowej linii), łańcuch NAMEbędzie później pusty.


  1. Możemy połączyć krok 2. i 3. razem w jednym ifzestawieniu, używając operatora logicznego &&:
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

  1. Gotowy kod:
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

Jeśli wolisz funkcję używającą tej techniki, obsługującą fgetsciągi wyjściowe w ogóle bez ponownego wpisywania za każdym razem, oto fgets_newline_kill:

void fgets_newline_kill(char a[])
{
    size_t sl = strlen(a);

    if(sl > 0 && a[sl - 1] == '\n')
    {
       a[sl - 1] = '\0';
    }
}

W podanym przykładzie byłoby to:

printf("Enter your Name: ");

if (fgets(Name, sizeof Name, stdin) == NULL) {
    fprintf(stderr, "Error reading Name.\n");
    exit(1);
}
else {
    fgets_newline_kill(NAME);
}

Zauważ, że ta metoda nie działa, jeśli łańcuch wejściowy ma \0w niej osadzone s. W takim przypadku strlen()zwracałaby tylko liczbę znaków do pierwszego \0. Ale nie jest to dość powszechne podejście, ponieważ większość funkcji czytania ciągów zwykle zatrzymuje się na początku\0 i pobiera ciąg znaków aż do znaku o wartości zerowej.

Oprócz samego pytania. Staraj się unikać podwójnych negacji, które czynią swój kod unclearer: if (!(fgets(Name, sizeof Name, stdin) != NULL) {}. Możesz po prostu zrobić if (fgets(Name, sizeof Name, stdin) == NULL) {}.


Nie jestem pewien, dlaczego chcesz to zrobić. Celem usuwania nowych linii nie jest ciągi zerowe; jest usunięcie nowych linii. Wymiana \nz \0na końcu ciągu znaków jest sposobem na „usuwaniu” nowej linii. Ale zastąpienie \nznaków w ciągu zasadniczo zmienia ciąg. Często zdarza się, że ciągi znaków zawierają celowo wiele znaków nowej linii, a to skutecznie odcina ich końce. Aby usunąć takie nowe znaki, zawartość tablicy musi przesunąć w lewo, aby nadpisać \n.
ex nihilo

@exnihilo Jak ktoś może wprowadzić ciąg z wieloma znakami nowej linii za pomocą fgets()?
RobertS wspiera Monikę Cellio

Cóż, możesz połączyć łańcuchy uzyskane przez wiele wywołań do fgets(). Ale nie rozumiem twojego sprzeciwu: to ty proponujesz kod do obsługi wielu nowych linii.
ex nihilo

@exnihilo Masz rację, przemyślę strategię. Chciałem tylko dodać bardzo surowy, ale możliwy sposób, aby uzyskać pożądany efekt.
RobertS obsługuje Monikę Cellio

@exnihilo Całkowicie zredagowałem moją odpowiedź i zastosowałem główne podejście, używając strlenitp. Uzasadnienie braku bycia duplikatem: 1. Objaśnienie kodu krok po kroku. 2. Dostarczone jako rozwiązanie funkcyjne i kontekstowe. 3. Wskazówka, aby uniknąć wyrażeń podwójnej negacji.
RobertS obsługuje Monikę Cellio

0

Jeden linijka Tim Čas jest niesamowity dla ciągów uzyskanych przez wezwanie do fgets, ponieważ wiesz, że zawierają jedną nową linię na końcu.

Jeśli jesteś w innym kontekście i chcesz obsługiwać ciągi znaków, które mogą zawierać więcej niż jeden znak nowej linii, być może szukasz strrspn. To nie jest POSIX, co oznacza, że ​​nie znajdziesz go na wszystkich Uniksach. Napisałem jeden na własne potrzeby.

/* 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;
}

Dla tych, którzy szukają Perl chomp równoważnych w C, myślę, że to jest to (chomp usuwa tylko końcowy znak nowej linii).

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

Funkcja strrcspn:

/* 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;
}

1
„ponieważ wiesz, że na końcu zawierają jedną nową linię”. -> Działa nawet, gdy nie ma '\n'(lub jeśli ciąg jest "").
chux - Przywróć Monikę

W odpowiedzi na Twój pierwszy komentarz, moja odpowiedź to zachowuje. Musiałem wrzucić resetlen, strrcspngdy nie ma go \n.
Philippe A.,

Dlaczego warto korzystać goto end;zamiast return len;?
chqrlie,

@chqrlie Musiałem wyjść z tej nieeleganckiej 2-poziomowej pętli, w którą się wszedłem. Szkoda została wyrządzona. Dlaczego nie goto?
Philippe A.,

W gototwoim kodzie są dwa rodzaje s: bezużyteczne, gotoktóre można zastąpić returninstrukcją i wstecz, gotoktóry jest uważany za zły. Korzystanie strchrpomaga w implementacji strrspni strrcspnw prostszy sposób: size_t strrspn(const char *s, const char *accept) { size_t len = strlen(s); while (len > 0 && strchr(accept, s[len - 1])) { len--; } return len; }orazsize_t strrcspn(const char *s, const char *reject) { size_t len = strlen(s); while (len > 0 && !strchr(reject, s[len - 1])) { len--; } return len; }
chqrlie,

0

Jeśli użycie getlinejest opcją - Nie zaniedbując jej problemów związanych z bezpieczeństwem i jeśli chcesz nawiasować wskaźniki - możesz uniknąć funkcji łańcuchowych, ponieważ getlinezwraca liczbę znaków. Coś jak poniżej

#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;
}

Uwaga : W [ kwestie bezpieczeństwa ] z getlinenie należy lekceważyć, choć.


-1

Poniższa funkcja jest częścią biblioteki przetwarzania ciągów, którą utrzymuję w Github. Usuwa niechciane znaki z łańcucha dokładnie tego, czego chcesz

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;
}

Przykładem użycia może być

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

Możesz sprawdzić inne dostępne funkcje, a nawet przyczynić się do projektu :) https://github.com/fnoyanisi/zString


Należy usunąć *w *src++;i sprawiają bad, tokeni d const char *. A dlaczego nie użyć strchrzamiast zChrSearch? *srcnie może być '\0'w twojej zStrrmvfunkcji.
chqrlie,

Dzięki @chqrlie! zaktualizowałem kod, aby odzwierciedlić twoje sugestie ..... Zstring rozpoczął się jako fajny projekt mający na celu utworzenie biblioteki manipulacji ciągami bez użycia standardowych funkcji bibliotecznych, dlatego nie strchr
użyłem

1
Pisanie „ biblioteki manipulacji ciągami bez użycia standardowych funkcji bibliotecznych ” to fajne ćwiczenie, ale po co mówić innym ludziom, żeby z niej korzystali? Jeśli już, będzie wolniejszy i mniej przetestowany niż jakakolwiek standardowa biblioteka.
melpomene

To robi inną pracę niż ta, o którą pyta pytanie. Prawdopodobnie można go użyć do pozbycia się jedynego nowego wiersza, ale wydaje się, że to przesada.
Jonathan Leffler

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

Powinieneś spróbować. Ten kod zasadniczo przechodzi przez ciąg znaków, aż znajdzie „\ n”. Po znalezieniu „\ n” zostanie zastąpione przez terminator znaku zerowego „\ 0”

Zauważ, że porównujesz znaki, a nie łańcuchy w tym wierszu, więc nie musisz używać strcmp ():

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

ponieważ będziesz używać pojedynczych cudzysłowów, a nie podwójnych. Oto link o pojedynczych lub podwójnych cudzysłowach, jeśli chcesz dowiedzieć się więcej


2
byłoby lepiej, jeśli wyjaśnisz i edytujesz format swojego kodu.
Anh Pham

Zwykle lepiej jest wyjaśnić rozwiązanie zamiast po prostu opublikować kilka wierszy anonimowego kodu. Możesz przeczytać Jak napisać dobrą odpowiedź , a także wyjaśnienie odpowiedzi całkowicie opartych na kodzie .
Massimiliano Kraus,

1
Przepraszam, to był mój pierwszy wkład tutaj. Naprawię to. Dzięki za opinie
Matheus Martins Jerônimo

3
Nieefektywne: for(int i = 0; i < strlen(Name); i++ )zadzwoni strlen(Name)wiele razy (zmiany w pętli Name[]), więc przy długości Njest to O(N*N)rozwiązanie. strlen(Name)Aby uzyskać rozwiązanie O (N), potrzebne jest tylko 1 połączenie z ewentualnym. Niejasne, dlaczego int istosuje się zamiast size_t i. Zastanów sięfor(size_t i = 0; i < Name[i]; i++ )
chux - Przywróć Monikę

@chux Bardziej jakfor (size_t i = 0; Name[i]; i++) { if (Name[i] == '\n') { Name[i] = '\0'; break; } }
melpomene

-1

Spróbuj tego:

        int remove_cr_lf(char *str)
        {
          int len =0;


          len = strlen(str);

          for(int i=0;i<5;i++)
          {
            if (len>0)
            if (str[len-1] == '\n')
            {
              str[len-1] = 0;
              len--;
            }

            if (len>0)
            if (str[len-1] == '\r')
            {
              str[len-1] = 0;
              len--;
            }
          }

          return 0;
        }

1
len = strlen(str)może się przepełnić: strlenzwraca size_t, a nie int. Co jest z tymi dziwnymi if (len>0) if (...)warunkami? Nie wiesz o &&? Jeśli zamierzasz usunąć wiele wystąpień CR / LF, po co ograniczać się do 5? Dlaczego nie usunąć ich wszystkich? Dlaczego funkcja ma inttyp zwracany, gdy zawsze zwraca 0? Dlaczego po prostu nie wrócić void?
melpomene
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.