Niektóre systemy pozwalają użytkownikowi terminala wpisać bajt NUL naciskając Ctrl - @. scanf()
zapisałby następnie ten bajt do tablicy docelowej, ale najprawdopodobniej nie uznałby tego bajtu za separator słów, więc parsowanie wejściowe będzie kontynuowane aż do końca pliku lub wprowadzony zostanie znak odstępu, taki jak znak nowej linii.
Nie da się określić z tablicy docelowej, czy bajt NUL został zapisany po innych znakach, ani ile kolejnych znaków zostało przeczytanych po tym bajcie NUL. Ale jeśli scanf()
zwróci 1
ima zerową długość, jedyną możliwością jest to, że użytkownik wprowadził bajt NUL po możliwie pustej sekwencji białych znaków.
Byłoby to również jedyna możliwość dla fgets()
wrócić pusty ciąg kiedy minął tablicę docelową o rozmiarze większym niż 1.
Jeśli wejście jest czytane z pliku zamiast terminalu, to zawsze możliwość, aby plik zawierał bajty NUL i należy zachować ostrożność, aby uniknąć niezdefiniowanego zachowania, jeśli tak się stanie. Na przykład o to klasyczny błąd:
char msg[1000];
if (fgets(msg, sizeof msg, stdin)) {
int len = strlen(msg);
if (msg[len - 1] == '\n') { // potential undefined behavior!
msg[--len] = '\0' // potential undefined behavior!
}
...
}
Należy również pamiętać, że kod ma wadę: maksymalna liczba znaków do przechowywania do miejsca przeznaczenia powinna być 999
nie 1000
:
char msg[1000];
if (scanf("%999s",msg) == 1) {
/* word was read from the user */
if (*msg == '\0') {
printf("user entered a NUL byte\n");
}
}
Dla formatu ['scanf'] (http://en.cppreference.com/w/c/io/fscanf)' "% s" 'musi istnieć * trochę * wprowadzania spoza przestrzeni. Jeśli chcesz opcjonalne wejście, dlaczego nie użyć zamiast tego ['fgets'] (http://en.cppreference.com/w/c/io/fgets)? –
@Someprogrammerdude Nie mogę używać fgets, musi to być scanf –
Następnie musisz żyć z ograniczeniami, że nie możesz podać niepustych danych wejściowych. –