我最近开始从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!
答案 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为文件末尾。)
一般情况下,我建议使用准备好的文件,这些文件被重定向到程序的标准输入,以便测试这些程序。这避免了交互式会话中涉及的许多陷阱,并且具有完全可重复的优点,并且可以自动运行,这对于测试非常重要。