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

标签 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

来自命令

while loop doesn't end

示例 2:

input: dadada[enter]^Z

来自 Notepad++

output: 7

来自命令

while loop doesn't end

示例 3:

input: dadada[enter]^Z[enter]

来自 Notepad++

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

来自命令

output: 7

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

谁能解释一下 EOF 整数。在cmd中是[enter]^Z[enter],在notepad++中是[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() 或来自文件描述符的等效项上收到零返回值。用户输入如何触发是终端(输入窗口和驱动程序)的问题。

unix网上有很好的解释;一个相当彻底的是here . (与我之前的想法相反,shell 不参与其中;shell 不处理从终端到前台程序的输入。)底线是终端程序和驱动程序一起对某些用户操作使用react(就像按下一个特殊的按钮,或者选择一个菜单项),然后“传达事物”(关闭文件描述符,发送信号)到正在运行的进程[组]。 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 的 mintty 解释为暂停当前前台进程的请求。请注意,这些特殊键可通过 stty 配置:stty eof ^E,其中 ctrl-e 是通过按 ctrld-v ctrl-e 产生的,从那时起将使终端识别 ctrl-e 而不是 ctrl-d 作为文件结尾。)


一般来说,我建议使用重定向到程序标准输入的准备文件来测试此类程序。这避免了交互式 session 中涉及的许多陷阱,并具有可完美重现和自动运行的优点,这对测试很重要。

关于c - K&R 字符计数程序打印 0,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35101194/

相关文章:

notepad++ - 内置html编码的HTML编辑器

c++ - 使用动态链接库管理堆

c - 使用 write 打印 float

c - 如何修复我在 'else' 之前说预期表达式的错误

c++ - GTK 应用程序 : How do I create a working indicator with Qt/C++?

Notepad++ 崩溃后显示空值

javascript - 正则表达式在 HTML 文件中使用 getAttribute 批量替换 attribute[x]

regex - 使用正则表达式 Notepad++ 将字符串的特定部分更改为标题或正确的大小写

regex - 匹配分隔符后且小于 9 的行

c - 使 DMA 内存可临时缓存