CTRL-D i CTRL-Z "koniec pliku" wskaźniki służą podobnemu celowi na Unix i Windows systemów, ale są wdrażane zupełnie inaczej.
W systemach Unix (w tym klonach Unix, takich jak Linux) CTRL-D, oficjalnie opisany jako znak końca pliku, jest w rzeczywistości znakiem ograniczającym. Działa to prawie tak samo, jak znak końca wiersza (zwykle powrót karetki lub CTRL-M), który służy do ograniczania linii. Obie postacie informują system operacyjny, że linia wejściowa została zakończona i aby udostępnić program. Jedyna różnica polega na tym, że w przypadku znaku końca wiersza znak końca linii (CTRL-J) jest wstawiany na końcu bufora wejściowego, aby oznaczyć koniec linii, natomiast znak końca pliku nic nie jest wstawiane .
Oznacza to, że po wpisaniu house^D^D
na systemie Unix, wywołanie systemowe najpierw zwróci bufor o długości 5 z 5 znakami house
. Po ponownym wywołaniu read
w celu uzyskania większej ilości danych wejściowych, powróci on do bufora o długości 0 bez żadnych znaków. Ponieważ odczyt zerowej długości zwykłego pliku wskazuje, że koniec pliku został osiągnięty, funkcja biblioteczna gets
interpretuje to również jako koniec pliku i przestaje czytać dane wejściowe. Jednak ponieważ wypełnił bufor 5 znakami, nie zwraca wartości NULL, aby wskazać, że osiągnął koniec pliku. A ponieważ faktycznie nie dotarł on do końca pliku, ponieważ urządzenia końcowe nie są w rzeczywistości plikami, dalsze wywołania do gets
będą następnie wywoływać kolejne wywołania read
, które zwrócą wszystkie kolejne znaki wpisane przez użytkownika.
W systemie Windows CTRL-Z jest obsługiwany w różny sposób. Największą różnicą jest to, że nie jest on w ogóle traktowany przez system operacyjny. Po wpisaniu house^Z^Z^M
w systemie Windows tylko znak powrotu karetki jest traktowany w specjalny sposób. Podobnie jak w systemie Unix, powrót karetki sprawia, że linia wpisana jest dostępna dla programu, ale w tym przypadku powrót karetki i linia są dodawane do bufora, aby oznaczyć koniec linii. W rezultacie funkcja ReadFile
zwraca 9-bajtowy bufor z 9 znakami house^Z^Z^M^J
w nim.
To właściwie sam program, w szczególności biblioteka uruchomieniowa C, która specjalnie traktuje CTRL-Z. W przypadku biblioteki środowiska wykonawczego Microsoft C, gdy widzi znak CTRL-Z w buforze zwróconym przez ReadFile
, traktuje go jako znacznik końca pliku i ignoruje wszystko inne po nim. Korzystając z przykładu z poprzedniego akapitu, gets
kończy wywoływanie ReadFile
, aby uzyskać więcej danych wejściowych, ponieważ fakt, że widział znak CTRL-Z nie jest pamiętany podczas odczytu z konsoli (lub innego urządzenia) i jeszcze nie widział końca -of-line (które zostało zignorowane). Jeśli ponownie naciśniesz enter, gets
powróci z buforem wypełnionym 7 bajtami house^Z\0
(dodając 0 bajtów, aby wskazać koniec napisu). Domyślnie robi to samo podczas odczytu z normalnych plików, jeśli w pliku pojawia się znak CTRL-Z, to i wszystko po nim jest ignorowane. Ma to na celu kompatybilność wsteczną z CP/M, która obsługuje tylko pliki o długościach wielokrotności 128 i używa CTRL-Z do zaznaczania, gdzie pliki tekstowe miały się kończyć.
Należy zauważyć, że opisane powyżej zachowania zarówno w systemie Unix, jak i w Windows są normalną domyślną operacją wprowadzania danych przez użytkownika. Uniksowa obsługa CTRL-D występuje tylko podczas odczytu z urządzenia terminalowego w trybie kanonicznym i istnieje możliwość zmiany znaku "końca pliku" na coś innego. W systemie Windows system operacyjny nigdy specjalnie nie traktuje CTRL-Z, ale to, czy biblioteka środowiska wykonawczego C działa czy nie, zależy od tego, czy odczytany strumień PLIK jest w trybie tekstowym czy binarnym. Dlatego w programach przenośnych zawsze należy dołączyć znak b
w ciągu znaków podczas otwierania plików binarnych (np. fopen("foo.gif", "rb")
).
to wyrażenie: '|| ! feof (stdin)) 'nie ma żadnego użytecznego efektu. Głównie dlatego, że funkcja: 'feof()' sprawdza, czy kod próbował odczytać przeszłość EOF, A to wyrażenie jest sprawdzane tylko wtedy, gdy napotkano EOF, więc zawsze będzie fałszywe. Ponieważ ta funkcja NIE wykonuje tego, co jest (zwykle) spodziewane, zdecydowanie sugeruje, że nigdy jej nie użyje. – user3629249
to wyrażenie: '* curr ++' can/będzie problemem. Problem jest z powodu pierwszeństwa operatorów w C. Zaproponuj: '* curr = (char) c; curr ++; ' – user3629249
Użyłem! feof (stdin), aby sprawdzić, czy napotkałem błąd odczytu zamiast eof. Próbowałem tylko emulować funkcję get (...), aby lepiej wyizolować źródło moich wątpliwości (co jest getchar()) –