K& R字符计数程序打印0

时间:2016-01-30 11:27:16

标签: c notepad++

我最近开始从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
来自Notepad ++的

output: 0

来自cmd

while loop doesn't end

示例2:

input: dadada[enter]^Z
来自Notepad ++的

output: 7

来自cmd

while loop doesn't end

示例3:

input: dadada[enter]^Z[enter]
来自Notepad ++的

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

来自cmd

output: 7

现在我想知道为什么示例1中的输出为0。

有人可以解释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!

1 个答案:

答案 0 :(得分:3)

编辑:我现在看到你使用gcc,我意识到编译器(确定运行时库)可能并不那么重要。它只会从read()或文件描述符中的等效项接收零返回值。用户输入如何触发,这是终端(输入窗口和驱动程序)的问题。

unix在线有很好的解释;一个相当彻底的是here。 (与之前的想法相反,shell不参与其中; shell不会处理从终端输入前台程序。)底线是终端程序和驱动程序一起对某些用户操作作出反应(比如按一个特殊按钮,或者选择一个菜单项,然后&#34;传达信息&#34; (关闭文件描述符,发送信号)到正在运行的进程[组]。 Windows机制可能几乎完全不同。

然后,根据documentation,nppexe插件不是真正的终端;在什么条件下它关闭它发送数据的文件描述符(这个事件会使读取过程检测到EOF)我不知道。我必须假设当你按ctrl-z而不发送到目前为止输入的字符时它会关闭文件描述符。

普通的Windows控制台通常会将ctrl-z识别为文件结束指示符,并带有限制(参见Cool Guy的评论)。在我使用cygwin-gcc编译程序的Windows控制台上尝试时,ctrl-z立即关闭与程序的通信,到目前为止丢弃当前输入行上的任何用户输入。这与你的0结果一致。

cygwin终端(我使用mintty)和shell(我使用bash)通常会识别ctrl-d。在那里,ctrl-d也必须在一行的开头按下,或者更确切地说,当到目前为止所有输入都被发送时。如果在按下ctrl-d时输入处于待处理状态,例如键入一行时,它会导致终端将该数据发送到进程,以便不再有数据等待。随后的第二个ctrl-d将使终端关闭连接。 (感谢Chrono指出这一点。)

(Ctrl-z通常由unix终端解释,以及cygwin的精简,作为暂停当前前台进程的请求。请注意,这些特殊键可以使用stty进行配置:{ {1}},其中ctrl-e是通过按ctrld-v ctrl-e生成的,从那时起将使终端识别ctrl-e而不是ctrl-d为文件末尾。)

一般情况下,我建议使用准备好的文件,这些文件被重定向到程序的标准输入,以便测试这些程序。这避免了交互式会话中涉及的许多陷阱,并且具有完全可重复的优点,并且可以自动运行,这对于测试非常重要。