【问题标题】:Reading ppm files and using fscanf()读取 ppm 文件并使用 fscanf()
【发布时间】:2011-07-10 01:42:17
【问题描述】:

我正在尝试解析 ppm 文件,但首先需要验证标头信息是否正确。一个 ppm 文件可能有以下格式:

P3
100 100
255
data...

p3
100 100
255
data...

我使用fscanf (file_stream, "P3 %d %d %d", &width, &height, &max_colour); 来验证标题信息。我想知道的是,如何在验证标头信息后继续读取数据(char by char)。

【问题讨论】:

    标签: c ppm


    【解决方案1】:

    假设标头告诉您数据的大小,然后分配一个足够大的内存块并使用 fread() 在一次调用中读取它 - 这比一次读取一个字节要快得多。

      unsigned char *data = malloc(width*height); // or whaterver size
      fread(file_stream,width*height,1,data);
    

    【讨论】:

      【解决方案2】:

      fscanf 字符串的末尾添加一个%*[\n] 以吃掉标题中的最后一个换行符,然后您可以使用fread 从文件的其余部分读取原始字节(假设您以二进制打开它模式)。

      【讨论】:

      • 实际上,在格式字符串中放入\n 会导致它吃掉所有连续的空格——如果随后的二进制数据恰好以09、@987654326 中的任何一个字节开头@ 或 20(制表符、换行符或空格),那么它们将被意外消耗。你真的很想使用%*c 格式说明符,它总是会吃掉一个字符的输入。
      • @Adam:我现在改成的正确吗?那是试图停在第一个\n。但是,它仍然假定文件是正确的,除非您正确检查 scanf 结果。
      • @Adam:实际上,查看 PPM 规范,任意空格是不允许的;它只是一个换行符。
      【解决方案3】:

      有什么理由不使用netpbm 库吗?

      【讨论】:

        【解决方案4】:

        使用fscanf,您可以使用"%c" 读取字符。

        char ch;
        while (fscanf(file_stream, "%c", &ch) == 1) {
            /* process ch */
        }
        

        但是你可以使用fgetc()而不是fscanf

        int ch;
        while ((ch = fgetc(file_stream)) != EOF) {
            /* process ch */
        }
        

        但是,假设 ppm 文件使用 ASCII 编码(P1、P2 或 P3),fscanf 是一个非常好的选择。

        /* P3 format */
        if (fscanf(file_stream, "%d%d%d", &red, &green, &blue) == 3) {
            /* RGB triplet read; process it */
        }
        

        如果要处理二进制 PPM,请记住以二进制模式打开文件

        fopen(filename, "rb");
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-03-22
          • 1970-01-01
          相关资源
          最近更新 更多