如何简化此readLine()函数?

时间:2019-05-23 21:58:57

标签: c file text readline simplify

我有此功能,它读取一些.txt文件的第一行并返回该行供我使用。我不知道行将要走多久,所以我不能有恒定大小的缓冲区。 我的问题是我不能使用此功能,因为它不是我的代码,它会被视为作弊(我有考试)。

我一直在考虑数组的可变长度,但这是邪恶的,因为有人对我说,我可以将整行扫描到我猜的某个地方,但是我不确定在这种情况下我会怎么做(我需要返回行)

char* readLine(FILE *line) { 
    char individualChar;
    int pos = 0;
    int size = 16;
    char *buffer = (char *)malloc(size);

    while ((individualChar = fgetc(line)) != EOF && individualChar != '\n'){
        if (pos + 1 == size){
            size *= 2;
            char *tmp = (char *)realloc(buffer, size);
            if (!tmp){
                free(buffer);
                fprintf(stderr, "Realloc failed");
                return 0;
            }
            buffer = tmp;
        }
        buffer[pos] = individualChar;
        pos++;
    }

    buffer[pos] = '\0';
    return buffer;
}

2 个答案:

答案 0 :(得分:2)

在这里张贴很多代码是不好的,因为OP具有

  

因为它不是我的代码,所以被视为作弊(我参加考试)。

一些技巧


  

我不知道行将要走多久,所以我不能保持恒定的缓冲区大小。

防御性编程假定合理合理的上限以防止黑客利用。 IAC,读取文本文件会导致环境限制

  

环境限制
  一个实现应支持包含至少254个字符的行的文本文件,包括终止换行符。宏BUFSIZ的值至少应为256。C11§7.21.27

采用这种方法:

#include <stdio.h>
#define SANE_BOUND (BUFSIZ+1)

char* readLine(FILE *line) { 
  char buffer[SANE_BOUND];
  if (fgets(buffer, sizeof buffer, line) == NULL) {
    return NULL;
  }
  return strdup(buffer);
}

  

如何简化此readLine()函数?

要清楚,您不想复制的代码有问题

更正

// char is insufficient to distinguish the 257 different results from fgetc()
// char individualChar;
int individualChar;

// Use size_t for sizing, `int` may be too small
size_t pos = 0;
size_t size = 16;

由于罕见的输入错误,如果第一个fgetc()调用返回EOF或以后的调用返回EOF,则该函数应返回NULL

丢弃演员,不需要。

//char *buffer = (char *)malloc(size);
//char *tmp = (char *)realloc(buffer, size);
char *buffer = malloc(size);
char *tmp = realloc(buffer, size);

为什么检查不完整?

代码中有if (!tmp){,但尚未对if (!buffer){进行事先检查

次要

// Use \n and stay case correct
// fprintf(stderr, "Realloc failed");
fprintf(stderr, "realloc() failed\n");

pedantic

size *= 2;可能溢出。您想要多安全?

设计

我要合适的大小并加上最后一个realloc()

我将重新设计以将读取的大小和分配的内存都传达给调用方。文本文件 lines 可能不包含 null字符,并且仅返回 string 指针并不表示某些内容被读取。也适用于此case


分配readLine()比OP发布的代码要简单。

答案 1 :(得分:0)

您可以采用一种更简单的方法:

  1. 计算第一行大小
  2. 一步分配所需的内存
  3. 将行读入分配的内存

此代码不是最佳选择,因为它两次读取文件,但是我认为 适合您的操作会更简单:

#include <stdio.h>
#include <stdlib.h>

char *readline(FILE *f)
{
    size_t size = 0;
    char *ret = NULL;
    long pos = ftell(f);

    /* find line size */
    int c = fgetc(f);
    while (c != EOF && c != '\n')
    {
        c = fgetc(f);
        ++size;
    }

    if (size)
    {
        /* allocate mem */
        ret = malloc(size + 1);

        /* rewind file */
        fseek(f, SEEK_SET, pos);

        /* read data */
        fread(ret, 1, size, f);

        /* add string limiter */
        ret[size] = 0;
    }
    return ret;
}

警告

此代码不完整,因为它无法测试:

  • 使f不是NULL
  • mallocfread的返回值