Ich möchte sicherstellen, dass meine Zeichenfolge mit “.foo” endet. Ich benutze C, eine Sprache, mit der ich nicht ganz vertraut bin. Der beste Weg, den ich gefunden habe, ist unten. Irgendwelche C-Gurus wollen sicherstellen, dass ich das elegant und klug mache?
BEARBEITEN: NULL-Prüfung für die Umständlichkeit hinzugefügt. Für die Ultra-Pedantisten, diskutieren Sie, ob es ungleich Null zurückgeben sollte, wenn sowohl str als auch suffix beide NULL sind.
In diesem Fall können Sie strcmp() anstelle von strncmp() (oder sogar memcmp()) verwenden, da wir zu diesem Zeitpunkt genau wissen, wie viele Zeichen in beiden Strings noch übrig sind, obwohl der Geschwindigkeitsunterschied kaum wahrnehmbar ist .
– Adam Rosenfield
13. April 2009 um 18:23 Uhr
jeder Aufruf von strlen verschwindet sowieso aus der Assembly, sobald Sie Optimierungen einschalten, also ist das wahrscheinlich ein Fall von vorzeitiger Optimierung (obwohl C-Strings eklig genug sind, um über solche Probleme nachzudenken).
– Joey
13. April 2009 um 18:37 Uhr
@Johannes: Wie kann das für andere Zeichenfolgen als zur Kompilierzeit bekannte Zeichenfolgenliterale sein? Sicherlich können Sie den strlen-Code einbetten, aber auf einer bestimmten Ebene müssen Sie immer noch die Länge der Zeichenfolge finden. Bei konstanten Zeichenfolgenliteralen weiß der Compiler, wie lang es ist, aber das gilt im Allgemeinen nicht. Gedanken?
– Matt J
13. April 2009 um 19:20 Uhr
Wenn !str && !suffix, wäre es nicht sinnvoller, 1 zurückzugeben?
– wilhelmtel
14. April 2009 um 19:18 Uhr
@MattJ: etwas spät …, aber ich nehme an, Adam meinte, dass der Compiler alle Aufrufe außer dem ersten für jede Zeichenfolge entfernen wird, da sie nicht geändert werden. da hast du natürlich recht nicht alle davon können wegoptimiert werden.
Rückgabewerte sollten umgekehrt werden, da Null falsch und Nicht-Null wahr ist und der Name der Funktion auf eine boolesche Rückgabe hinweist.
– Traumlax
14. April 2009 um 0:17 Uhr
@dreamlax -> ja, das stimmt
– Benutzer82238
14. April 2009 um 6:34 Uhr
@Eichhörnchen strcmp prüft beide Strings auf das Null-Terminatorzeichen. Wenn eine Zeichenfolge kürzer als die andere ist, wird sie einen Wert ungleich Null zurückgeben. Es wird nicht überlesen.
– cgmb
15. November 2019 um 0:49 Uhr
Die Verwendung der Variablen “string” scheint mir keine gute Idee zu sein, da sie mit std::string in c++ kollidieren kann. Ich bin mir nicht sicher, wie gut der Compiler das kann, aber ich würde auch die Verwendung von const char * empfehlen. Also wird es int EndsWithFoo(const char *s1 ) { const char * s2 = strrchr(s1, ‘.’); …. und jetzt alles mit s2 weiter.
– Tõnu Samuel
27. Oktober 2020 um 10:37 Uhr
Ich habe gerade keinen Zugriff auf einen Compiler, könnte mir also jemand sagen, ob das funktioniert?
#include <stdio.h>
#include <string.h>
int EndsWithFoo(const char* s);
int
main(void)
{
printf("%d\n", EndsWithFoo("whatever.foo"));
return 0;
}
int EndsWithFoo(const char* s)
{
int ret = 0;
if (s != NULL)
{
size_t size = strlen(s);
if (size >= 4 &&
s[size-4] == '.' &&
s[size-3] == 'f' &&
s[size-2] == 'o' &&
s[size-1] == 'o')
{
ret = 1;
}
}
return ret;
}
Achten Sie auf jeden Fall darauf, den Parameter als zu qualifizieren constteilt es allen (einschließlich dem Compiler) mit, dass Sie nicht beabsichtigen, die Zeichenfolge zu ändern.
+1 am besten optimiert. Ich bevorzuge eine solche Version, wenn sich ‘foo’ nicht ändert!
– dirkgent
13. April 2009 um 18:07 Uhr
Nur ein Tipp: Wenn Sie eine Internetverbindung haben, steht Ihnen auf codepad.org ein C-Compiler zur Verfügung
– John Cromartie
13. April 2009 um 18:10 Uhr
Murphy’s Law besagt, dass “.foo” sich ändern wird und zwar im ungünstigsten Moment.
– Sockel
13. April 2009 um 18:16 Uhr
Es ist nicht “optimiert”, da Sie den .foo-Teil zweimal durchlesen – einmal für strlen, einmal zum Vergleich. Aber gut und praktisch. +1
– Aib
13. April 2009 um 21:41 Uhr
Ich bin mir ziemlich sicher, dass eine Standardversion mit einer Schleife und const char * sowieso mit -O3 auf so etwas optimiert werden würde.
– Samuel Danielson
28. Januar 2016 um 23:28 Uhr
Hier ist eine allgemeine Lösung, die dieselben Werte wie Pythons str.endswith() zurückgibt, wobei memcmp() verwendet wird. Es ist beabsichtigt, str / suffix nicht auf NULL zu prüfen, andere libc str-Funktionen prüfen ebenfalls nicht auf NULL:
Wenn Sie die Signatur Ihrer Funktion ändern können, ändern Sie sie in
int EndsWith(char const * str, char const * suffix, int lenstr, int lensuf);
Dies führt zu einem sichereren, wiederverwendbaren und effizienteren Code:
Die hinzugefügten konstanten Qualifizierer stellen sicher, dass Sie die Eingabezeichenfolgen nicht versehentlich ändern. Diese Funktion ist ein Prädikat, daher gehe ich davon aus, dass sie niemals Nebenwirkungen haben soll.
Das zu vergleichende Suffix wird als Parameter übergeben, sodass Sie diese Funktion zur späteren Wiederverwendung mit anderen Suffixen speichern können.
Diese Signatur gibt Ihnen die Möglichkeit, die Längen der Saiten anzugeben, wenn Sie sie bereits kennen. Wir nennen das dynamische Programmierung.
Das offensichtliche Gegenargument für die zusätzlichen Parameter ist, dass sie mehr Rauschen im Code oder einen weniger ausdrucksstarken Code implizieren.
Ihr Code hat undefiniertes Verhalten, wenn lenstr < lensufob als Argumentwerte oder wie berechnet mit strlen(). Ein weiteres Gegenargument ist int hat einen kleineren positiven Bereich als size_t.
– chqrlie
16. August 2021 um 17:08 Uhr
Das strlen(".foo")s sind nicht erforderlich. Wenn Sie es wirklich flexibel haben wollten, könnten Sie es verwenden sizeof ".foo" - 1 — eine Kompilierzeitkonstante.
Auch eine Null-String-Prüfung wäre gut.
Ihr Code hat undefiniertes Verhalten, wenn lenstr < lensufob als Argumentwerte oder wie berechnet mit strlen(). Ein weiteres Gegenargument ist int hat einen kleineren positiven Bereich als size_t.
– chqrlie
16. August 2021 um 17:08 Uhr
Getesteter Code, beinhaltet den Test:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int ends_with_foo(const char *str)
{
char *dot = strrchr(str, '.');
if (NULL == dot) return 0;
return strcmp(dot, ".foo") == 0;
}
int main (int argc, const char * argv[])
{
char *test[] = { "something", "anotherthing.foo" };
int i;
for (i = 0; i < sizeof(test) / sizeof(char *); i++) {
printf("'%s' ends %sin '.foo'\n",
test[i],
ends_with_foo(test[i]) ? "" : "not ");
}
return 0;
}
Schnapp! Obwohl ich mir nicht die Mühe mache, das Ergebnis von strcmp () zu vergleichen, gebe ich es einfach direkt zurück.
– Benutzer82238
13. April 2009 um 18:26 Uhr
Sie gehen davon aus, dass es kein anderes ‘.’ in der Eingabezeichenfolge.
– Naveen
13. April 2009 um 18:50 Uhr
Es macht keinen Unterschied. strcmp() gibt nur dann 0 zurück, wenn es zwei identische Strings gibt (zB die Länge muss gleich sein). Der Vergleich wird vorzeitig beendet, wenn sich die Zeichenfolgen in der Länge unterscheiden.
– Benutzer82238
13. April 2009 um 19:05 Uhr
@Blank Xavier: Die Version in der Frage gibt 1 zurück, wenn sie mit “.foo” endet. Nur das Ergebnis von strcmp() zurückzugeben, würde bei Erfolg 0 zurückgeben.
– stesch
13. April 2009 um 19:12 Uhr
@Naveen: strrchr() gibt das letzte Vorkommen des gesuchten Zeichens zurück.
– stesch
13. April 2009 um 19:15 Uhr
14115400cookie-checkWie vergleicht man die Enden von Strings in C?yes
25 Antworten, nur 4 oder 5 ohne Probleme.
– chqrlie
16. August 2021 um 17:31 Uhr