【问题标题】:K&R C Programming Language 1.5.1 (File Copying) [duplicate]K&R C编程语言1.5.1(文件复制)[重复]
【发布时间】:2012-08-24 13:21:14
【问题描述】:

嗯,几个月前我读过另一本“众所周知”的 C 书(用我的语言),但我从来没有对此一无所知。 K&R 在 20 页中写了 3 章的方式简直令人惊叹,当然我不能指望巨大的解释,但这也引发了问题。

我对此点有疑问 1.5.1 这本书说(第 16 页):

main(){
  int c;// <-- Here is the question
  c=getchar();
  while (c != EOF){
    putchar(c);
    c = getchar();
  }
}

[...] char 类型专门用于存储此类字符 数据,但可以使用任何整数类型。我们用 int 来表示一个微妙但 重要原因。 问题是将输入的结尾与 有效数据。解决方案是 getchar 返回一个独特的值 当没有更多输入时,一个不能与任何输入相融合的值 真实的性格。此值称为 EOF,表示“文件结束”。我们必须 声明 c 是一个足够大的类型来保存 getchar 的任何值 返回。我们不能使用 char 因为 c 必须足够大才能容纳 EOF 除了任何可能的字符。因此我们使用 int.[...]

在谷歌搜索另一种解释后:

EOF 是一个表示文件结束的特殊宏(Linux:使用 CTRL+d 创建这个的键盘,Windows 命令:使用 CTRL+z(可能必须 在新行的开头,后跟 RETURN)):通常 EOF = -1,但 实现依赖。必须是无效值 对于任何可能的字符。由于这个原因,c 是 int 类型(不是 char 可能已经预料到了)。

所以我将源代码从 int 修改为 char 以查看有什么问题,关于取 EOF 值......但没有问题。以同样的方式工作。

我也没有解释 getchar 如何获取我写的每个字符并打印所有内容。 Int 类型是 4 字节长,因此它可以在一个变量中占用 4 个字符。 但我可以输入任意数量的字符,它会以相同的方式读取和写入所有内容。 而对于 char,也会发生同样的情况...... 真正发生了什么?超过 1-4 个字符时,值存储在哪里?

【问题讨论】:

    标签: c types kernighan-and-ritchie


    【解决方案1】:

    所以我将源代码从 int 修改为 char 看看有什么问题, 关于取EOF值......但没有问题。以同样的方式工作

    碰巧以同样的方式工作。这完全取决于char 的真实类型,即它是签名的还是未签名的。还有一个关于这个主题的C FAQ。如果您的 chars 未签名,您更有可能看到该错误。

    但是,如果字符是 签名,如果输入全是 7 位字符。

    编辑

    最后一个问题是:char类型是1字节长,int是4字节长 长。所以,char 只会占用一个 ascii 字符。但是如果我输入 “堆栈溢出超过 1 字节长”,输出将是“堆栈 溢出超过 1 字节长”。哪里是“粘性溢出超过 1 字节 long" 存储,putchar 是如何放置整个字符串的

    每个字符将由c依次存储。所以第一次,getchar() 将返回 sputchar 将发送它。然后t 会出现,依此类推。 c 绝不会存储一个以上的字符。因此,尽管您给它输入一个大字符串,但它通过一次吃一个字符来处理它。

    【讨论】:

    • 最后一个问题是:char类型是1字节长,int是4字节长。所以,char 只会占用一个 ascii 字符。但是如果我输入“堆栈溢出超过 1 字节长”,输出将是“堆栈溢出超过 1 字节长”。 “tack overflow is over 1byte long”存储在哪里,putchar如何放置整个字符串。对不起,如果这是一个菜鸟问题。
    • 哦,那是一个有点愚蠢的问题。我几乎忘记了循环是如何工作的。 :P 谢谢。
    • 如果 char 是无符号的,这个 bug 很少会漏掉,它会导致无限循环。 char 签名时,可能会长时间不被注意;如果该程序仅用于未分配 -1 的语言环境(例如 UTF-8 语言),则可能永远如此。
    【解决方案2】:

    分成两个答案:

    为什么是int 而不是char

    简短而正式的回答:如果您希望能够表示所有真实字符和另一个非真实字符 (EOF),则不能使用旨在仅保存真实字符的数据类型字符。

    可以理解但不完全准确的答案:函数getchar()返回它读取的字符的ASCII码,或EOF。

    因为-1 转换为char 等于255,我们无法区分255 个字符和EOF。也就是说,

    char a = 255;
    char b = EOF;
    a == b // Evaluates to TRUE
    

    但是,

    int a = 255;
    int b = EOF;
    a == b // Evaluates to FALSE
    

    因此,使用 char 将无法区分 ASCII 码为 255 的字符(从文件读取时可能发生)和 EOF。

    你怎么可以用 putchar() 和 int 来使用

    函数putchar() 查看它的参数,看到一个数字,然后转到 ASCII 表并绘制它看到的字形。当您将int 传递给它时,它会隐式转换为char。如果int 中的数字适合char,则一切正常,没有人注意到任何事情。

    【讨论】:

      【解决方案3】:

      如果您使用char 存储getchar() 的结果,则有两个潜在问题,您将遇到哪一个取决于char 的签名。

      • 如果char 未签名,c == EOF 将永远不会为真,您将获得无限循环。

      • 如果char 被签名,c == EOF 将在您输入一些字符时为真。这取决于使用的字符集;在使用 ISO8859-1 或 CP852 的语言环境中,如果 EOF 为 -1(最常见的值),则为“ÿ”。某些字符集(例如 UTF-8)不会在有效代码中使用值 (char)EOF,但您很少能保证您的问题将停留在签名字符实现上,并且仅在没有问题的语言环境中使用。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-04
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-25
        • 1970-01-01
        • 2013-10-21
        • 2012-07-27
        相关资源
        最近更新 更多