chars eof啥用
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了chars eof啥用相关的知识,希望对你有一定的参考价值。
参考技术A EOF的定义和运用看来给一些入门编程者带来了许多困惑,我希望以下的解释能有助于你更好地理解它。 在我向你详细地讲述EOF是什么之前,我要首先告诉你它不是什么。
EOF不是:
(1) 一个字符
(2) 存在于文件结尾的一个数
(3) 存在于文件中数
EOF 是:
EOF是一个定义为负值的宏。通常,一个函数在读取过程中出错或到了输入结尾时就会返回EOF。
由于类型提升规则 (variable promotion rules,下文中讲述),用int型变量来存取一些函数返回值十分必要,即使这些函数返回一个
字符,如 getchar()和fgetc().
以下是一些你可能会用到的示例代码:
int c;
while ((c = fgetc(fp)) != EOF)
putchar (c);
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
int ch;
while ((ch = cin.get()) != EOF)
cout <<(char)ch;
字符型转换为整型
在定义上,一个int型变量的范围比一个char型的大,因此,一个负的int型数不能表示一个字符。但是,当你比较 一个int型数和一个
char型数时,由于这两个变量在内存尺寸上的不同,这个char型数将会被提升为一个int型数。被提升后的char型变量的值受符号位的影响, 糟
糕的是,一个char型变量在缺省情况下既可以是有符号的也可以是无符号的,这些取决于所用的编译器。
为了更好地理解,让我们看几个int 型和char型的实例。假定int型变量为二个字节,char型仅有一个字节。除了第一栏,所有数值都用十六进
值表示。
----------------------------- ------------------------------
| char and int comparison | | char to int promotion |
----------------------------- ------------------------------
| Decimal | int | char | | char | unsigned | signed |
|---------|---------|-------| |-------|----------|---------|
| 2 | 00 02 | 02 | | 02 | 00 02 | 00 02 |
| 1 | 00 01 | 01 | | 01 | 00 01 | 00 01 |
| 0 | 00 00 | 00 | | 00 | 00 00 | 00 00 |
| -1 | FF FF | FF | | FF | 00 FF | FF FF |
| -2 | FF FE | FE | | FE | 00 FE | FF FE |
----------------------------- ------------------------------
The "char to int promotion" table makes it clear that the sign of a char produces a very different number in the int.
So what does all this mean to me as a programmer?
上面的表格很清晰地显示:有符号字符型在转换后变成了一个大不相同的整型 数。
让我们修改一下前面的代码,用字符型变量来存储fgetc()的返回值。
char c;
while ((c = fgetc(fp)) != EOF)
putchar (c);
现在我们假定从文件中读取了一个字节,该字节的 值为0xff. fgetc()在一个整型变量中返回了这个值,它看起来是:0x00 0xff(再次假定整
型变量为二个字节)。为了将这个结果存放在一个字符型变量中,它必须被降级(demote),因此字符型的值变为0xff.接下来,字符型c与整型
的EOF比较。提升规则开始起作用了,c必须被提升为整型。但是,在代码中,c的符号并未显式地声明,所以我们不知道它是有符号的还是无符
号的,整型的数值可能为0xff 0xff或者0x00 0xff.
因此,不能保证这段代码会按照这们设想的方式执行。
下面是一小 段展示这些转换的代码:
#include <stdio.h>
int main(void)
int i = -1;
signed char sc = 0xff;
unsigned char usc = 0xff;
printf ("Comparing %x with %x/n", i, sc);
if (i == sc) puts("i == sc");
else puts("i != sc");
putchar ('/n');
printf ("Comparing %x with %x/n", i, usc);
if (i == usc) puts("i == usc");
else puts("i != usc");
return 0;
/*
* 输出
比较ffff和ffff <--- 注意这些值已经提升过了
i == sc
比较ffff和ff
i != usc
*
*/
在有些情况下程序可能会陷入无限循环中。
分段错误,怎么办? [关闭]
【中文标题】分段错误,怎么办? [关闭]【英文标题】:segmentation fault, what to do? [closed] 【发布时间】:2022-01-22 09:09:57 【问题描述】:char* scanString(FILE* fp, unsigned int size)
char* str;
int Char;
unsigned int len = 0;
str = (char*)realloc(NULL, size);
if (str == NULL)
return str;
while (EOF != (Char = fgetc(fp)) && Char != '\n')
str[len++] = Char;
if (len == size)
size = size + 16;
str = (char*)realloc(str, size);
if (!str)return str;
str[len++] = '\0';
return (char*)realloc(str, len);
我使用这个函数来扫描未知大小的字符串,当我在没有循环的主函数中使用它时,一切正常。 但是当我试图在另一个函数中使用它时,程序就停止了,我该怎么办?
【问题讨论】:
您应该附加一个调试器以至少知道段错误发生在哪一行。此外,如果返回 null,则会泄漏:str = (char*)realloc(str, size);
不要解释“当我尝试使用另一个函数时”,而是向我们展示您编写的实际代码,当您尝试运行它时会停止。
提示:str = (char*)realloc(str, size); if (!str)return str;
在realloc
返回NULL
时会泄漏内存。
你传递的size
是什么?
提示:size
参数的意义何在?
【参考方案1】:
您的代码取决于size
最初至少是一个。错误可能是因为 0
被传递了。
在向缓冲区添加字符之前,您没有确保缓冲区中有可用空间,最简单的解决方案是在向缓冲区添加字符之前而不是之后扩展缓冲区。
// Type-safe version of realloc.
#define REALLOC(p, T, n) ((T*)realloc(p, sizeof(T) * n))
char* readLine(FILE* fp)
char* str = NULL;
size_t size = 0;
size_t len = 0;
while (1)
int ch = fgetc(fp);
if (len == size)
size += 16;
char* tmp = REALLOC(str, char, size);
if (!tmp)
free(str);
return NULL;
str = tmp;
if (ch == EOF || ch == '\n')
str[len] = 0;
return str;
str[len++] = ch;
其他变化:
消除了realloc
返回 NULL 时发生的内存泄漏。
删除了无用的size
参数。
更好的函数名。
请注意,返回此接口并不表示 EOF 或读取错误。调用者有责任使用feof(fp)
和ferror(fp)
进行检查。我会使用不同的设计。
对于为什么宏更安全有些困惑,所以我会解释一下。
malloc
/calloc
/realloc
的一个大问题是它们返回 void*
,这意味着没有类型检查来确保返回的指针与其分配的变量兼容。宏添加了这种类型检查。
这允许捕获某些原本会被忽视的错误。您可以找到一个宏捕获错误的演示,常见替代方法无法捕获here。
#include <stdlib.h>
#define REALLOC(p, T, n) ((T*)realloc(p, sizeof(T) * n))
int main(void)
size_t n = 4;
int *a = NULL;
double *b = NULL;
b = realloc(NULL, n * sizeof(int)); // Silently accepts the error.
b = realloc(NULL, n * sizeof *a); // Silently accepts the error.
b = REALLOC(NULL, int, n); // Catches the error.
(void)a; // Proxy for remainder of function.
(void)b; // Proxy for remainder of function.
【讨论】:
请原谅我的失明,但str
第一次测试时怎么不为NULL?
@kirjosieppo 错字。固定。
"注意返回这个接口" ...这里少了一个词吗?从,也许?
// Safer
不...为什么? IMO 这是相当不安全的。传递不必要的显式类型没有任何好处......类型转换也没有。更好的方法是:char* tmp = realloc(str, size * sizeof *tmp);
如果你想要“安全”
@ikegami 类型检查? int* tmp = REALLOC(str, char, size);
或 char* tmp = REALLOC(str, int, size);
... 都容易出错。只需使用sizeof *tmp
以上是关于chars eof啥用的主要内容,如果未能解决你的问题,请参考以下文章