【问题标题】:segmentation fault when read file in c在c中读取文件时出现分段错误
【发布时间】:2019-12-21 08:56:10
【问题描述】:

我尝试编写获取字符数组的函数,从文件中插入行来自重定向,并返回文件的长度。

我试过了:

#define LINE 256
int getline1(char s[]){
    char ch;
    int length = 0;
    scanf("%c", &ch);
    while(ch != '\n' && ch != EOF){
        s[length++] = ch;
        scanf("%c", &ch);
    }
    s[length] = '\0';
    return length;
}

int main(){
    char line[LINE];
    while(getline1(line) != 0){
        printf("%s\n", line);
        char line[LINE];
    }
    return 0;
}

但我遇到分段错误,我不明白为什么?

输入 ./main

find_input.txt:

一个

b

已编辑:

我在 while 中添加了 while(ch != '\n' && ch != EOF && length < LINE),但现在我得到了一个垃圾。出于某种原因,我没有在文件末尾退出。

【问题讨论】:

  • 您声明了两次char line[LINE];。一次在外面,一次在while 块内。块内的那个没有初始化,可能会导致打印很长的%s,其中包含大量垃圾。删除块中的定义
  • @PaulOgilvie 你是对的,但块内的那个从未使用过
  • Gal Leshem,不要编辑您寻求支持的代码错误。
  • Gal Leshem,当我说“删除块中的定义”时,我的意思是从你的代码中删除它,尝试一下,如果它解决了问题,然后报告。我并不是要从您发布的代码中删除它。
  • scanf() 返回读取的字符数,或 EOF... EOF 未放入变量“ch”中。你应该在你的 while() 中检查它的返回码(它是一个 INT)。换句话说 "int rc; rc = scanf("%c", &ch); while(rc == 1 && ch != '\n' && length

标签: c


【解决方案1】:

由于未检查 scanf 函数的返回值,您的程序失败。此外,表达式 (ch != EOF) 在您的 while 循环中作为控制表达式的一部分毫无意义。您正在根据 EOF 检查 char 变量 (ch)。这几乎总是表明代码中有错误。 EOF 不是一个字符:它是一个具有 int 类型(和一个负值)的整数常量表达式,由几个标准库函数返回以指示 文件结束(或有时输入错误)。例如,如果在任何转换之前发生输入失败,scanf 函数将返回 EOF。否则,它返回分配的输入项的数量,可以为零。所以你要实现的功能可以写成:

int getline1(char s[])
{
    char ch;
    int length = 0;
    /* The scanf call below will return 1 if it reads a character from stream */
    while (scanf("%c", &ch) == 1 && ch != '\n')
            s[length++] = ch;

    s[length] = '\0';
    return length;
}

但是上面的函数有个致命的缺陷:它不知道调用函数中数组的长度。参数 s 只是从函数的角度来看的一个指针,不可能仅从指针确定该信息。如果从流中读取的字符数大于数组的大小,它将不会在数组末尾停止写入。相反,它继续写到最后并进入它不拥有的内存。 此功能不能安全使用。因此,数组大小必须作为此类函数的参数传递。所以更安全的实现可能是:

int getline1(char s[], int size)
{
    char ch;
    int length = 0;

    if (size < 1)
            return 0;

    while (length < size - 1 && scanf("%c", &ch) == 1 && ch != '\n')
            s[length++] = ch;

    s[length] = '\0';
    return length;
}

这个函数应该像这样调用

getline1(line, sizeof line)

如果字符数组的原始定义行是可见的。

注意:C 程序员通常更喜欢使用 getchar 函数从 stdin 中读取一个字符。为此目的使用 scanf(带有 %c)本身不是错误,但可能效率低下。

【讨论】:

  • 非常好的答案!
猜你喜欢
  • 2022-10-04
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 2019-06-08
  • 1970-01-01
  • 2014-05-02
  • 2020-08-14
相关资源
最近更新 更多