#include <stdio.h>

int main()
{
    int c = getchar();

    while (c != EOF) {
        putchar(c);
        c = getchar();
    }

    return 0;
}

问题是如何区分输入结束和有效数据.这个 解决方案是,当不存在 更多的输入,一个不能与任何实际字符混淆的值. 该值称为EOF,表示``文件结束‘’.我们必须声明c为 一个足够大的类型,可以容纳getchar返回的任何值.我们不能用 字符,因为c必须足够大以容纳EOF 可能是焦炭.因此,我们使用int.

摘自《C编程语言》一书.我有三个问题. 首先,为什么在上述程序运行时同时按ctrl4键会得到输出^\Quit (core dumped)?我使用的是GNU/Linux机器.

其次,我编写了一个程序,如下所示:

#include <stdio.h>

int main()
{
    printf("The part before EOF\n");
    putchar(EOF);
    printf("The part after EOF\n");
}

然后将其编译为‘eof.out’,并将程序中的int c = getchar();从书中的int c = getchar();更改为char c = getchar();,保存它,然后将程序编译为‘Cop.out’. 当我在终端中运行命令./eof.out | ./copy.out时,我得到的输出是:

The part before EOF

这意味着程序‘Cop.out’工作正常,因为它没有打印第二个print f,但上面这本书中的段落表明,自从我将int改为char之后,应该出现了某种故障,那么发生了什么?

第三,当我将char c = getchar();改为double c = getchar();并运行命令./eof.out | ./copy.out时,我得到的输出是:

The part before EOF
�The part after EOF

为什么putchar(EOF);不能阻止复制?double的字节数不是比intchar都多吗?这是怎么回事?

推荐答案

getcharputchar处理unsigned char个值,而不是char个值,因此将c声明为char类型会使有效字符255与EOF混淆.

为了简化解释,这个答案假设了一个常见的C实现,除非有说明:char是带符号的8位,EOF是−1,并转换为以2为模的带符号整数类型w,其中w是以位为单位的类型宽度.C标准在这里允许一些变化,但这些假设在常见的C实现中是典型的,并且与问题中报告的行为相匹配.

从下面的问题中考虑eof.c的代码:

#include <stdio.h>

int main()
{
    printf("The part before EOF\n");
    putchar(EOF);
    printf("The part after EOF\n");
}

当该程序执行putchar(EOF)时,发生的情况是:

  • putcharEOF转换为unsigned char.这在C 2018 7.21.7.3中有所规定(通过7.21.7.7和7.21.7.8).
  • 将−1转换为unsigned char会得到255,因为转换为无符号八位整数类型会对256取模,并且−1+256=255.
  • 将字符代码255写入标准输出.

…将程序中的int c = getchar();从书中的int c = getchar();更改为char c = getchar();,保存它,然后将程序编译为‘Copy.out’. 当我在终端中运行命令./eof.out | ./copy.out时,我得到的输出是:

The part before EOF

对于c = getchar();,当读取字节255并计算c = getchar()时,会发生以下情况:

  • getchar返回255.请注意,根据C 2018 7.21.7.1(通过7.21.7.5和7.21.7.6),它将字符代码作为unsigned char值.
  • 要将255赋给c,255将转换为char类型.根据上面的假设,这包络了模256,产生−1.

−1的值为EOF,因此c != EOF为FALSE,因此循环结束,程序退出.

为什么不停止复制?double的字节数不是比intchar都多吗?这是怎么回事?

对于double c,赋值给c的值是从getchar返回的值;由于目的地类型不能表示getchar返回的所有值,因此不会发生变化.当getchar返回有效字符代码255时,c被设置为255,并且循环继续.当getchar返回用于文件结束的代码−1时,c被设置为−1,并且循环退出.

…这本书指出,自从我把int改成char…以来,应该已经出现了某种故障

书中的这段话并没有说应该有某种失败.它说EOF是"一个不能与任何实际字符混淆的值";它并没有说你不能把EOF转换成char.如果您的C实现使用unsigned char类型,转换将包装取模2w的值,其中wchar中的位数,通常为8,因此取模256.例如,−1映射到255.如果您的C实现使用带符号的char,则转换是由实现定义的.因此,当计算putchar(EOF)时,您的eof.c程序不会输出文件结束指示.相反,它输出字符代码255.

C++相关问答推荐

如何确保内存分配在地址附近?

C/C++中的状态库

带有sigLongjMP中断I/O的异常处理程序

如何在C客户端应用程序的ClientHello消息中添加自定义扩展?

在CLANG中调试预处理器宏

限制不同类型的限定符

理解C版宏(看起来像未声明的变量?)

将返回的char*设置为S在函数中定义的字符串文字可能会产生什么问题?

我的C函数起作用了,但我不确定为什么

使用TCL C API导航到列表中的元素

-Wnonnull-Compare警告不是具有误导性吗?

如何将大写/小写土耳其字母相互转换?

合并对 struct 数组进行排序

如何对现有的双向循环链表进行排序?

如何修复我的qsort()算法?它每次都给出不同的结果

计算SIZE_MAX元素的长数组的大小

是否有单独的缓冲区用于读写库调用?

我正在使用c学习数据 struct ,在学习堆栈时,我试图将中缀转换为后缀,并编写了这段代码.代码未给出输出

为什么 int32_t 和 int16_t 在 printf 输出中具有相同的位数?

GDB 用内容初始化数组