读取不同流的独特功能

GSc*_*iti 0 c pointers stream

我正在寻找一种方法来使用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替换).

Jon*_*ler 5

它无法正常工作,因为您重新分配字符串但不返回指向新分配的指针,并且因为您处理不当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)

这里有很多更正; 仍然可以并且应该做出改进.

  1. 将指针传递给指针,以便更改可以反映在调用代码中.在原始代码中,如果realloc()调用可以增加当前块,则可能会失败,但是当它必须移动内存时,移动的位置在调用函数中不可用.

  2. 返回类型fgetc()int,而不是char.

  3. 你应该更喜欢while循环到do ... while循环.如果您的代码遇到EOF,它会尝试将字符值存储到数组中.

  4. (仍然是一个问题,各种各样)最初的分配在string很大程度上被忽略了; 它被视为零长度分配.

  5. 您一次增加一个字符存储的空间 - 这是低效的.修订后的代码每次大约翻倍可用空间.它还为终止空字节分配足够的空间.

  6. 未固定: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() 函数.