【问题标题】:read() function error in CC中的read()函数错误
【发布时间】:2017-02-10 10:49:14
【问题描述】:

我正在尝试从 .txt 文件中读取,直到点击字符“=”。文本文件总是一样的,只包含这些字符串:

TaskLimit=3
cc pr.c && ./a.out

有时代码运行良好并退出 while 循环,有时它会打印“TaskLimit”,但随后会抛出“Segmentation fault (core dumped)”错误。任何想法我做错了什么?我应该清除 buf[] 还是什么?

   char buf[1];

   file = open(argv[1], O_RDONLY);
   if (file == -1){
      perror("Error opening file");
      exit(1);
   }
   while(1){
       read(file, buf, 1);
       if(buf[0]=='=') {printf("I'm out");break;}
       printf("%c",buf[0]);

   //further actions

编辑: 在“进一步的行动”中,我试图将 char 转换为 int,这似乎是问题所在:

char limit_char[0];
int limit;
read(file,limit_char,1);
limit=atoi(limit_char[0]);

编辑2: 改变这一行

limit=atoi(limit_char[0]);

limit=atoi(&limit_char);

帮助。

【问题讨论】:

  • 如何检查read 调用是否真的成功?如果它给出错误,了解什么错误可能很有用。
  • 我假设plik 应该是file?请也进行编辑以解决此问题。
  • 无论如何,您应该在此类问题中提供minimal reproducible example。您显示的代码中没有任何内容会产生段错误。
  • 除非你正在做例如非阻塞 I/O,否则一般建议你使用 C 标准 fopen() 和相关函数而不是 POSIX open()
  • 与您的问题无关:一次从文件中读取 1 个字节不是一个好主意。

标签: c file


【解决方案1】:

C 编程中最重要的部分是检查返回值。

在您的示例代码示例中,您为open(2) 执行此操作,但不是为read(2) 执行此操作,您应该这样做,因为它不仅会告诉您是否有错误,还会告诉您已读取了多少字节。手册页摘录:

   On success, the number of bytes read is returned (*zero indicates end of file*),
   and the file position is advanced by this number.

也就是说,知道没有更多要读取的内容(返回值为零)可以让您在用户给您无效文件的情况下中断循环。

当您学习 C 语言时,我建议(以及该站点上的几乎每个人)始终使用 -Wall -Wextra -Werror 进行编译。 C 是一种简朴的语言,掌握它需要纪律。 GCC(或任何你的编译器)永远不会让你执行:

limit=atoi(&limit_char);

因为&limit_char 的类型实际上是char **,而atoi 需要const char *

【讨论】:

    【解决方案2】:

    atoi 需要一个以 NULL 结尾的 char 数组,因此您的数组需要比您正在读取的多 1 个元素。

    char limit_char[2];
    int limit;
    read(file,limit_char,1);
    limit_char[1]='\0';
    limit=atoi(limit_char);
    

    除此之外,您可能应该检查来自read 的返回值,以确保您确实读入了一些内容。

    【讨论】:

    • NULLNUL 不同。你想要NUL,它是'\0' 字符。 NULL 是一个指针值。
    • NUL 是 ASCII 中 '\0' 字符的名称,但它仍称为以 NULL 结尾的字符串 en.wikipedia.org/wiki/Null-terminated_string
    • 在这种情况下,nullNULL 也不同。请注意维基百科页面从不大写Nullnull
    • 完全大写的NULL 被 C 标准定义为评估“空指针”的宏(标准也很好地使用 正是这个拼写),所以将它的用法视为“保留”。
    • 这听起来有点挑剔,但在这里准确可以让大家避免误解,这可能会导致某人做一些丑陋的事情,比如char s[42]; s[0] = NULL; 来终止一个 C 字符串,实际上应该是 ... s[0] = '\0';或者只是... s[0] = 0;
    【解决方案3】:
    1. 在您的代码中,您引用 argv[1] 获取文件名,但在示例用法 (cc pr.c && ./a.out) 中您没有指定任何文件名。

    2. 在你的read() 语句中,你使用了一个没有在任何地方定义的变量plik,在这里使用file,即你用来存储`open() 结果的变量。

    解决这个问题,它会起作用。

    【讨论】:

    • 我并不担心 txt 文件的后面部分,我只是想先读取“=”字符后面的数字。我已经更正了错误,我从错误的 .c 文件中复制了这一行,对此感到抱歉。
    【解决方案4】:

    这声明了一个长度为零的数组,这没有多大意义。顺便说一句:通常编译器应该至少发出一个警告。

    char limit_char[0];
    

    这行不通,您需要一个长度为 1 的数组,因为您使用 read 读取了 1 个字节:

    char limit_char[1];
    

    或者更确切地说:

    char limit_char;
    ...
    read(file, &limit_char, 1);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-10
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多