c - 尝试将输入存储在具有意外行为的结构类型数组中

标签 c arrays pointers struct io

我正在尝试制作一个读取文本文件的程序。文本文件包含代表 rgb 数字的数字。 test.txt 示例:

P3
3 4       
255
12 32 222 12 32 222 12 32 222 12 32 222 12 32 222 12 32 222 12 32 222 
12 32 222 12 32 222 12 32 222 12 32 222 12 32 222

模拟 PPM 文件。然后我忽略第一行,读取以下三个整数用于以后的计算。我一直在测试的不正常行为是尝试将以下数字存储在结构类型 RGB 的数组中,该数组包含三个类型为 unsigned char 的元素:r、g、b。我不明白的是,当我尝试打印前几个元素时,我的第一个像素(第一个结构,第一个 r、g、b)是正确的,然后,接下来的三个数字是随机的,之后的每次执行都会生成那个用随机数设置。其余为零。我虽然我的理解是正确的,但有人可以帮助我吗?代码:

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

RGB *readPPM(const char *file, int *width, int *height, int *max) 

{
width = malloc(sizeof(int)*10);         
height = malloc(sizeof(int)*10);
max = malloc(sizeof(int)*3);        

FILE *fp;                               
int numOfPix, i=0;
char garbage[3];                                                        

if ((fp = fopen(file,"r")) == NULL)                                         
{
    printf("No such file exists!");
}

fgets(garbage,sizeof(garbage),fp);                                      
fscanf(fp,"%d %d %d",width,height,max);                             
int numofPix = (*width) * (*height);            
RGB pixels[numOfPix];                                       
RGB *returnptr = pixels;
printf("w: %d h: %d m: %d pix: %d\n",*width,*height,*max,numofPix);
while (!feof(fp))
{
    fscanf(fp,"%hhd %hhd %hhd", &pixels[i].r, &pixels[i].g, &pixels[i].b);
    i++;    
}
fclose(fp);
return returnptr;
}

int main()
{
RGB *RGBValues;
int *width, *height, *max;
int j=0;
char *testfile = "test.txt";
RGBValues = readPPM(testfile,width,height,max); 
for(j=0;j<5;j++)
{
printf("r: %d g: %d b: %d\n",RGBValues[j].r,RGBValues[j].g,RGBValues[j].b);
}
}

filter.h中的结构体定义:

typedef struct { unsigned char r, g, b; } RGB;

示例输出:

w: 3 h: 4 m: 255 pix: 12        //Correct
r: 12 g: 32 b: 222              //Correct
r: 232 g: 253 b: 85            //Changes every execution
r: 0 g: 0 b: 19                //Static
r: 0 g: 0 b: 0                //Static
r: 0 g: 0 b: 0                  //Static

最佳答案

您正在声明指针 int *width, *height, *max; 并将它们传递给 readPPM。然后在 readPPM 中放置

width = malloc(sizeof(int)*10);         
height = malloc(sizeof(int)*10);
max = malloc(sizeof(int)*3); 

这些 malloc 分配为 widthheightmax 创建整数数组。显然,创建宽度和高度数组不是您的意图。不要那样做。只需声明整数并传递地址。

也不要使用while(feof(fp)),而是检查fscanf的返回值,如果fscanf则中断循环> 失败。

正如评论中所指出的,RGB pixels[numOfPix] 在函数退出时被销毁。在这种情况下,请对 RGB *pixels 使用 malloc。这将在堆上创建内存,函数退出时它不会被销毁。您稍后必须释放该内存。

RGB *readPPM(const char *file, int *ptr_width, int *ptr_height, int *ptr_max)
{
    int width, height, max;

    FILE *fp;
    int numOfPix, i = 0;
    char garbage[3];

    if((fp = fopen(file, "r")) == NULL)
    {
        printf("No such file exists!");
    }

    fgets(garbage, sizeof(garbage), fp);
    fscanf(fp, "%d %d %d", &width, &height, &max);
    int numofPix = width * height;
    RGB *pixels = malloc(numofPix * sizeof(RGB));
    printf("w: %d h: %d m: %d pix: %d\n", width, height, max, numofPix);
    while(fscanf(fp, "%d %d %d", &pixels[i].r, &pixels[i].g, &pixels[i].b) == 3)
    {
        i++;
    }
    fclose(fp);

    *ptr_width = width;
    *ptr_height = height;
    *ptr_max = max;

    return pixels;
}

int main()
{
    RGB *RGBValues;
    int width, height, max;
    int j = 0;
    char *testfile = "test.txt";

    //pass the address of width, height, and max
    RGBValues = readPPM(testfile, &width, &height, &max);
    for(j = 0; j<5; j++)
    {
        printf("r: %d g: %d b: %d\n", RGBValues[j].r, RGBValues[j].g, RGBValues[j].b);
    }

    //width, height, max should be modified:
    printf("%d %d %d\n", width, height, max);

    //free the memory which was allocated in `readPPM`
    free(RGBValues);
}

关于c - 尝试将输入存储在具有意外行为的结构类型数组中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47544272/

相关文章:

c - Makefile编译多个C程序?

c++ - rtai no such file or directory 错误编译

C - 声明一个具有未定义值的数组

c - tcp socket hungry 程序是否会干扰文件系统 I/O

javascript - 如何找到数组中缺少的下一个字符?

java - 从 Java 传递到 C 后未初始化的 JNA 结构数组

c - C 中的运算符优先级(指针算术)

c - 使用 malloc 的多个数组

c - ASCII 字符未打印出来

c - 在 C99 的结构中分配指向二维空数组的指针