Was ist der Unterschied zwischen scanf("%d")
und scanf("%d ")
Wo ist in diesem Code der Unterschied das abschließende Leerzeichen in der Formatzeichenfolge?
#include <stdio.h>
int main(void)
{
int i, j;
printf("enter a value for j ");
scanf("%d ",&j);
printf("j is %d\n", j);
printf("enter a value for i ");
scanf("%d", &i);
printf("i is %d\n", i);
return 0;
}
Wie funktioniert die scanf()
Funktion funktioniert tatsächlich, wenn ich Leerzeichen nach dem Formatbezeichner wie hinzufüge scanf("%d ", &j);
?
Ein Leerzeichen in einem scanf-Format bewirkt, dass es explizit so viele Leerzeichen wie möglich liest und ignoriert. Also mit scanf("%d ", ...
, liest es nach dem Lesen einer Zahl weiterhin Zeichen und verwirft alle Leerzeichen, bis es ein Nicht-Leerzeichen in der Eingabe sieht. Dieses Nicht-Leerzeichen bleibt als nächstes Zeichen übrig, das von einer Eingabefunktion gelesen wird.
Mit deinem Code:
printf("enter a value for j ");
scanf("%d ",&j);
printf("j is %d \n", j);
Es druckt die erste Zeile und wartet dann darauf, dass Sie eine Zahl eingeben, und dann warten Sie weiter auf etwas danach die Nummer. Also, wenn Sie nur tippen 5Eintreten, scheint es zu hängen – Sie müssen eine weitere Zeile mit einem Nicht-Leerzeichen eingeben, um fortzufahren. Wenn Sie dann eingeben 6Eintretendas wird der Wert für i
sodass Ihr Bildschirm in etwa so aussieht:
enter a value for j 5
6
j is 5
enter a value for i i is 6
Da die meisten Scanf-%-Konvertierungen auch führende Leerzeichen überspringen (alle außer %c
, %[
and %n
), spaces before %-conversions are irrelevant ("%d"
and " %d"
will act identically). So for the most part, you should avoid spaces in scanf conversions unless you know you specifically need them for their peculiar effect.
A white-space character (space, newline, horizontal and vertical tab) in a format string matches any number of white-space characters in the input.
In your first case
scanf("%d ",&j);
when it encounters the white-space char (WSC) ' '
then it will eat all the white spaces input by user including \n
on pressing Enter and it will expect to enter a non-WSC . In this case your program will terminate by pressing Ctrl + Z.
A whitespace character in your scanf
format matches any number of whitespace characters as described by isspace
. So if you have tailing spaces, newlines, tabulators or any other whitespace character then it will also be consumed by scanf
before it returns.
The difference (although obvious) is a different format string. If you enter the following line:
"3 "
scanf()
will return successfully. Otherwise, it depends on your input provided. scanf()
essentially skips over whitespace (tabs, spaces, newlines), and searches for alphanumeric values in the input stream. Since this is trailing whitespace, it gets lumped in with the trailing newline character at the end of input when pressing ENTER, so it’s of little consequence.
scanf()
expects the input provided to exactly match the format string you provide to it, with the exception that contiguous whitespace characters are compressed to a single whitespace character. This becomes very important if you want to parse large strings of data with it’s string-processing equivalent, sscanf()
.
A good exercise to further test this would be something like:
#include<stdio.h>
int main(void)
{
int a=0,b=0,c=0;
printf("Enter values for A, B, C, in the format: \"A B - C\"\n");
scanf("%d %d - %d", &a, &b, &c);
printf("Values: A:%d, B:%d, C:%d\n", a, b, c);
}
Afterwards, check and see what the values of these integers are after providing both correctly and incorrectly formatted consoled input (ie: spaces and hyphens). Here are a couple example runs. The first used incorrect input, the second used correctly formatted input. Notice that in the first case, C
doesn’t even get set, as scanf()
will provided unexpected behavior if the input and the format strings don’t match up. In general, you are better off using something like fgets()
to get a string of input from the user, and then use various search functions (ie: strstr(), strch(), strcat, strcpy, etc) to parse your string, as it is much safer than just using scanf()
and assuming the user won’t make a mistake, either accidentally or deliberately.
Enter values for A, B, C, in the format: "A B - C"
1 2 3
Values: A:1, B:2, C:0
Enter values for A, B, C, in the format: "A B - C"
1 2 - 3
Values: A:1, B:2, C:3
Now, consider one last run: You’ll see that scanf()
compacts multiple consecutive whitespace characters to a single character, hence why these final runs actually succeeds:
Enter values for A, B, C, in the format: "A B - C"
1 2 - 3
Values: A:1, B:2, C:3
Enter values for A, B, C, in the format: "A B - C"
1 2 - 3
Values: A:1, B:2, C:3
Vielleicht sollten wir das Tittle umbenennen, um allgemeiner zu sein?
– Sternengatter
19. April 2018 um 4:13 Uhr
@Stargateur kannst du vorschlagen?
– Vikas Verma
23. April 2018 um 10:37 Uhr
Ich dachte daran, “Nachlauf” zu entfernen
– Sternengatter
23. April 2018 um 15:51 Uhr
@Stargateur Warum solltest du das tun wollen? Die Frage (und auch die Antworten) ist/sind eindeutig auf einen Formatstring mit fokussiert nachlaufend Leerraum, nicht führend eine (die natürlich von Vorteil sein kann und Gegenstand anderer SO-Fragen ist). Es gibt einen großen Unterschied zwischen den beiden Fällen, daher erscheint mir dieser Vorschlag als völliger Unsinn und sogar schädlich.
– RobertS unterstützt Monica Cellio
9. Juni 2020 um 16:23 Uhr
@Stargateur Es ist richtig, dass das tatsächliche Verhalten gleich ist, aber der tatsächliche Effekt hängt davon ab, wie Sie es verwenden. Überspringen von führenden Leerzeichen bis zur richtigen Eingabe wie
" %c"
oder am Konsum hängen (wie diese Frage zeigt). Damit gibt es auch einen Unterschied in der Bedeutung – nachlaufend Leerzeichen = immer schlecht; führender Leerraum = kann nützlich sein. – Ich weiß, worauf Sie hinweisen möchten, aber die Frage ist so gut, wie sie ist, und hat bereits Antworten, wie die Frage ist. Eine Änderung des Titels würde erfordern, dass auch die Antworten geändert werden müssten (mit Beispielen usw.).– RobertS unterstützt Monica Cellio
9. Juni 2020 um 18:15 Uhr