此代码用于将图像文件中的值读取到数组中(我知道大小为16 * 8)。
当我动态创建img数组以便我可以拥有任何大小的图像时,它会在运行时崩溃,当我手动设置正确的大小(char img[16][8];
)时它会起作用。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main()
{
FILE *fin;
fin= fopen ("test.pgm","rb");
if (fin == NULL)
{
printf ("ERROR");
fclose(fin);
}
int i=0,j=0,u=16,v=8,d;
char test[20];
char k;
char c[10];
while((k=fgetc(fin))!='\n')
{
test[j]=k;
j=j+1;
}
char **img = (char**) calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = (char*) calloc(v,sizeof(char));
}
fread(img,1,(u*v),fin);
for (i=0; i<u; i++)
{
for (j=0; j<v; j++)
{
printf("%d ",img[i][j]);
}
printf("\n");
}
fclose(fin);
}
答案 0 :(得分:3)
由于您正在动态分配16个独立的8字节数组,因此您需要为每个数组计算16个单独的读数。 (我已经删除了不必要的,可能容易出错的演员阵容到calloc()
)。
char **img = calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = calloc(v,sizeof(char));
fread(img[i],1,v,fin);
}
/*fread(img,1,(u*v),fin);*/
您为fread()
工作的单char img[16][8]
次呼叫,因为在这种情况下,img
由大小为16 * 8
字节的连续内存组成。但是,该调用对于您创建动态分配的数组的方式不起作用,因为img
现在是一个指针数组,因此您所拥有的fread()
调用将使用来自的数据覆盖这些指针值。文件。
如果您想对fread()
进行一次调用,那么您可以更改动态分配(并与VLA结合使用)
char (*img)[v];
img = malloc(u * sizeof(*img));
fread(img,1,(u*v),fin);
这声明img
是指向v
的数组char
的指针(v
已初始化为8)。然后,它在u
的连续分配中为v
的许多数组char
分配img
(即16)。现在,img
可以像fread()
一样用于单char img[16][8]
次调用,也可以保留img
的相同“2D”地址。
答案 1 :(得分:2)
answer jxh正确诊断了原始代码的问题,而这个答案却没有(部分是因为这个原因)。它还展示了可变长度阵列(VGA)的强大功能,它们被添加到C99中。这真的很整洁,应该被接受。
如果您遇到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
答案 2 :(得分:0)
你进入你的指针数组,但它们指向内存中的各个位置,这样就无法工作了。
为了使它工作,设置指针指向相同的块,但是在不同的偏移
所以而不是
char **img = calloc(u,sizeof(char*));
for ( i = 0; i < u; i++ )
{
img[i] = calloc(v,sizeof(char));
}
DO
char **img = calloc(u,sizeof(char*));
char *block = calloc(u*v,sizeof(char);
for ( i = 0; i < u; i++ )
{
img[i] = block + v*i;
}
然后
fread(block,1,(u*v),fin);