fgetc returns 一个奇怪的字符
fgetc returns a strange character
我正在使用 fgetc()
读取输入直到 EOF。我 运行 遇到了一个奇怪的问题。在 EOF 之前,我得到一个字符 7
。我不确定那是什么。
这是我的代码实现:
char *get_file_paths()
{
char *return_str = NULL;
int chars_read = 0;
size_t buf_sz = 80;
return_str = (char *) malloc(buf_sz * sizeof(char));
while((*(return_str + chars_read) = fgetc(stdin)) != EOF) {
chars_read++;
if ((chars_read + 1) == buf_sz) {
buf_sz *= 2;
return_str = realloc(return_str, buf_sz);
}
}
return return_str;
}
例如,如果我有一个字符串:assignment_2/grepout.txt
。在 gdb 中查看 return_str
时,我得到以下信息:
assignment_2/grepout.txt\n7
我很好奇这是什么意思。我在网上查了一下,但没有提到它。它可以是特定于平台的吗?
我是运行以下版本的gcc:
gcc version 4.8.1 20130909 [gcc-4_8-branch revision 202388] (SUSE Linux)
我是 运行 openSuse。
你没有标记字符串的结尾。
return_str[chars_read] = '[=10=]';
return return_str;
重要的是不要将 fgetc()
的 return 强制键入 char
。 fgetc()
(和 fgets())return int
而不是 char
正是因为 EOF 是一个超出字符范围的值。您的 0337(0xFF 或十进制的 255)在大多数实现中都是有效字符(它是代码页 1252、ISO-8859-15 和 Unicode 中的字符 ÿ)。
在你的循环中,如果你在键盘上输入那个字符,你将有与 EOF 相同的行为。
因此您应该将循环更改为:
char *get_file_paths(void)
{
int chars_read = 0;
size_t buf_sz = 0;
int ch;
char *return_str = NULL;
while((ch = fgetc(stdin)) != EOF) {
if(chars_read == buf_sz) {
buf_sz += 80;
void *no_leak = realloc(return_str, buf_sz+1);
if(!no_leak) {
perror("No memory\n");
abort();
}
return_str = no_leak;
}
return_string[chars_read++] = ch;
}
if(return_string)
return_string[chars_read++] = 0;
return return_str;
}
我换了其他几个小的"issues"。
realloc()
以 NULL
作为第一个参数与 malloc()
相同,因此通过在循环中重新安排(重新)分配,您可以避免不必要的代码。
sizeof (char)
定义为1,无需说明。
- EOF 值(即 -1)未进入循环且未与字符 0xFF 混淆。
- 如果已经到达 EOF,函数 returns NULL。这是一个可能有用(或无用)的功能性选择。这取决于上下文。
- 使用数组语法(
a[x]
而不是 *(a+x)
),它的可读性要高得多。
编辑:添加了分配检查。用了狠辣的手段。在那种情况下我们还能做什么?
我正在使用 fgetc()
读取输入直到 EOF。我 运行 遇到了一个奇怪的问题。在 EOF 之前,我得到一个字符 7
。我不确定那是什么。
这是我的代码实现:
char *get_file_paths()
{
char *return_str = NULL;
int chars_read = 0;
size_t buf_sz = 80;
return_str = (char *) malloc(buf_sz * sizeof(char));
while((*(return_str + chars_read) = fgetc(stdin)) != EOF) {
chars_read++;
if ((chars_read + 1) == buf_sz) {
buf_sz *= 2;
return_str = realloc(return_str, buf_sz);
}
}
return return_str;
}
例如,如果我有一个字符串:assignment_2/grepout.txt
。在 gdb 中查看 return_str
时,我得到以下信息:
assignment_2/grepout.txt\n7
我很好奇这是什么意思。我在网上查了一下,但没有提到它。它可以是特定于平台的吗?
我是运行以下版本的gcc:
gcc version 4.8.1 20130909 [gcc-4_8-branch revision 202388] (SUSE Linux)
我是 运行 openSuse。
你没有标记字符串的结尾。
return_str[chars_read] = '[=10=]';
return return_str;
重要的是不要将 fgetc()
的 return 强制键入 char
。 fgetc()
(和 fgets())return int
而不是 char
正是因为 EOF 是一个超出字符范围的值。您的 0337(0xFF 或十进制的 255)在大多数实现中都是有效字符(它是代码页 1252、ISO-8859-15 和 Unicode 中的字符 ÿ)。
在你的循环中,如果你在键盘上输入那个字符,你将有与 EOF 相同的行为。
因此您应该将循环更改为:
char *get_file_paths(void)
{
int chars_read = 0;
size_t buf_sz = 0;
int ch;
char *return_str = NULL;
while((ch = fgetc(stdin)) != EOF) {
if(chars_read == buf_sz) {
buf_sz += 80;
void *no_leak = realloc(return_str, buf_sz+1);
if(!no_leak) {
perror("No memory\n");
abort();
}
return_str = no_leak;
}
return_string[chars_read++] = ch;
}
if(return_string)
return_string[chars_read++] = 0;
return return_str;
}
我换了其他几个小的"issues"。
realloc()
以NULL
作为第一个参数与malloc()
相同,因此通过在循环中重新安排(重新)分配,您可以避免不必要的代码。sizeof (char)
定义为1,无需说明。- EOF 值(即 -1)未进入循环且未与字符 0xFF 混淆。
- 如果已经到达 EOF,函数 returns NULL。这是一个可能有用(或无用)的功能性选择。这取决于上下文。
- 使用数组语法(
a[x]
而不是*(a+x)
),它的可读性要高得多。
编辑:添加了分配检查。用了狠辣的手段。在那种情况下我们还能做什么?