【问题标题】:Segmentation fault in c when reading a line读取一行时c中的分段错误
【发布时间】:2014-06-01 11:20:42
【问题描述】:

我想读取用户输入(如终端),直到写入退出或 ctrl+c/ctrl+d 被按下。我阅读每一行(直到按下返回/输入),检查它是否只是空格或注释(#),然后执行一些函数。

我尝试了三种方法,但都没有成功。每次插入字符串并按 Enter 时都会出错

char line[256];
while(printf("%s>", shell_name) && scanf("%50[^\n]", line) != EOF)
{

分段错误(核心转储)

while(printf("%s>", shell_name) && getline(line, 100, stdin) != EOF)

注意:预期为“size_t * restrict”,但参数的类型为“int”

while(printf("%s>", shell_name) && fgets(line, sizeof(line), stdin) != NULL)
{

分段错误(核心转储)

为了获得更多的指导,我接下来会这样做

if(isspace(&line) == 0 && &line[0] != "#")

我做错了什么?有没有更合适/简单/更好的选择?

【问题讨论】:

  • 有趣——我注意到的第一件事是你似乎确信这没关系:printf("%s", strcat(shell_name, ">")),因为你到处都在使用它。请改用printf("%s>", shell_name)
  • 愚蠢的错误 :) 痴迷于 strcat
  • 解决了吗? :D 所以要么shell_name 是一个静态字符串(所以它可能不会被修改),或者strcating 很多字符使它溢出?
  • 不不,它以前工作过,它打印 mysh> 并等待输入,但是一旦我输入命令并按 Enter,我就会得到分段错误
  • 您想要*lineline[0] 而不是&line。请不要忽略编译器警告,尤其是关于类型不匹配的警告。

标签: c line next


【解决方案1】:

段错误可能是因为您进入了无限循环:scanf("%50[^\n]", line) 读取您的输入并在返回处停止。 Return 不会被消耗并保留在输入缓冲区中。那么下一次会发生什么呢? scanf 检查输入缓冲区,嘿!有回报!所以它停止阅读。等等。

scanf 格式字符串中添加一个空格作为第一个字符可以解决:

int main()
{
    char line[256];
    char *shell_name = "mysh";

    while (printf("%s>", shell_name) && scanf(" %50[^\n]", line) != EOF)
    {
        printf ("you entered [%s]\n", line);
    }
    printf ("done.\n");
    return 0;
}

进一步说明,这是错误的:

if(isspace(&line) == 0 && &line[0] != "#")

-- gcc 抱怨

warning: passing argument 1 of 'isspace' makes integer from pointer without a cast
warning: comparison with string literal results in unspecified behavior

isspace(&line) 上的第一个,您可能指的是isspace(line[0])&line[0] != "#" 上的第二个,可以更简洁地写成line[0] != '#'


getline

getline 与其他“从标准输入获取”函数不同,因为它会在被要求时自动分配内存。由于它需要返回的不是一个,而是 三个 结果(字符数、输入的字符串及其长度),您需要提供 pointers 到字符串和大小参数:

size_t line_size = 0;
char *ptr_to_line = NULL;

while (printf("%s>", shell_name) && getline(&ptr_to_line, &line_size, stdin) != -1)
      ...

当使用这种方式时,您不应该使用静态字符串大小分配,因为该函数将填充适当的值。 (但不要忘记它在内部使用mallocrealloc,所以请确保free 结果。它第一次使用malloc,之后使用realloc 调整大小。)

【讨论】:

  • 如果getline 想要重新分配缓冲区,char *ptr_to_line = line; 会给你带来麻烦。使用0NULL 是更好的选择!
  • 谢谢,将“可以”改为“应该”。应该这样做:)
  • 我会更改整个代码块。你永远无法确定没有人会在不阅读它下面的文字的情况下使用它。
  • @rmartinjak 实际上,如果我按空格(一次或多次)然后按 enter 程序不会忽略它,但仍在等待输入。另外,我将如何忽略输入,尝试 line[0] != '\n',但它不起作用
猜你喜欢
  • 2022-10-04
  • 1970-01-01
  • 2016-01-12
  • 2019-03-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-11
相关资源
最近更新 更多