簡體   English   中英

K&R字符計數程序打印0

[英]K&R Character counting program prints 0

我最近開始從K&R書中學習C。 現在我停留在示例1.5.2上。 該程序是這樣的:

#include <stdio.h>

/* Count the number of characters written in input */
main()
{
    long nc;

    nc = 0;
    while (getchar() != EOF)
        nc++;

    printf("%ld\n", nc);
}

我通過NppExec插件直接從notepad ++編譯代碼,但也嘗試直接從cmd運行它。

這是不同的例子

范例1:

input: dadada^Z

從記事本++

output: 0

從cmd

while loop doesn't end

范例2:

input: dadada[enter]^Z

從記事本++

output: 7

從cmd

while loop doesn't end

范例3:

input: dadada[enter]^Z[enter]

從記事本++

output: program end with [enter]^Z, additional [enter] doesn't do anything

從cmd

output: 7

現在我想知道的是為什么示例1中的輸出為0。

有人可以解釋一下EOF整數EOF 在cmd中為[enter]^Z[enter] ,在記事本++中為[enter]^Z ,甚至有人說它的^Z

編輯

這是我在NppExec中使用的命令

npp_console 1               //open console
NPP_CONSOLE -               //disable output of commands
npe_console m-              //disable unnecessary output
con_colour bg= 191919 fg= F5F5F5    //set console colors
npp_save                //save the file
cd $(CURRENT_DIRECTORY)         //follow current directory
NPP_CONSOLE +               //enable output
IF $(EXT_PART)==.c GOTO C       //if .c file goto C label
IF $(EXT_PART)==.cpp GOTO CPP       //if .cpp file goto CPP label
IF $(EXT_PART)==.java GOTO JAVA     //if .java file goto JAVA label
IF $(EXT_PART)==.cs GOTO C#     //if .cs file goto C# label
IF $(EXT_PART)==.py GOTO PYTHON     //if .py file goto PYTHON label
echo FILE SAVED
GOTO EXITSCRIPT             // else treat it as a text file and goto  EXITSCRIPT
//C label
:C                                                                  
cmd /C if exist "$(NAME_PART).exe" cmd /c del "$(NAME_PART).exe"//delete   existing executable file if exists
gcc "$(FILE_NAME)" -o $(NAME_PART)              //compile file
IF $(EXITCODE) != 0 GOTO EXITSCRIPT             //if any compilation error   then abort
echo C CODE COMPILED SUCCESSFULLY:              //print message on console
$(NAME_PART)                                            //run file in cmd,  set color to green and pause cmd after output
GOTO EXITSCRIPT                         //finally exits

:CPP
cmd /C if exist "$(NAME_PART).exe" cmd /c del "$(NAME_PART).exe"
g++ "$(FILE_NAME)" -o $(NAME_PART)
IF $(EXITCODE) != 0 GOTO EXITSCRIPT
echo C++ CODE COMPILED SUCCESSFULLY:
$(NAME_PART)
GOTO EXITSCRIPT

:JAVA
cmd /C if exist "$(NAME_PART).class" cmd /c del "$(NAME_PART).class"
javac $(FILE_NAME) -Xlint
IF $(EXITCODE) != 0 GOTO EXITSCRIPT
echo JAVA CODE COMPILED SUCCESSFULLY:
java $(NAME_PART)
GOTO EXITSCRIPT

:C#
cmd /C if exist "$(NAME_PART).exe" cmd /c del "$(NAME_PART).exe"
csc $(FILE_NAME)
IF $(EXITCODE) != 0 GOTO EXITSCRIPT
echo C# CODE COMPILED SUCCESSFULLY:
$(NAME_PART)
GOTO EXITSCRIPT

:PYTHON
echo RUNNING PYTHON SCRIPT IN CMD:              //python is a script so no     need    to compile
python $(NAME_PART).py
GOTO EXITSCRIPT

:EXITSCRIPT
// that's all, folks!

編輯:我現在看到您使用gcc,並且我意識到也許編譯器(確定運行時庫)可能沒有那么重要。 它只會在文件描述符的read()或等效值上收到零返回值。 用戶輸入如何觸發取決於終端(輸入窗口和驅動程序)。

網上有很好的解釋。 一個相當徹底的人在這里 (與我之前的想法相反,shell不參與其中; shell不會處理從終端輸入到前台程序。)最重要的是,終端程序和驅動程序共同對某些用戶動作做出反應(例如按下特殊按鈕,或選擇菜單項),然后“傳達信息”(關閉文件描述符,發送信號)給正在運行的進程[group]。 Windows機制可能幾乎但不是完全不同。


然后,根據文檔 ,nppexe插件不是真正的終端。 在什么情況下,它將關閉文件描述符,它將數據發送到該文件描述符(該事件會使讀取過程檢測到EOF),我不知道。 我必須假定當您按ctrl-z時,它關閉了文件描述符,而沒有發送到目前為止已鍵入的字符。

普通的Windows控制台通常將ctrl-z識別為文件結尾指示符,但有限制(請參閱Cool Guy的評論)。 在使用cygwin-gcc編譯程序的Windows控制台上進行嘗試時,ctrl-z立即關閉與該程序的通信,到目前為止已放棄了當前輸入行上的任何用戶輸入。 這與您的0結果一致。

cygwin終端(我使用薄荷)和shell(我使用bash)通常會識別ctrl-d。 同樣,也必須在一行的開頭按ctrl -d,或者在發送完到目前為止所有的輸入后更精確地按ctrl -d。 如果在按ctrl-d時(例如,在鍵入一行時)輸入待處理,則它將導致終端將該數據發送到進程,因此不再有數據在等待。 因此,隨后的第二個ctrl-d將使終端關閉連接。 (感謝Chrono指出這一點。)

(Ctrl-z通常由unix終端以及cygwin的mintty解釋為暫停當前前台進程的請求。請注意,可以使用stty配置這些特殊鍵: stty eof ^E ,在其中生成ctrl-e通過按ctrld-v ctrl-e,從那時起將使終端識別ctrl-e而不是ctrl-d作為文件結尾。)


通常,我建議使用准備好的文件,這些文件將重定向到程序的標准輸入,以便測試此類程序。 這避免了交互式會話涉及的許多陷阱,並具有可完美重現並可以原子運行的優點,這對測試很重要。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM