“ String ” enthält Funktion in C

Diese Funktion prüft ob eine Teilzeichenfolge needle in einer anderen Zeichenfolge haystack vorhanden ist oder nicht, und gibt die Position zurück, wenn dies der Fall ist, oder 0, wenn dies nicht der Fall ist, es sei denn, die Die Position ist 0. In diesem Fall wird sie nicht gefunden.

Suche nach Möglichkeiten zur Verbesserung dieses Codes, insbesondere nach einer besseren Fehlerbehandlung.

#include <stdio.h> #include <stdlib.h> #include <string.h> size_t contains(const char * needle, const char *haystack); int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; printf("Position: %lu", contains(needle, haystack)); return EXIT_SUCCESS; } size_t contains(const char * needle, const char *haystack) { if(needle == NULL || haystack == NULL) { return 0; } long int first_char_pos = -1; size_t len_h = strlen(haystack); size_t len_n = strlen(needle); size_t i, j; size_t exist_count = 0; // Find the first character. If it doesn"t exist, we"re done. for(i = 0; i < len_h; i++) { if((haystack[i] == needle[0]) && (first_char_pos == -1)) { first_char_pos = i; exist_count++; } } if(first_char_pos == -1) { return 0; } printf("First char match index: %li\n", first_char_pos); printf("Char: %c\n", haystack[first_char_pos]); size_t current_index = (size_t) first_char_pos; for(i = first_char_pos; i < len_h; i++) { if(haystack[i] == needle[exist_count] && (i == (current_index + 1))) { current_index = i; exist_count++; } printf("Exist count: %lu\n", exist_count); //<--Debugging if(exist_count == len_n) { return first_char_pos; } } return 0; } 

Kommentare

  • Bitte fügen Sie einige Beispiele hinzu, um genau zu zeigen, was Sie damit meinen, dass “ . Ich bezweifle, dass Ihr Code wie beabsichtigt funktioniert.
  • Dies existiert bereits: strstr(). Es gibt ‚ eine sicherere Version namens strnstr(). Eine Implementierung finden Sie hier: github.com/lattera/freebsd/blob/master/lib/libc/string/…
  • @RolandIllig: Warum können Sie das erklären?
  • Sollte contains("tt", "test") true zurückgeben?
  • @ CacahueteFrito Sie zahlen also nicht unerhebliche Kosten für die Benutzerfreundlichkeit und , um Datenbeschädigungen in seltenen Fällen zu maskieren, anstatt sich auf die Invarianten Ihrer Programme zu verlassen, die Daten zu patchen oder den Fehler zu melden? Das scheint eine schlechte Idee zu sein.

Antwort

Nur ein paar Bemerkungen:

  • Sie sollten nach der letzten Zeile eine neue Zeile einfügen:

     $ ./nh First char match index: 18 Char: t Exist count: 1 Exist count: 2 Exist count: 3 Exist count: 4 Position: 18 $ 
  • Ich weiß nicht was Compiler, den Sie verwenden, aber beim Kompilieren mit gcc und -Wall -Wextra -pedantic erhalten Sie:

    gcc -O2 nh.c -lm -o nh -Wall -Wextra -pedantic nh.c: In function ‘contains’: nh.c:25:15: warning: unused variable ‘j’ [-Wunused-variable] size_t i, j; ^ 
  • Die Codeformatierung sollte konsistenter sein. In dieser Zeile setzen Sie beispielsweise ein Leerzeichen vor needle, aber kein Leerzeichen vor haystack:

    size_t contains(const char * needle, const char *haystack); 
  • %lu ist kein portabler Bezeichner für den Typ size_t. Sie sollten %zu verwenden, das in C99 eingeführt wurde.

  • Sie sagten:

gibt die Position zurück, wenn dies der Fall ist, oder 0, wenn dies nicht der Fall ist, es sei denn, die Die Position ist 0. In diesem Fall wird sie nicht gefunden.

as ist wirklich nicht gut. Damit wird beispielsweise 0 zurückgegeben:

char *needle = "This"; char *haystack = "This is a dinosaurtest."; 

Damit wird auch Null zurückgegeben:

char *needle = "non-existent"; char *haystack = "This is a dinosaurtest."; 

In diesen beiden Beispielen können Sie den Unterschied zwischen Erfolg und Misserfolg nicht erkennen. Tatsächlich hat atoi() das gleiche Problem. Ich weiß nicht, welches Betriebssystem Sie verwenden Aber vielleicht könnten Sie ssize_t als Rückgabetyp verwenden, wenn es verfügbar ist, und im Fehlerfall -1 zurückgeben.

Antwort

Hinzufügen zur vorherigen Antwort von @Arkadiusz Drabczyk:

Eine einfache, triviale Implementierung von contains könnte sein Gehen Sie dazu wie folgt vor:

ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } 

Dann sollte dieses Programm (mit einigen Änderungen wie oben erwähnt) funktionieren:

#include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> ssize_t contains(const char * needle, const char *haystack) { char *needle_in_haystack; if(!needle || !haystack) return -1; needle_in_haystack = strstr(haystack, needle); return needle_in_haystack ? needle_in_haystack - haystack : -1; } int main(void) { char *needle = "test"; char *haystack = "This is a dinosaurtest."; char *haystack2 = "This does not contain the string."; printf("Position: %zd\n", contains(needle, haystack)); printf("Position: %zd\n", contains(needle, haystack2)); return EXIT_SUCCESS; } 

Ausgabe:

Position: 18
Position: -1

Kommentare

  • Ich würde die Überprüfung entfernen, dass die Eingabe nicht NULL ist, und ju Verwenden Sie dazu eine Spracherweiterung (__attribute__((nonnull)) in GCC). NULL ist etwas, das Sie als Eingabe für diese Funktion niemals erwarten würden, und es werden ein oder zwei unnötige Codezeilen hinzugefügt. Ich würde es vorziehen, in die Dokumentation der Funktion Folgendes zu schreiben: “ Wenn die Eingabe für diese Funktion ein NULL-Zeiger ist, ist das Verhalten undefiniert. „.
  • @CacahueteFrito Der ursprüngliche Code hat es getan, und ich möchte nach Kompatibilität streben (wer weiß, wie das OP es verwendet hat?).
  • Fehlendes Include für ssize_t: #include <sys/types.h>. Eine andere Möglichkeit wäre, stattdessen ptrdiff_t von #include <stddef.h> zu verwenden. Sie geben tatsächlich einen Zeigerunterschied zurück: ? needle_in_haystack - haystack :

Antwort

Ihr Code funktioniert nicht. Er gibt 0 für haystack "abbc" und needle "bc", obwohl haystack needle enthält .

Antwort

Sie benötigen nicht die erste Schleife und alle Längenberechnungen. Übrigens ist die Funktion nicht erfolgreich, wenn das erste Zeichen gefunden wird, aber nur das zweite Vorkommen des ersten Zeichens mit der Nadel übereinstimmt.

Die Aufgabe kann auf einige Zeilen reduziert werden:

int contains(char *buf, char *needle) { char *src, *srch, *srcp; for(src=buf; *src; src++) { for(srch = needle, srcp = src; *srch && *srcp && *srch == *srcp; srch++, srcp++); if(!*srch) return src - buf; } return -1; } 

Kommentare

  • Was ist ein guter Weg, um kompakteren, effizienteren C-Code wie diesen besser zu schreiben ?Diese Art erinnert mich an K & R C.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.