jxh的答案正确地诊断了原始代码的问题,而这个答案没有(部分是因为这个)。它还展示了 C99 中添加的可变长度数组 VLA 的强大功能。它真的很整洁,应该被接受。
如果您坚持使用 C89(可能是因为您使用 MSVC 在 Windows 上工作),那么如果您连续分配空间,您仍然可以进行单次读取。但是,如果您还打算使用双索引表示法,您仍然需要指针数组,或者您将需要使用这种表示法img[i*v+j]
(以及不同的类型img
)。这段代码实现了额外的指针数组,还包括对原始代码的各种其他小错误修复(最重要的是它在打开文件失败后返回,而不是报告“错误”并继续,好像什么都没有出错了,包括尝试fclose()
空指针,这对崩溃有好处)。
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
const char *filename = "test.pgm";
FILE *fin = fopen(filename, "rb");
if (fin == NULL)
{
fprintf(stderr, "ERROR opening file %s\n", filename);
return(1);
}
int i;
int j = 0;
int u=16;
int v=8;
char test[20];
int k;
while ((k = fgetc(fin)) != '\n')
test[j++] = k;
test[j] = '\0';
printf("test: %s\n", test);
char **img = (char**) calloc(u,sizeof(char*));
char *space = (char *)calloc(u*v, sizeof(char));
for (i = 0; i < u; i++)
img[i] = &space[v*i];
if (fread(img[0], 1, (u*v), fin) != (size_t)(u*v))
{
fprintf(stderr, "Error: short read\n");
return(1);
}
for (i = 0; i < u; i++)
{
for (j = 0; j < v; j++)
printf("%3d ", img[i][j]);
printf("\n");
}
fclose(fin);
free(img[0]);
free(img);
return(0);
}
请注意,读入的循环test
没有正确检查错误;它可能会溢出,并且它也不会检测到 EOF。
输入数据:
abcdefghij
aaaaaaa
bbbbbbb
ccccccc
ddddddd
eeeeeee
fffffff
ggggggg
hhhhhhh
iiiiiii
jjjjjjj
kkkkkkk
lllllll
mmmmmmm
nnnnnnn
ooooooo
ppppppp
输出数据:
test: abcdefghij
97 97 97 97 97 97 97 10
98 98 98 98 98 98 98 10
99 99 99 99 99 99 99 10
100 100 100 100 100 100 100 10
101 101 101 101 101 101 101 10
102 102 102 102 102 102 102 10
103 103 103 103 103 103 103 10
104 104 104 104 104 104 104 10
105 105 105 105 105 105 105 10
106 106 106 106 106 106 106 10
107 107 107 107 107 107 107 10
108 108 108 108 108 108 108 10
109 109 109 109 109 109 109 10
110 110 110 110 110 110 110 10
111 111 111 111 111 111 111 10
112 112 112 112 112 112 112 10