Entfernen des nachgestellten Zeilenumbruchs aus der Eingabe von fgets ()

235

Ich versuche, einige Daten vom Benutzer abzurufen und an eine andere Funktion in gcc zu senden. Der Code ist ungefähr so.

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

Ich finde jedoch, dass es \nam Ende einen Zeilenumbruch hat . Wenn ich also eintrete, wird Johnes gesendet John\n. Wie entferne ich das \nund sende eine richtige Zeichenfolge.

sfactor
quelle
21
if (!fgets(Name, sizeof Name, stdin))(Verwenden Sie zumindest nicht zwei Negationen! und! =)
4
@ Roger Pate "benutze nicht zwei Negationen" -> hmmm, wenn wir tief graben, sind "nicht" und "Negation" beide Negationen . ;-). Vielleicht "Verwenden Sie if (fgets(Name, sizeof Name, stdin)) {.
chux
3
@chux, ich bin sicher, Sie meintenif (fgets(Name, sizeof Name, stdin) == NULL ) {
R Sahu
@ RSahu True : lästig !:
Chux

Antworten:

154

Der etwas hässliche Weg:

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

Der etwas seltsame Weg:

strtok(Name, "\n");

Beachten Sie, dass die strtokFunktion nicht wie erwartet funktioniert, wenn der Benutzer eine leere Zeichenfolge eingibt (dh nur die Eingabetaste drückt). Es lässt den \nCharakter intakt.

Natürlich gibt es auch andere.

Jerry Sarg
quelle
7
Jede Thread-fähige C-Laufzeitbibliothek (dh die meisten, die auf eine Multithread-Plattform abzielen) ist strtok()threadsicher (sie verwendet den lokalen Thread-Speicher für den Status zwischen Aufrufen). Trotzdem ist es im Allgemeinen immer noch besser, die nicht standardmäßige (aber häufig genug) strtok_r()Variante zu verwenden.
Michael Burr
2
Siehe meine Antwort für eine vollständig threadsichere und wiedereintrittsfähige Variante, ähnlich Ihrem strtokAnsatz (und sie funktioniert mit leeren Eingaben). In der Tat ist eine gute Möglichkeit zu implementieren strtok, strcspnund zu verwenden strspn.
Tim
2
Es ist wichtig, den Fall else zu behandeln, wenn Sie sich in einer Umgebung befinden, in der die Gefahr von zu langen Leitungen besteht. Das stille Abschneiden der Eingabe kann zu sehr schädlichen Fehlern führen.
Malcolm McLean
2
Wenn Sie Einzeiler mögen und glibc verwenden, versuchen Sie es *strchrnul(Name, '\n') = '\0';.
Twobit
Wenn strchr(Name, '\n') == NULLdann neben "Eingabe zu lang für Puffer, Flag-Fehler" andere Möglichkeiten bestehen: Der letzte Text in stdinendete nicht mit einem '\n'oder einem seltenen eingebetteten Nullzeichen.
chux
439

Vielleicht verwendet die einfachste Lösung eine meiner wenig bekannten Lieblingsfunktionen strcspn():

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

Wenn Sie möchten, dass es auch funktioniert '\r'(z. B. wenn der Stream binär ist):

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

Die Funktion zählt die Anzahl der Zeichen, bis sie a '\r'oder a trifft '\n'(mit anderen Worten, sie findet das erste '\r'oder '\n'). Wenn es nichts trifft, stoppt es bei '\0'(Rückgabe der Länge der Zeichenfolge).

Beachten Sie, dass dies auch dann gut funktioniert, wenn keine neue Zeile vorhanden ist, da strcspnbei a angehalten wird '\0'. In diesem Fall wird die gesamte Linie einfach zu ersetzen '\0'mit '\0'.

Tim Čas
quelle
30
Diese Griffe sogar die seltene bufferals beginnt mit '\0'etwas , dass Ursachen für die Trauer buffer[strlen(buffer) - 1] = '\0';Ansatz.
chux
5
@chux: Ja, ich wünschte, mehr Leute hätten davon gewusst strcspn(). Eine der nützlicheren Funktionen in der Bibliothek, IMO. Ich habe beschlossen, heute eine Reihe gängiger C-Hacks wie diesen zu schreiben und zu veröffentlichen. Eine strtok_rImplementierung mit strcspnund strspnwar eine der ersten: codepad.org/2lBkZk0w ( Warnung: Ich kann nicht garantieren, dass sie fehlerfrei ist ; sie wurde hastig geschrieben und hat wahrscheinlich einige). Ich weiß noch nicht, wo ich sie veröffentlichen werde, aber ich beabsichtige, es im Geiste der berühmten "Bit Twiddling Hacks" zu machen.
Tim
4
Es wurde nach Möglichkeiten gesucht , robust zu trimmenfgets() . Dies strcspn()scheint der einzig richtige Einzeiler zu sein. strlenist schneller - wenn auch nicht so einfach.
chux - Monica wieder einsetzen
6
@sidbushes: Die Frage, sowohl im Titel als auch im Inhalt, fragt nach der nachfolgenden Newline aus der fgets()Eingabe . Welches ist immer auch die erste Newline.
Tim am
9
@sidbushes: Ich verstehe, woher Sie kommen, kann jedoch nicht für die Google-Suchergebnisse für bestimmte Begriffe verantwortlich gemacht werden. Sprich mit Google, nicht mit mir.
Tim Čas
83
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';
James Morris
quelle
8
Wird wahrscheinlich eine Ausnahme auslösen, wenn die Zeichenfolge leer ist, nicht wahr? Wie Index außerhalb des Bereichs.
Edward Olamisan
1
@ EdwardOlamisan, die Zeichenfolge wird jedoch niemals leer sein.
James Morris
5
@ James Morris In ungewöhnlichen Fällen fgets(buf, size, ....)-> strlen(buf) == 0. 1) fgets()liest als erstes chara '\0'. 2) size == 13) gibt fgets()zurück, NULLdann kann der bufInhalt alles sein. (OPs Code size_t ln = strlen(name); if (ln > 0 && name[ln-1] == '\n') name[--ln] = '\0';
testet
2
Was ist, wenn die Zeichenfolge leer ist? lnwäre -1, außer dass die Tatsache size_tvorzeichenlos ist und somit in einen zufälligen Speicher schreibt. Ich denke, Sie möchten verwenden ssize_tund überprüfen, lnist> 0.
Abligh
2
@ legends2k: Eine Suche nach einem Wert zur Kompilierungszeit (insbesondere nach einem Nullwert wie in strlen) kann viel effizienter implementiert werden als eine einfache char-by-char-Suche. Aus diesem Grund würde ich diese Lösung besser in Betracht ziehen als eine strchroder eine strcspnbasierte.
Am
17

Im Folgenden finden Sie einen schnellen Ansatz zum Entfernen eines Potenzials '\n'aus einer von gespeicherten Zeichenfolge fgets().
Es verwendet strlen()mit 2 Tests.

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

Verwenden Sie jetzt bufferund lennach Bedarf.

Diese Methode hat den Nebeneffekt eines lenWerts für nachfolgenden Code. Es kann leicht schneller sein als strchr(Name, '\n'). Ref YMMV, aber beide Methoden funktionieren.


buffer, aus dem Original fgets()wird "\n"unter Umständen nicht enthalten :
A) Die Zeile war zu lang, bufferso dass nur charvor dem '\n'gespeichert wird buffer. Die ungelesenen Zeichen bleiben im Stream.
B) Die letzte Zeile in der Datei endete nicht mit a'\n' .

Wenn in die Eingabe '\0'irgendwo Nullzeichen eingebettet sind , enthält die von gemeldete Länge strlen()nicht die '\n'Position.


Einige andere Antworten:

  1. strtok(buffer, "\n");zu entfernen , schlägt die , '\n'wenn bufferist "\n". Aus dieser Antwort - nach dieser Antwort geändert, um vor dieser Einschränkung zu warnen.

  2. Das Folgende schlägt in seltenen Fällen fehl, wenn das erste charLesen von fgets()ist '\0'. Dies geschieht, wenn die Eingabe mit einem Embedded beginnt '\0'. Dann buffer[len -1]wird der buffer[SIZE_MAX]Zugriff auf Speicher sicherlich außerhalb des legitimen Bereichs von buffer. Etwas, das ein Hacker versuchen oder finden könnte, wenn er törichterweise UTF16-Textdateien liest. Dies war der Stand einer Antwort, als diese Antwort geschrieben wurde. Später wurde es von einem Nicht-OP so bearbeitet, dass es Code wie die Antwort dieser Antwort enthält "".

    size_t len = strlen(buffer);
    if (buffer[len - 1] == '\n') {  // FAILS when len == 0
      buffer[len -1] = '\0';
    }
  3. sprintf(buffer,"%s",buffer);ist undefiniertes Verhalten: Ref . Außerdem werden keine führenden, trennenden oder nachfolgenden Leerzeichen gespeichert. Jetzt gelöscht .

  4. [Bearbeiten aufgrund einer guten späteren Antwort ] Es gibt keine Probleme mit dem 1-Liner buffer[strcspn(buffer, "\n")] = 0;außer der Leistung im Vergleich zum strlen()Ansatz. Die Leistung beim Trimmen ist normalerweise kein Problem, da der Code E / A ausführt - ein schwarzes Loch der CPU-Zeit. Wenn der folgende Code die Länge der Zeichenfolge benötigt oder sehr leistungsbewusst ist, verwenden Sie diesen strlen()Ansatz. Sonst strcspn()ist das eine gute Alternative.

chux - Monica wieder einsetzen
quelle
Danke für die hilfreiche Antwort. Können wir verwenden, strlen(buffer)wenn die Puffergröße mithilfe von dynamisch zugewiesen wird malloc?
rrz0
@ Rrz0 buffer = malloc(allocation_size); length = strlen(buffer);ist schlecht - Daten im Speicher, auf die von gezeigt bufferwird, sind unbekannt. buffer = malloc(allocation_size_4_or_more); strcpy(buffer, "abc"); length = strlen(buffer);ist OK
chux
Danke dafür!! Ich nehme an einem CS-Kurs teil und dies war sehr hilfreich für eine der Aufgaben. Ich habe Ihre Antwort im Quellcode gutgeschrieben.
Nathaniel Hoyt
8

Direkt, um das '\ n' aus der fgets-Ausgabe zu entfernen, wenn jede Zeile '\ n' hat.

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

Andernfalls:

void remove_newline_ch(char *line)
{
    int new_line = strlen(line) -1;
    if (line[new_line] == '\n')
        line[new_line] = '\0';
}
Amitabha
quelle
1
Hinweis, es wäre sicherer zu verwenden strnlenstatt strlen.
Mike Mertsock
3
Ein Kommentar zur ersten Antwort in der verknüpften Frage lautet: "Beachten Sie, dass strlen (), strcmp () und strdup () sicher sind. Die 'n'-Alternativen bieten Ihnen zusätzliche Funktionen."
Étienne
4
@esker nein, würde es nicht. Das Einfügen von nerhöht die Sicherheit nicht auf magische Weise. In diesem Fall würde der Code tatsächlich gefährlicher. Ähnlich verhält es sich mit strncpyeiner schrecklich unsicheren Funktion. Der Beitrag, auf den Sie verlinkt haben, ist ein schlechter Rat.
MM
3
Dies schlägt für eine leere Zeichenfolge ( "") kläglich fehl . Auch strlen()kehrt size_tnicht int.
Alk
4
Dies ist für eine leere Zeichenfolge nicht sicher. Sie schreibt am Index -1. Benutze das nicht.
Jean-François Fabre
3

Für einzelnes '\ n' Trimmen,

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

für mehrfaches '\ 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';
  }
}
BEPP
quelle
1
Warum verschachteln, ifwenn Sie einfach eine Bedingung mit schreiben können &&? Diese whileSchleife hat eine seltsame Struktur; es könnte einfach sein while (length > 0 && string[length-1] == '\n') { --length; string[length] = '\0'; }.
Melpomene
@ Melpomene danke für den Vorschlag. Aktualisieren Sie den Code.
BEPP
1
Ich würde vorschlagen, dass die erste Funktion natürlicher definiert ist als : size_t length = strlen(string); if (length > 0 && string[length-1] == '\n') { string[length-1] = '\0'; }. Dies spiegelt auch die zweite Definition besser wider (nur mit ifstatt while).
Melpomene
@elpomene danke. Es ergibt Sinn. Ich habe den Code aktualisiert.
BEPP
1

Mein Neuling Weg ;-) Bitte lassen Sie mich wissen, ob das richtig ist. Es scheint für alle meine Fälle zu funktionieren:

#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;
}
Ente Ling
quelle
1

Die Schritte zum Entfernen des Zeilenumbruchs auf die vielleicht offensichtlichste Weise:

  1. Bestimmen Sie die Länge der Zeichenfolge im Inneren NAMEmithilfe der strlen()Kopfzeile string.h. Beachten Sie, dass strlen()das Beenden nicht berücksichtigt wird \0.
size_t sl = strlen(NAME);

  1. Überprüfen Sie, ob die Zeichenfolge mit einem \0Zeichen beginnt oder nur ein Zeichen enthält (leere Zeichenfolge). In diesem Fall slwäre, 0da, strlen()wie ich oben sagte, das nicht zählt \0und beim ersten Auftreten davon stoppt:
if(sl == 0)
{
   // Skip the newline replacement process.
}

  1. Überprüfen Sie, ob das letzte Zeichen der richtigen Zeichenfolge ein Zeilenumbruchzeichen ist '\n'. Wenn dies der Fall ist, ersetzen Sie \ndurch a \0. Beachten Sie, dass die Indexzählungen bei beginnen, 0sodass wir Folgendes tun müssen NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

Hinweis: Wenn Sie bei der fgets()Zeichenfolgenanforderung nur die Eingabetaste gedrückt haben (der Zeichenfolgeninhalt bestand nur aus einem Zeilenumbruchzeichen), ist die NAMEZeichenfolge danach eine leere Zeichenfolge.


  1. Wir können Schritt 2. und 3. in nur einer ifAnweisung zusammenfassen, indem wir den Logikoperator verwenden &&:
if(sl > 0 && NAME[sl - 1] == '\n')
{
   NAME[sl - 1] = '\0';
}

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

Wenn Sie eine Funktion zur Verwendung dieser Technik fgetsbevorzugen , indem Sie Ausgabezeichenfolgen im Allgemeinen verarbeiten, ohne sie jedes Mal neu einzugeben, finden Sie hier 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';
    }
}

In Ihrem Beispiel wäre dies:

printf("Enter your Name: ");

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

Beachten Sie, dass diese Methode nicht funktioniert, wenn in die Eingabezeichenfolge \0s eingebettet ist. Wenn dies der Fall strlen()wäre, würde nur die Anzahl der Zeichen bis zum ersten zurückgegeben \0. Dies ist jedoch kein gängiger Ansatz, da die meisten Funktionen zum Lesen von Zeichenfolgen normalerweise beim ersten anhalten \0und die Zeichenfolge bis zu diesem Nullzeichen verwenden.

Abgesehen von der Frage für sich. Vermeiden Sie doppelte Negationen, die Ihren Code unklar machen : if (!(fgets(Name, sizeof Name, stdin) != NULL) {}. Sie können einfach tun if (fgets(Name, sizeof Name, stdin) == NULL) {}.

RobertS unterstützt Monica Cellio
quelle
Ich bin mir nicht sicher, warum Sie das tun möchten. Beim Entfernen von Zeilenumbrüchen geht es nicht darum, Zeichenfolgen mit Null zu beenden. es ist, Zeilenumbrüche zu entfernen. Das Ersetzen von a \ndurch a \0am Ende einer Zeichenfolge ist eine Möglichkeit, die neue Zeile zu "entfernen". Das Ersetzen von \nZeichen innerhalb einer Zeichenfolge ändert die Zeichenfolge jedoch grundlegend. Es ist nicht ungewöhnlich, Zeichenfolgen mit absichtlich mehreren Zeilenumbrüchen zu haben, und dies würde die Enden dieser Zeichenfolgen effektiv abschneiden. Um solche Zeilenumbrüche zu entfernen , muss der Array-Inhalt nach links verschoben werden, um das zu überschreiben \n.
ex nihilo
@exnihilo Wie kann jemand mithilfe von eine Zeichenfolge mit mehreren Zeilenumbrüchen eingeben fgets()?
RobertS unterstützt Monica Cellio
Nun, Sie könnten Zeichenfolgen verketten, die durch mehrere Aufrufe von erhalten wurden fgets(). Aber ich verstehe Ihren Einwand nicht: Sie sind derjenige, der Code für die Behandlung mehrerer Zeilenumbrüche vorschlägt.
ex nihilo
@exnihilo Du hast recht, ich werde die Strategie überdenken. Ich wollte nur einen sehr harten, aber möglichen Weg hinzufügen, um das gewünschte Ergebnis zu erzielen.
RobertS unterstützt Monica Cellio
@exnihilo Ich habe meine Antwort vollständig bearbeitet und bin dem Hauptansatz gefolgt, indem ich strlenusw. verwendet habe. Begründung dafür, dass es sich nicht um ein Duplikat handelt: 1. Erläuterung des Codes in Schritten. 2. Wird als funktions- und kontextbasierte Lösung bereitgestellt. 3. Hinweis, um doppelte Negationsausdrücke zu vermeiden.
RobertS unterstützt Monica Cellio
0

Tim Čas ein Liner ist erstaunlich für Strings, die durch einen Aufruf von fgets erhalten werden, weil Sie wissen, dass sie am Ende eine einzelne Newline enthalten.

Wenn Sie sich in einem anderen Kontext befinden und Zeichenfolgen verarbeiten möchten, die möglicherweise mehr als eine neue Zeile enthalten, suchen Sie möglicherweise nach strrspn. Es ist nicht POSIX, was bedeutet, dass Sie es nicht auf allen Unices finden. Ich habe eine für meine eigenen Bedürfnisse geschrieben.

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

Für diejenigen, die nach einem Perl-Chomp-Äquivalent in C suchen, ist dies meiner Meinung nach das Richtige (Chomp entfernt nur die nachfolgende Newline).

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

Die strrcspn-Funktion:

/* 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;
}
Philippe A.
quelle
1
"weil du weißt, dass sie am Ende eine einzige neue Zeile enthalten." -> Es funktioniert sogar, wenn es keine gibt '\n'(oder wenn die Zeichenfolge ist "").
chux
Als Antwort auf Ihren ersten Kommentar chux, meine Antwort bewahrt das. Ich musste Resetlen einwerfen, strrcspnwenn es keine gibt \n.
Philippe A.
Warum goto end;statt verwenden return len;?
Chqrlie
@chqrlie Ich musste aus dieser uneleganten 2-Level-Schleife herauskommen, in die ich geraten bin. Der Schaden wurde angerichtet. Warum nicht ein Goto?
Philippe A.
Sie haben zwei Arten von gotos in Ihrem Code: eine nutzlose goto, die durch eine returnAnweisung ersetzt werden kann, und eine rückwärts goto, die als böse angesehen wird. Die Verwendung strchrhilft bei der Implementierung strrspnund strrcspnauf einfachere Weise: 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; }undsize_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

Wenn die Verwendung getlineeine Option ist - ohne die Sicherheitsprobleme zu vernachlässigen und Zeiger zu klammern -, können Sie Zeichenfolgenfunktionen vermeiden, da getlinedie Anzahl der Zeichen zurückgegeben wird. So etwas wie unten

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

Hinweis : Die [ Sicherheitsprobleme ] mit getlinesollten jedoch nicht vernachlässigt werden.

sjsam
quelle
-1

Die folgende Funktion ist Teil der String-Verarbeitungsbibliothek, die ich auf Github verwalte. Es entfernt und unerwünschte Zeichen aus einer Zeichenfolge, genau das, was Sie wollen

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

Ein Beispiel für eine Verwendung könnte sein

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

Vielleicht möchten Sie andere verfügbare Funktionen überprüfen oder sogar zum Projekt beitragen :) https://github.com/fnoyanisi/zString

fnisi
quelle
Sie sollten das *in entfernen *src++;und machen bad, tokenund d const char *. Auch warum nicht strchrstatt verwenden zChrSearch? *srckann nicht '\0'in deiner zStrrmvFunktion sein.
Chqrlie
Danke @chqrlie! Der Code wurde aktualisiert, um Ihre Vorschläge widerzuspiegeln ..... zstring wurde als unterhaltsames Projekt mit dem Ziel gestartet, eine String-Manipulationsbibliothek ohne Verwendung von Standardbibliotheksfunktionen zu erstellen. Daher habe ichstrchr
fnisi
1
Das Schreiben einer " String-Manipulationsbibliothek ohne Verwendung von Standardbibliotheksfunktionen " ist eine nette Übung, aber warum sollten Sie anderen Leuten sagen, dass sie sie verwenden sollen? Wenn überhaupt, wird es langsamer und weniger getestet als jede Standardbibliothek.
Melpomene
Dies macht einen anderen Job als die Frage. Es kann wahrscheinlich verwendet werden, um die einzige Newline loszuwerden, aber es fühlt sich wie ein Overkill an.
Jonathan Leffler
-1
 for(int i = 0; i < strlen(Name); i++ )
{
    if(Name[i] == '\n') Name[i] = '\0';
}

Sie sollten es versuchen. Dieser Code durchläuft im Grunde die Zeichenfolge, bis er das '\ n' findet. Wenn es gefunden wird, wird das '\ n' durch den Nullzeichen-Terminator '\ 0' ersetzt.

Beachten Sie, dass Sie Zeichen und keine Zeichenfolgen in dieser Zeile vergleichen. Dann müssen Sie strcmp () nicht verwenden:

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

da Sie einfache Anführungszeichen und keine doppelten Anführungszeichen verwenden. Hier ist ein Link zu einfachen oder doppelten Anführungszeichen, wenn Sie mehr wissen möchten

Matheus Martins Jerônimo
quelle
2
Es ist besser, wenn Sie das Format Ihres Codes erklären und bearbeiten.
Anh Pham
Normalerweise ist es besser, eine Lösung zu erklären, als nur einige Zeilen anonymen Codes zu veröffentlichen. Sie können lesen, wie ich eine gute Antwort schreibe und wie Sie vollständig codebasierte Antworten erklären .
Massimiliano Kraus
1
Es tut mir leid, dass dies mein erster Beitrag hier war. Ich werde es reparieren. Vielen Dank für das Feedback
Matheus Martins Jerônimo
3
Ineffizient: for(int i = 0; i < strlen(Name); i++ )Wird strlen(Name)viele Male aufgerufen (Schleifenänderungen Name[]). Mit einer Länge Nist dies eine O(N*N)Lösung. Es ist nur ein Anruf strlen(Name)erforderlich, um eine O (N) -Lösung bereitzustellen. Unklar, warum int istatt verwendet wird size_t i. Betrachten Siefor(size_t i = 0; i < Name[i]; i++ )
chux
@chux Mehr wiefor (size_t i = 0; Name[i]; i++) { if (Name[i] == '\n') { Name[i] = '\0'; break; } }
Melpomene
-1

Probier diese:

        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;
        }
Balazs Kuss
quelle
1
len = strlen(str)kann überlaufen: strlenkehrt zurück size_t, nicht int. Was ist mit den seltsamen if (len>0) if (...)Bedingungen? Weißt du nichts davon &&? Wenn Sie mehrere nachfolgende Instanzen von CR / LF entfernen möchten, warum sollten Sie sich auf 5 beschränken? Warum nicht alle entfernen? Warum hat die Funktion einen intRückgabetyp, wenn sie immer zurückgibt 0? Warum nicht einfach zurückkehren void?
Melpomene