在C语言中,输出中的'y'代表什么?

6

我有一个问题,在循环中构建字符串,将该字符串的输出显示到stdout时,最后一个字符是一个带两个点的字符“y”。

那是什么?

我在这个函数中创建字符串:

char get_string(char *buf, int ble, FILE *fp, char del)
{
    int i = 0;
    int c;
    char    result;

    memset(buf, 0, BUFLEN);

    do {

        c = fgetc(fp);

        if (c == del) {
            buf[i] = '\0';
            result = c;
            break;
        } else if(c == '\n') {
            buf[i] = '\0';
            result = '\n';
            break;
        } else {
            buf[i] = c;
            i++;
        }

    } while (c != EOF);

    return result;
}

然后在另一个函数中使用buf和result如下:

char    pair[BUFLEN];
char    end;

do {

        end = get_string(pair, BUFLEN, fp, ';');
        printf("Result: %s\n",pair);

} while (pair != NULL);

上述代码的最后一次迭代输出“Result: y”,我不知道为什么。
6个回答

9
您正在使用 do-while 循环,这意味着您在测试 EOF 之前执行循环体,因此最终将 EOF 放入缓冲区中。 EOF 值为 -1 会被转换为字符范围,其中它对应于 ÿ。建议您切换到更常见的 while 循环,因为它更自然地处理此条件。

8

ÿ 是一个字符的图形表示,其在 Unicode 和许多 ISO-8859-? 编码中的序数值为 0xFF。该值也称为十进制值 255,在某些情况下被用作“文件结束符”(EOF)--尽管没有标准定义“该字符”的意思(据我所知),但当你试图从已经耗尽的文件中读取更多内容时,许多语言(如 C)会返回值 -1。

因此,在输出中出现意外的 ÿ 通常意味着您错误地将一个表示“结束某事”的字节(一个所有位都设置为一的字节)解释为要显示的文本的一部分。


小细节 - 它是Unicode代码点U+00FF的字形,它在UTF-8中对应于字节0xFF - Jesse Beder
@Jesse,在Unicode中可以写成U+00FF(在十进制中具有序数值255,十六进制为FF等),在ISO-8859-1(&c)中当然不能用'U'前缀来写(虽然0xFF仍然正确;-),而UTF-8中的这个代码点被编码为两个字节序列0xC3 0xBF,与OP的问题无关。 - Alex Martelli
我的错,你是对的,在UTF-8中它是一个双字节序列。但我认为正确引用Unicode代码点的方式是U+00FF,而0xFF是指所有位都设置为1(或者只是数字255)的字节。当然,这只是从各种关于Unicode的碎片阅读中获得的知识,我不是专家,所以很高兴被纠正。(例如,维基百科页面仅通过U +stuff引用代码点)。虽然我可能不应该在没有思考一秒钟的情况下提到UTF-8比特 :) - Jesse Beder
-1 是一种误导性的解释(在 C 语言中没有 EOF “字符”,它也不具有值 255 或任何其他值;它是一种带外指示器值)。你没有看到的问题是,代码犯了通常初学者的错误,期望在读取最后一个字符后设置 EOF。 - Jens

2

'y' with two dots over it,是字符0xFF(在Latin-1中是控制台默认代码页)。

作为8位有符号值,0xFF是-1。

请查找您正在打印-1为字符的位置(或使用-1作为字符,然后将其打印出来)。


1

当你在循环中 "构造字符串" 时,你是否记得用 '\0' 正确终止它?

如果循环将字符赋值给一个字符数组,那么最后一个数组项应该是 '\0'

好的,看了代码之后,你已经正确终止了字符串。

编辑:

看起来你将 EOF 字符包含在字符串中。这是一种字符串未被正确终止的情况。你应该在 if-else 结构中检查 EOF 并正确处理它。

我还注意到了另外一件事:

当从函数返回时,你将 int c 赋值给了 char result。编译器应该已经警告过你,你正在尝试将一个较大的数据类型放入一个较小的数据类型中。根据返回值的目的,在考虑更改返回数据类型为 int


1

你的if语句以一个else结束,将字符放入缓冲区,其中有两个问题:

  1. 它未过滤掉EOF特殊“字符”,该字符表示流的结尾
  2. 它未通过比较i与BUFLEN值来检查缓冲区溢出。

第一个问题是你ÿ字符的原因,当流结束时,你会将EOF字符添加到缓冲区,然后循环停止。

解决方法是在你的if-else语句中加入一个子句来过滤它,像这样:

} else if (c != EOF) {
    buf[i] = c;
    i++;
}

第二个问题是在修复之前需要决定如何处理,但它应该被解决。


0

你没有正确地给字符串加上空字符。如果从fp读取的内容既不是"del"也不是"\n",并且到达了文件结尾,那么就不会有空字符。你需要修复你的代码。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接