通过 scanf 的 EOF,返回值 -65 [已关闭]

EOF via scanf, returned value -65 [closed]

提问人:bar toplian 提问时间:3/23/2023 最后编辑:Some programmer dudebar toplian 更新时间:3/24/2023 访问量:83

问:


编辑问题以包括所需的行为、特定问题或错误以及重现问题所需的最短代码。这将有助于其他人回答这个问题。

8个月前关闭。

我需要在我的“系统编程实验室”中将我的“strcmp”实现写成作业,这只是 C 课程的一个花哨名称。 当我测试代码与标准版本时,它在任何情况下都可以工作,除了 EOF,它在标准版本中自动返回 -1,而在我的版本中,它将开始比较并相应地返回 0,1,-1。 我想写一个宏来处理这种情况。

我正在使用:VMware Workstation 17 Player 运行 Ubuntu 16.04(这些是uni的要求)。

我试过:

#define EOF_CHECK(s1, s2) if ((s1)[0] == EOF || (s2)[0] == EOF ) return -1; 

#define EOF_CHECK(s1, s2) if ((s1)[0] == '\0' || (s2)[0] == '\0' ) return -1; 

#define EOF_CHECK(s1, s2) if ((s1) == NULL || (s2) == NULL ) return -1; 

他们都没有奏效。 我在 scanf 收到 EOF 后打印了值,结果是 (-65) 十进制。 此宏确实有效:

#define EOF_CHECK(s1, s2) if ((s1)[0] == -65  || (s2)[0] == -65  ) return -1;

我想避免使用神奇的数字。

c ubuntu eof

评论

5赞 Some programmer dude 3/23/2023
您需要检查返回的内容以检测错误或文件末尾。scanf
5赞 Some programmer dude 3/23/2023
你真的在检查函数调用的实际返回值吗?不是调用中使用的变量的内容或值?您显示的宏似乎检查字符串的内容,如果失败,则不会更新这些字符串。请尝试创建一个适当的最小可重复示例编辑您的问题以显示它。scanfscanf
1赞 Gerhardh 3/23/2023
您没有演示如何使用这些宏。我们无法判断到底出了什么问题。我们只能从您的使用方式中猜测,您可能没有使用正确的值。但这只是一个空白的猜测。你应该向我们展示你正在做的事情的完整最小示例。s1s2
1赞 0___________ 3/23/2023
显示完整的代码,因为你对问题的描述还远不清楚
2赞 Jabberwocky 3/23/2023
所以你要求回报 -65?这没有任何意义,不可能返回 -65。还是其他东西返回 -65?请编辑并明确说明。你的问题完全不清楚。您需要显示您的实际代码以及输入和预期与实际输出。阅读: 如何提问。而这个:最小的可重复的例子scanfscanf

答:

2赞 chqrlie 3/23/2023 #1

我需要将我的实现写成作业strcmp

和 之间没有联系。 不是字符值,则不应将其存储到字符串中。如果在读取 中的字符串时返回,则目标数组中不会存储任何内容,该数组可能仍处于未初始化状态。在使用字符串之前,必须测试此条件。因此,在处理字符串内容时不需要进行特定测试。strcmpEOFEOFscanfEOFstdinEOF

strcmp将字符串中的字符作为值进行比较,直到并包括 null 终止符。如果两个字符串对所有字符的比较相等并且长度相同,则返回,否则,如果两个字符串中不相等的第一个字符的值小于第二个字符串的值,则返回负值(或任何其他负值)(对值执行比较)。否则,它将返回一个正值(或其他值)。经典实现返回字符值的差异,例如,如果比较 和 ,则可能是 。unsigned char0-1unsigned char1-65"""A"

scanf是一个完全独立的功能,重新实现要困难得多

我建议您不要在赋值中使用宏,尤其是扩展为语句的宏,因为它们隐藏了流控制构造,因此非常容易出错。

下面是 :strcmp

// Assuming UCHAR_MAX <= INT_MAX
int strcmp(const char *s1, const char *s2) {
    /* use unsigned char for comparisons */
    const unsigned char *p1 = (const unsigned char *)s1;
    const unsigned char *p2 = (const unsigned char *)s2;
    for (; *p1 == *p2; p1++, p2++) {
        if (*p1 == '\0')
            return 0;
    }
    return *p1 - *p2;
}

评论

0赞 chux - Reinstate Monica 3/23/2023
细节:“EOF不是字符值,它不能存储到字符串中。 -->嗯,当有符号时,很容易将-1作为字符串的一部分存储在a中。charchar
0赞 chux - Reinstate Monica 3/23/2023
迂腐:“strcmp 将字符串中的字符作为无符号字符值进行比较,直到并包括 null 终止符。可能只会在即将不受支持的非 2 补码中产生影响。unsigned char
0赞 Some programmer dude 3/23/2023
另请注意,在 Windows 上,字符值实际上可以解释为文件末尾。例如,如果从文本文件或控制台读取它。它对应于 Windows 控制台中用作文件末尾。26Ctrl-Z
0赞 chqrlie 3/23/2023
@chux-ReinstateMonica:是的,你是对的,但标准的字母有些模棱两可, 7.25.4 比较函数 比较函数 memcmpstrcmp 和 strncmp 返回的非零值的符号由在被比较的对象中不同的第一对字符(均解释为无符号字符)的值之间的差值的符号确定。可以解释为与哪个没有区别,因为负零转换为 时转换为 。(unsigned char)*s1 == (unsigned char)*s2*s1 == *s20(unsigned char)
2赞 chqrlie 3/24/2023
@Someprogrammerdude:Windows 中 ^Z 的情况令人遗憾地提醒人们 MS/DOS 的起源是 CP/M 的克隆,其文件系统不存储文件的字节长度,而只存储扇区数。最后一个扇区的 ^Z 被解释为文本文件的文件结束标记,库必须显式测试。MS/DOS 文件系统始终有一个字节长度字段(最初是 24 位,然后是 32 位),因此从不需要 ^Z hack。几十年前就可以取消对它的支持,以及过时的 CR LF 行序列末尾,但它们至今仍困扰着程序员的生活。