【问题标题】:Printf printing garbage after read() call. The offset is always printed as 0在 read() 调用后 Printf 打印垃圾。偏移量始终打印为 0
【发布时间】:2015-01-07 15:05:00
【问题描述】:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <stdint.h>

int main()
{
    int file;
    off_t offset;

    if((file=open("testfile.txt",O_RDONLY)) < -1)
            return 1;

    char buffer[19];

    if(read(file,buffer,19) != 19)  return 1;
    fprintf(stdout,"%s\n",buffer);


    if(offset = lseek(file,-19,SEEK_END) < 0) return 1;
    fprintf(stdout,"%jd\n",(intmax_t)offset);

    if(read(file,buffer,19) != 19)  return 1;
    fprintf(stdout,"%s\n",buffer);

    return 0;
}

输出如下:

这是一个测试文件��

0

这是一个测试文件

��

testfile.txt:

这是一个测试文件 测试 SEEK_END 的工作原理 这是一个测试文件

我尝试了不同的偏移格式,例如 %ld,%d,但输出仍然相同。 无法弄清楚为什么垃圾会出现在第一行和最后一行的末尾。请帮忙。

【问题讨论】:

  • 你不会终止你的字符串。
  • 我必须专门使用 open() 系统调用并使用 fd 进行其他系统调用并传递它。我正在处理的项目处理读取和写入二进制文件并在不同进程之间共享它。我不想通过包含几乎所有地方都使用 open() 的 fopen() 来使代码变得混乱。因此,坚持开放。

标签: c file printf offset lseek


【解决方案1】:

您需要为行尾字符“\0”留出空间;

所以让char buffer[19]; char buffer[20]; 然后加上buffer[19] = '\0'; - 请记住它是从零开始的计数。那么它不应该有垃圾数据。

原因是 printf 不知道字符数组的末尾在哪里。所以它会一直打印,直到它在垃圾内存中找到一个'\0'。

【讨论】:

    【解决方案2】:

    read 对字符串一无所知,它从文件中读取字节。因此,如果您将 19 个字节读入“缓冲区”并且没有终止 \0 则它不是有效的字符串。

    因此,您要么需要确保缓冲区为 0,要么只打印前 19 个字节,例如printf( "%.*s", sizeof(buffer), buffer ); 或扩展 \0 的缓冲区,例如char buffer[20] = {0};

    您还应该像这样打开文件以确保 lseek 正常工作(文件必须以二进制模式打开)

    if((file=open("testfile.txt",O_RDONLY|O_BINARY)) == -1) // returns -1 by failure
    {
      perror("testfile.txt"); // to get an error message why it failed.
      return 1;
    }
    

    当某些事情失败时给出错误消息总是好的,而不是仅仅终止程序。

    【讨论】:

    • 我都试过了,效果很好。非常感谢。但仍然无法弄清楚为什么偏移量打印为 0。由于两次都正确读取,我猜这只是打印方案的问题。可能是什么问题?
    • @ShravanB 您通过写入lseek(file,-19,SEEK_END) 将文件指针重新定位到文件的开头,因此偏移量返回为0是正确的,-19 是文件的相对结尾。
    • 实际上它打印的是 0,无论我在哪里寻找。我猜我选了一个不好的例子。实际问题是另一个答案指出的括号使用不正确。再次感谢。
    【解决方案3】:

    其他答案已经为打印buffer 的问题提供了解决方案。此答案解决了您帖子中的另一个问题。

    由于运算符优先级,该行

    if(offset = lseek(file,-19,SEEK_END) < 0) return 1;
    

    相当于:

    if(offset = (lseek(file,-19,SEEK_END) < 0)) return 1;
    

    我确定您打算使用:

    if( (offset = lseek(file,-19,SEEK_END)) < 0) return 1;
    

    【讨论】:

    • 知道我错过了一些简单的东西。非常感谢。应该更加小心括号。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-26
    • 1970-01-01
    • 2023-03-28
    • 2013-08-18
    相关资源
    最近更新 更多