【问题标题】:Invalid Argument Reported By getdelimgetdelim 报告的参数无效
【发布时间】:2014-11-10 03:12:48
【问题描述】:

我正在尝试使用getdelim 函数将整个文本文件的内容读入字符串。

这是我正在使用的代码:

ssize_t bytesRead = getdelim(&buffer, 0, '\0', fp);

然而,这失败了,strerror(errno) 说“错误:无效参数”

我已经查看了所有我可以使用的文档,但无法使其正常工作,我尝试了 getline 确实可以工作,但我想让这个功能更好地工作。

缓冲区也被初始化为 NULL,所以它似乎不是那个
fp 也没有报告任何错误,文件完美打开

编辑:我的实现是基于这个stackoverflow问题Easiest way to get file's contents in C的答案

【问题讨论】:

  • 您知道您正在为第二个参数传递 NULL(作为 0)。 Check the documentation,因为我不相信这是允许的。该函数需要一个size_t*它指向的值可以是0,但指针本身不能这样。而buffer 还保存着从malloc family, it should be NULL` 分配的动态缓冲区地址。
  • 我试过了,但还是一样。如果第一个参数为 NULL,它将忽略大小值。
  • 忽略at大小地址的值;它不会忽略地址本身。它仍将使用地址来存储输出大小。您实际上使用的是空字符(0 字节)作为分隔符吗?真的吗?
  • 在我发现的 getdelim 示例中,0 似乎对他们来说很好用。我也尝试过使用 size_t* 指针(这就是我让 getline 工作的方式)。然而,getdelim 的反应并不相同。没有编译器错误或警告,即使设置了 -Wall

标签: c linux gnu getline errno


【解决方案1】:

Kervate,请启用编译器警告(-Wall 用于 gcc),并注意它们。他们很有帮助;为什么不接受你能得到的所有帮助呢?

正如 WhozCraig 和 n.m. 指出的那样。在您原来的问题的 cmets 中,getdelim() man page 显示了正确的用法。

如果你想读取由 NUL 字符分隔的记录,你可以使用

FILE   *input; /* Or, say, stdin */
char   *buffer = NULL;
size_t  size = 0;
ssize_t length;

while (1) {
    length = getdelim(&buffer, &size, '\0', input);
    if (length == (ssize_t)-1)
        break;

    /* buffer has length chars, including the trailing '\0' */
}

free(buffer);
buffer = NULL;
size = 0;

if (ferror(input) || !feof(input)) {
    /* Error reading input, or some other reason
     * that caused an early break out of the loop. */
}

如果要将文件的内容读入单个字符数组,那么getdelim()是错误的函数。

相反,使用realloc() 动态分配和增长缓冲区,使用fread() 附加到它。为了让你开始——这还不完整! -- 考虑以下代码:

FILE   *input; /* Handle to the file to read, assumed already open */
char   *buffer = NULL;
size_t  size = 0;
size_t  used = 0;
size_t  more;

while (1) {

    /* Grow buffer when less than 500 bytes of space. */
    if (used + 500 >= size) {
        size_t new_size = used + 30000; /* Allocate 30000 bytes more. */
        char  *new_buffer;

        new_buffer = realloc(buffer, new_size);
        if (!new_buffer) {
            free(buffer); /* Old buffer still exists; release it. */
            buffer = NULL;
            size = 0;
            used = 0;
            fprintf(stderr, "Not enough memory to read file.\n");
            exit(EXIT_FAILURE);
        }

        buffer = new_buffer;
        size = new_size;
    }

    /* Try reading more data, as much as fits in buffer. */
    more = fread(buffer + used, 1, size - used, input);
    if (more == 0)
        break; /* Could be end of file, could be error */

    used += more;
}

请注意,后一个 sn-p 中的buffer 不是字符串。没有终止 NUL 字符,所以它只是一个字符数组。实际上,如果文件包含二进制数据,则数组可能包含大量 NUL(\0,零字节)。假设没有错误并且读取了所有文件(您需要检查这一点,请参见前面的示例),buffer 包含从文件中读取的used 字符,并为size 分配了足够的空间。如果used > 0,那么size > used。如果used == 0,则size 可能为零,也可能不为零。

如果您想将buffer 转换为字符串,您需要决定如何处理可能嵌入的\0 字节——我建议转换为例如空格或制表符,或移动数据以完全跳过它们 -- 并在末尾添加字符串终止 \0 以使其成为有效字符串。

【讨论】:

  • 成功了,非常感谢!我的 size_t 变量的问题是我已将其定义为 size_t *len,而不是 size_t len... 然而有趣的是,我正在使用 -Wall 进行编译,并且仅使用文字 0 并没有给出任何错误或警告。因此为什么我这么困惑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-24
  • 1970-01-01
  • 2021-09-30
  • 2011-10-17
  • 2014-08-18
  • 1970-01-01
  • 2012-06-21
相关资源
最近更新 更多