#include <stdio.h>
#include <string.h>
#include <ctype.h>
void delspace(char *str);
int main() {
int i, loops;
char s1[101], s2[101];
scanf("%d", &loops);
while (loops--) {
fgets(s1, 101, stdin);
fgets(s2, 101, stdin);
s1[strlen(s1)] = '\0';
s2[strlen(s2)] = '\0';
if (s1[0] == '\n' && s2[0] == '\n') {
printf("YES\n");
continue;
}
delspace(s1);
delspace(s2);
for (i = 0; s1[i] != '\0'; i++)
s1[i] = tolower(s1[i]);
for (i = 0; s2[i] != '\0'; i++)
s2[i] = tolower(s2[i]);
if (strcmp(s1, s2) == 0) {
printf("YES\n");
}
else {
printf("NO\n");
}
}
return 0;
}
void delspace(char* str) {
int i = 0;
int j = 0;
char sTmp[strlen(str)];
while (str[i++] != '\0') {
if (str[i] != ' ') {
sTmp[j++] = str[i];
}
}
sTmp[j] = '\0';
strcpy(str, sTmp);
}
Nachdem ich “loops” eingegeben habe, wurde “s1” automatisch eine Leerzeile zugewiesen. Wie passiert es? Ich bin mir sicher, dass meine Tastatur einwandfrei funktioniert.
“Ich bin sicher, meine Tastatur funktioniert gut.” Lol!
– orlp
6. Mai 2011 um 23:38 Uhr
Eine Variante dieser Frage scheint hier jeden Tag oder so gestellt zu werden.
– Jim Balter
7. Mai 2011 um 0:10 Uhr
Die Funktion delspace ist definitiv falsch! Dies wird konvertieren abc\0 zu bc\0.
– TrueY
17. Februar 2016 um 23:29 Uhr
Faustregel: Bei interaktiven Eingaben immer lesen Linien.
– Karoly Horvath
3. September 2016 um 11:06 Uhr
Siehe auch: stackoverflow.com/questions/5240789/…
– Melpomen
1. Oktober 2019 um 17:54 Uhr
scanf() liest genau das, worum Sie es gebeten haben, und hinterlässt das Folgende \n vom Ende dieser Zeile im Puffer wo fgets() werde es lesen. Entweder etwas tun, um den Zeilenumbruch zu verbrauchen, oder (meine bevorzugte Lösung) fgets() und dann sscanf() aus dieser Saite.
Wenn ich verwenden möchte scanf(), wie kann ich die neue Leitung konsumieren? Vielen Dank.
– Vain
6. Mai 2011 um 23:59 Uhr
Verwenden Sie so etwas wie %*[^\n]%*c am Ende des Formats, um alle Zeichen bis zum Zeilenumbruch zu überspringen, gefolgt vom Zeilenumbruch selbst.
– Geekosaurier
7. Mai 2011 um 0:07 Uhr
@geekosaur: Nur heften %*[^\n]%*c an das Ende des Formats funktioniert nicht wirklich, wenn nach dem vorherigen gelesenen Ding und vor dem Zeilenumbruch KEINE Zeichen stehen, wie dann das %*[^\n] wird nicht übereinstimmen, so dass die %*c wird übersprungen und der Zeilenumbruch bleibt bei der Eingabe. Sie müssen das tun %*c in einem separaten Scanf-Aufruf, damit es funktioniert.
– Chris Dodd
16. Mai 2016 um 1:59 Uhr
Umarmung
scanf hinterlässt Leerzeichen im Eingabepuffer, einschließlich Zeilenumbruchzeichen. Um fgets zum Lesen der nächsten Zeile zu verwenden, müssen Sie den Rest der aktuellen Zeile manuell entfernen:
int c;
do{
c = getchar();
}while(c != EOF && c != '\n');
Ja, das wird auch funktionieren, aber ich persönlich verwende nur fgets und dann sscanf (wie von geekosaur vorgeschlagen), weil es “einheitlich” für alle Arten von Daten funktioniert … nicht nur für einzelne Zeichen. Und ich mag “generische Mehrzwecklösungen”. Prost. Keith.
– corlettk
7. Mai 2011 um 0:32 Uhr
Dies funktioniert jedoch für mehr als einen Charakter – dafür ist die Schleife da;)
– Umarmung
7. Mai 2011 um 1:22 Uhr
while(c != EOF && c != '\n'); ist nicht gut. c ist außerhalb des Geltungsbereichs.
– chux – Wiedereinsetzung von Monica
23. Februar 2018 um 0:50 Uhr
Ich wollte mich entschuldigen, indem ich sagte, dass ich C- und Lua-Scoping-Regeln gemischt haben muss, aber anscheinend stammt diese Antwort, bevor ich Lua gelernt habe, hahaha.
– Umarmung
23. Februar 2018 um 2:45 Uhr
Shubham Pawar
Dies ist eine einfachere Lösung
scanf("%d",&loops);
while ((getchar()) != '\n'); //This will consume the '\n' char
//now you're free to use fgets
fgets(string,sizeof(string),stdin);
corlettk
Geekosaur hat Ihre Frage gut beantwortet, ich weise nur auf ein anderes “Problem” mit Ihrem Code hin.
Die Linie s1[strlen(s1)] = '\0'; ist ein no-op wenn s1 ist bereits richtig nullterminiert, BEVOR es ausgeführt wird.
Doch wenn s1 NICHT bereits ordnungsgemäß nullterminiert ist, BEVOR diese Zeile ausgeführt wird (und Sie Pech haben), wird dies Folgendes verursachen:
Das ist weil strlen findet im Grunde den Index der vorhandener Nullterminator und gibt es zurück! Hier ist eine gültige, nicht optimierte Implementierung von strlen:
int strlen(char *string) {
int i = 0;
while(string[i] != '\0') {
++i;
}
return i;
}
Also … Wenn Sie WIRKLICH besorgt sind, dass Strings NICHT nullterminiert sind, dann würden Sie so etwas tun:
string[sizeof(string)]='\0'; an lokal automatische Zeichenfolgen (wobei der Compiler die Größe der Zeichenfolge „kennt“);
oder string[SIZE_OF_STRING] für alle anderen Saiten, wo SIZE_OF_STRING ist (am häufigsten) a #define‘d-Konstante oder eine Variable, die Sie speziell pflegen, um die aktuelle Größe (nicht die Länge) einer dynamisch zugewiesenen Zeichenfolge zu speichern.
Und wenn Sie WIRKLICH, WIRKLICH, WIRKLICH besorgt sind, dass Zeichenfolgen nicht nullterminiert sind (als ob Sie es mit “schmutzigen” Bibliotheksmethoden (wie zum Beispiel ATMI von Tuxedo) zu tun haben) Sie AUCH “löschen” Sie Ihre “Rückgabezeichenfolgen”, bevor Sie sie an die verdächtigen Bibliotheksmethoden übergeben, mit:
Vor:memset(string, NULL, SIZE_OF_STRING);
aufrufen: DirtyFunction(/*out*/string);
nach: string[SIZE_OF_STRING]='\0'
SIG11’s sind ein komplettes Biatch zu finden, weil (es sei denn, Sie “haken” sie mit einem Signalprozessor und anders sagen, sie veranlassen Unix, Ihr Programm hart zu beenden, sodass Sie (im Nachhinein) nichts protokollieren können, um herauszufinden, woher zum Teufel das kam … besonders wenn man bedenkt dass in vielen Fällen die Codezeile, die das SIG11 auslöst, bei weitem nicht die eigentliche Ursache dafür ist, dass die Zeichenfolge ihren Nullterminator verliert.
Macht das für Sie Sinn?
PS: ACHTUNG: strncpy beendet NICHT immer null … Sie meinten wahrscheinlich strlcpy stattdessen. Ich habe das auf die harte Tour gelernt … als ein 60-Millionen-Dollar-Abrechnungslauf zusammenbrach.
BEARBEITEN:
FYI: Hier ist eine “sichere” (nicht optimierte) Version von strlen, die ich aufrufen werde strnlen (Ich denke, das sollte drin sein string.h. Seufzen.).
// retuns the length of the string (capped at size-1)
int strnlen(char *string, int size) {
int i = 0;
while( i<size && string[i]!='\0' ) {
++i;
}
return i;
}
phantom_ab
einfach setzen scanf("%d\n",&loops);
Anstatt von scanf("%d",&loops);
Während diese Antwort ein wichtiges Phänomen des ursprünglichen Problems abdeckt, bietet sie keinen Einblick in das Problem selbst. Daher ist es bestenfalls hilfreich, um das ursprüngliche Problem zu ermitteln, und auf lange Sicht nicht wirklich hilfreich. Bitte fügen Sie weitere Erklärungen hinzu, damit Ihre Antwort für spätere Leser hilfreich ist, die nach ähnlichen Problemen suchen.
– rpi
12. September 2016 um 13:48 Uhr
Fügen Sie keine abschließenden Leerzeichen am Ende von a ein scanf() format string – es unterbricht die UI/UX vollständig, da die Eingabe nicht aufhört, bis Sie etwas anderes als Leerzeichen eingeben (und Zeilenumbrüche sind Leerzeichen). Das bedeutet, dass der Benutzer vorhersagen muss, was die nächste Eingabe sein muss. Sehen [What is the effect of trailing white space in a scanf() format string?](stackoverflow.com/q/19499060/10ths 5168)
– Jonathan Leffler
8. Januar um 15:22 Uhr
ChandanK
Eine andere Möglichkeit, das folgende Zeilenumbruchzeichen (aufgrund des Drückens der EINGABETASTE) nach dem Scannen der Ganzzahl in variablen Label-Schleifen zu ignorieren, ist:
scanf ("%d%*c", &loops);
Wo, gemäß den Manpages:
* Unterdrückt die Zuweisung. Die folgende Konvertierung erfolgt wie gewohnt, es wird jedoch kein Zeiger verwendet; das Ergebnis der Konvertierung wird einfach verworfen.
Dies ist sehr unwahrscheinlich, aber eine gute Angewohnheit, während scanf nach Fehlern zu suchen:
errno = 0
scanf ("%d%*c", &loops);
if (errno != 0) perror ("scanf");
// act accordingly to avoid un-necessary bug in the code
In Ihrem Code ist loops beispielsweise eine lokale, nicht initialisierte Variable, die Datenmüll enthält. Wenn scanf den gewünschten Wert nicht füllt, kann die folgende While-Schleife willkürlich ausgeführt werden.
Während diese Antwort ein wichtiges Phänomen des ursprünglichen Problems abdeckt, bietet sie keinen Einblick in das Problem selbst. Daher ist es bestenfalls hilfreich, um das ursprüngliche Problem zu ermitteln, und auf lange Sicht nicht wirklich hilfreich. Bitte fügen Sie weitere Erklärungen hinzu, damit Ihre Antwort für spätere Leser hilfreich ist, die nach ähnlichen Problemen suchen.
– rpi
12. September 2016 um 13:48 Uhr
Fügen Sie keine abschließenden Leerzeichen am Ende von a ein scanf() format string – es unterbricht die UI/UX vollständig, da die Eingabe nicht aufhört, bis Sie etwas anderes als Leerzeichen eingeben (und Zeilenumbrüche sind Leerzeichen). Das bedeutet, dass der Benutzer vorhersagen muss, was die nächste Eingabe sein muss. Sehen [What is the effect of trailing white space in a scanf() format string?](stackoverflow.com/q/19499060/10ths 5168)
– Jonathan Leffler
8. Januar um 15:22 Uhr
scanf() Lassen Sie das folgende \n vom Ende dieser Zeile im Puffer wo fgets() werde es lesen. Um dies zu verlangsamen, müssen wir etwas tun, um den Zeilenumbruch zu verbrauchen. Sehen wir uns das Problem an.
“Ich bin sicher, meine Tastatur funktioniert gut.” Lol!
– orlp
6. Mai 2011 um 23:38 Uhr
Eine Variante dieser Frage scheint hier jeden Tag oder so gestellt zu werden.
– Jim Balter
7. Mai 2011 um 0:10 Uhr
Die Funktion
delspace
ist definitiv falsch! Dies wird konvertierenabc\0
zubc\0
.– TrueY
17. Februar 2016 um 23:29 Uhr
Faustregel: Bei interaktiven Eingaben immer lesen Linien.
– Karoly Horvath
3. September 2016 um 11:06 Uhr
Siehe auch: stackoverflow.com/questions/5240789/…
– Melpomen
1. Oktober 2019 um 17:54 Uhr