我正在寻找一种方法来使用C中的唯一void函数读取文件和stdin流.我正在尝试使用此功能:
#define ENTER 10 //'\n' ASCII code
........
void read(FILE *stream, char *string) {
char c;
int counter = 0;
do {
c = fgetc(stream);
string = realloc(string, (counter+1) * sizeof(char));
string[counter++] = c;
} while(c != ENTER && !feof(stream));
string[counter-1] = '\0';
}
Run Code Online (Sandbox Code Playgroud)
但它只适用于stdin流.当我使用文本文件时,文件内容在函数外部不可见.我正在调用这个函数:
read(stdin, inputString);
read(inputFile, fileContent);
Run Code Online (Sandbox Code Playgroud)
并且仅在第一种情况下正常工作.
PS:最初,inputString的fileContent已被声明为
char *inputString = malloc(sizeof(char));
char *fileContent = malloc(sizeof(char));
Run Code Online (Sandbox Code Playgroud)
我知道fgetc返回int,char重新分配的char很昂贵(但我只需要使用必要的内存)而EOF或'\n'存储在字符串中(但后面用0-terminator替换).
它无法正常工作,因为您重新分配字符串但不返回指向新分配的指针,并且因为您处理不当fgetc().
你可能需要:
void read(FILE *stream, char **string)
{
int c;
int counter = 0;
int available = 0;
while ((c = fgetc(stream)) != EOF && c != ENTER)
{
if (counter >= available)
{
int new_size = (available + 2) * 2;
void *space = realloc(*string, new_size);
if (space == 0)
// Handle out of memory reporting?
return;
*string = space;
available = new_size;
}
(*string)[counter++] = c;
}
(*string)[counter] = '\0';
}
Run Code Online (Sandbox Code Playgroud)
你会这样称呼它:
read(stdin, &inputString);
read(inputFile, &fileContent);
Run Code Online (Sandbox Code Playgroud)
这里有很多更正; 仍然可以并且应该做出改进.
将指针传递给指针,以便更改可以反映在调用代码中.在原始代码中,如果realloc()调用可以增加当前块,则可能会失败,但是当它必须移动内存时,移动的位置在调用函数中不可用.
返回类型fgetc()是int,而不是char.
你应该更喜欢while循环到do ... while循环.如果您的代码遇到EOF,它会尝试将字符值存储到数组中.
(仍然是一个问题,各种各样)最初的分配在string很大程度上被忽略了; 它被视为零长度分配.
您一次增加一个字符存储的空间 - 这是低效的.修订后的代码每次大约翻倍可用空间.它还为终止空字节分配足够的空间.
未固定:read()标准C不保留名称,但如果使用任何POSIX函数,则有效保留.
您(仍然)无法报告错误.我实际上更喜欢一个更像的功能:
char *read_line(FILE *stream)
{
int c;
int counter = 0;
int available = 2;
char *string = malloc(available);
if (string == 0)
return string;
while ((c = fgetc(stream)) != EOF && c != ENTER)
{
if (counter >= available)
{
int new_size = (available + 2) * 2;
void *space = realloc(string, new_size);
if (space == 0)
{
free(string);
return 0;
}
string = space;
available = new_size;
}
string[counter++] = c;
}
string[counter] = '\0';
return string;
}
Run Code Online (Sandbox Code Playgroud)
您还应该查找POSIX getline()
函数.