代码无法正常运行

时间:2013-09-09 05:05:36

标签: c

此代码用于将图像文件中的值读取到数组中(我知道大小为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);
}

3 个答案:

答案 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);