fscanf 作为 while 语句

fscanf as a while statement

大家好,希望你们都好。

我正在尝试计算 fscanf 函数从文件中读取了多少次。我无法处理大约 2 个小时。我不知道为什么会这样。在 VSCode 和 CodeBlocks 中,此代码片段可以正常工作。 顺便说一句,我正在使用 C 语言。

while(fscanf(fpt,"%d",&numpt)!=EOF)
{
    printf("grayvalues = %d\n",numpt);  
}

我正在尝试使用计数变量来计算循环工作的次数。它甚至不起作用。你能帮帮我吗?

int numpt;
int count = 0;
while(fscanf(fpt,"%d",&numpt)!=EOF)
{
 
   
   printf("grayvalues = %d\n",numpt);
   count=count +1;

}

源代码在这里

#include <stdio.h>
#include <stdlib.h>

int main()
{
char _name[] = "xc.ascii.pgm";
FILE *fpt;

char* buffp2;
fpt = fopen(_name,"r");

fgets(buffp2,70,fpt);
printf("p2 line will be written = %s\n",buffp2);

fgets(buffp2,70,fpt);
printf("%s\n",buffp2);

int col;
fscanf(fpt,"%d",&col);
printf("%d\n",col);

int row;
fscanf(fpt,"%d",&row);
printf("%d\n",row);

int max_g;
fscanf(fpt,"%d",&max_g);
printf("max gray val = %d\n",max_g);


printf("file matrix elements = \n");

int numpt;
int count = 0;
while(fscanf(fpt,"%d",&numpt)!=EOF)
{
    printf("grayvalues = %d\n",numpt);
// count=count +1;      
// printf("count = %d\n",count);
}

printf("file is read\n");

fclose(fpt);

return 0;

}

我已经创建了一个 pgm 文件,我正在尝试打开它。

P2
# xc.ascii.pgm
24 7
15
0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0
0 3  3  3  3  0  0  7  7 7  7  0  0 11 11 11 11 0  0 15 15 15 15  0
0 3  0  0  0  0  0  7  0 0  0  0  0 11  0  0  0 0  0 15  0  0 15  0
0 3  3  3  0  0  0  7  7 7  0  0  0 11 11 11  0 0  0 15 15 15 15  0
0 3  0  0  0  0  0  7  0 0  0  0  0 11  0  0  0 0  0 15  0  0  0  0
0 3  0  0  0  0  0  7  7 7  7  0  0 11 11 11 11 0  0 15  0  0  0  0
0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0  0 0  0  0  0  0  0  0



file name is xc.ascii.pgm

用代码

char* buffp2;
fpt = fopen(_name,"r");

fgets(buffp2,70,fpt);

您正在使用未初始化的指针读入内存,因此它可能会崩溃。它甚至不会进入您的 while 循环。

很明显,您在阅读输入的许多方面都遇到了困难。关键是验证每一步。对于初学者,不要硬编码文件名或使用幻数。你不应该 re-compile 你的程序只是为了从不同的文件中读取。 70 是一个神奇的数字。您可以通过简单地定义一个常量并将要读取的文件名作为参数传递给您的程序来处理这两者。 (这就是 main()int argc, char **argv 参数的用途)。您也可以将文件名作为输入——您的选择。

例如,您可以开始您的代码。

#include <stdio.h>
#include <stdlib.h>

#define MAXC 1024       /* if you need a constant, #define one (or more) */

int main (int argc, char **argv)
{
    char buf[MAXC];                             /* buffer to hold each line */
    int row, col, max_g, numpt, count = 0;
    /* use filename provided as 1st argument (stdin by default) */
    FILE *fpt = argc > 1 ? fopen (argv[1], "r") : stdin;
    
    if (!fpt) { /* validate file open for reading */
        fputs ("error: file open failed.\n", stderr);
        return 1;
    }

(注意: 程序将从作为程序第一个参数给出的文件名中读取,如果没有给出参数,则默认情况下将从 stdin 中读取. 一个三进制用来控制一个文件是否打开或者stdin简单赋值给fpt)

打开文件进行阅读并验证打开后,您可以开始将第一行读入 buf。注意 fgets() 读取并包含 '\n' 及其填充的缓冲区,因此您需要在输出中考虑到这一点。

    if (!fgets (buf, MAXC, fpt)) {              /* read/validate first line */
        fputs ("error: EOF\n", stderr);
        return 1;
    }
    printf("p2 line will be written = %s", buf);

现在您可以阅读并丢弃任何注释行并阅读包含 colrow 的行:

    /* read/ignore all comment lines, read col & row line */
    while (fgets (buf, MAXC, fpt) && *buf == '#')
        printf ("%s", buf);
    
    /* parse col & row from buf */
    if (sscanf (buf, "%d %d", &col, &row) != 2) {
        fputs ("error: invalid row/col format.\n", stderr);
        return 1;
    }
    printf ("col: %d, row: %d\n", col, row);

你明白了,用 fgets() 读取,然后使用 sscanf() 从缓冲区解析你需要的任何值(或者你可以使用一对指针手动完成,或者无数来自 string.h 的字符串函数的帮助)

下一行是最大灰度线,按照正常的read fgets()路线,sscanf()解析:

    if (!fgets (buf, MAXC, fpt)) {              /* read/validate max grayscale line */
        fputs ("error: EOF\n", stderr);
        return 1;
    }
    /* parse max grayscale from buf */
    if (sscanf (buf, "%d", &max_g) != 1) {
        fputs ("error: invalid max_g format.\n", stderr);
        return 1;
    }
    printf ("max gray val = %d\nfile matrix elements = \n", max_g);

现在您可以读取灰度值了。虽然您可以使用 fgets()sscanf() 方法,然后使用 "%n" 来捕获每次转换为 int 时消耗的字符数,但这里使用起来同样简单fscanf() 阅读直到 运行 出整数值:

    /* read all integer grayscale values */
    while (fscanf (fpt, "%d", &numpt) == 1) {
        int col1 = 0;                           /* flag indicating 1st col in row */
        if (count && count % col == 0) {        /* if not row1 and count % col == 0 */
            col1 = 1;                           /* set 1st col flag */
            putchar ('\n');                     /* output newline */
        }
        /* if 1st col in row, format as "%2d", otherwise " %2d" */
        printf ((!count || col1) ? "%2d" : " %2d", numpt);
        count += 1;                             /* increment count */
    }
    putchar ('\n');             /* tidy up with '\n' */

(注意: 三元运算符在 printf() 格式语句中用于控制在第 2 列的每个 2 位值之前输出一个 space直到最后,同时在第一列的值之前没有输出 space。三进制只是一种 shorthand,内联 if .. else 控制事物的方式。col1 标志只是控制在输出每个第一个 col 值之前输出一个 '\n',而不是第一行)

最后,仅仅因为你已经读取并输出了灰度值,并不意味着你有正确的数字,验证,验证,验证:

    if (count != col * row) {   /* validate col * row grayscale values read */
        fputs ("error: invalid grayscale count.\n", stderr);
        return 1;
    }
    
    printf("file is read\n");   /* all done */
    
    if (fpt != stdin)           /* close file if not reading stdin */
        fclose (fpt);
}

仅在验证读取了正确数量的 colrow 值后才输出 "file read"

例子Use/Output

从您的文件 xc.ascii.pgm 中读取,您将收到以下输出。

$ ./bin/pgmread dat/xc.ascii.pgm
p2 line will be written = P2
# xc.ascii.pgm
col: 24, row: 7
max gray val = 15
file matrix elements =
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
 0  3  3  3  3  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15 15 15 15  0
 0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0 15  0
 0  3  3  3  0  0  0  7  7  7  0  0  0 11 11 11  0  0  0 15 15 15 15  0
 0  3  0  0  0  0  0  7  0  0  0  0  0 11  0  0  0  0  0 15  0  0  0  0
 0  3  0  0  0  0  0  7  7  7  7  0  0 11 11 11 11  0  0 15  0  0  0  0
 0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0  0
file is read

检查一下,如果您还有其他问题,请告诉我。