【问题标题】:Storing an array from a file then writing it to another file从文件中存储一个数组,然后将其写入另一个文件
【发布时间】:2022-01-26 14:52:37
【问题描述】:

这部分代码我已经有一段时间了。我应该将 ppm 文件中的像素值存储在一个数组中,然后在按键时将它们写入另一个文件。一个多星期以来,我一直在尝试同一段代码,但它似乎仍然不起作用。非常感谢任何帮助(这不是我的全部代码,而只是与问题相关的部分)。似乎发生的情况是,在读取文件进行写入后,代码似乎停止运行,所以我不知道数组是否已成功分配。对不起,如果它有点乱,我更注重功能而不是整洁。

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

#define RGB_COMPONENT_COLOUR 255
#define height 1080
#define width 1920

typedef struct
{
    unsigned char red, green, blue;
} PPMPixel;

typedef struct
{
    int x, y;
    PPMPixel *data;
} PPMImage;

int main(PPMImage *readPPM())
{
    char key = 0;
    do
    {
        printf("\tPress r to read in an image in ppm format\n");
        printf("\tPress s to save image in ppm format\n");
        printf("\tPress q to quit\n");

        {
            scanf("\t %c", &key);
            fseek(stdin, 0, SEEK_END);
            switch(key)
            {
                FILE *fp, *pf;
                PPMImage *img;
                int i, j;
                int **array = malloc(height * sizeof(int*));
                array[i] = malloc(width * sizeof(int));
                case 'r' :
                {
                    char buff[16];
                    int c, rgb_comp_colour;
                    int e;
                    char fname[100];
                    printf("Enter file name: ");
                    scanf("%s", fname);
                    fseek(stdin,0,SEEK_END);
                    fp = fopen(fname, "r");
                    if (fp == NULL)
                    {   
                        printf("\tError while opening the file\n");
                    }                        
                    else    
                    {
                        printf("\tReading in %s\n", fname);
                    }

                    if (fp)
                    {
                        while ((e = getc(fp))!=EOF)
                        putchar(e);

                        if (!array)
                        {
                            perror("\tError occured allocating memory to the array\n");
                            exit(1);
                        }
                        else
                        {
                            printf("\tMemory allocated to the array successfully\n");
                        }

                        for(i=0;i<width;i++)
                        {
                            for(j=0;j<height;j++)
                            {
                                fseek(fp, 0, SEEK_SET);
                                fscanf(fp, "%d", &array[i][j]);
                            }
                        }
                    else
                    {
                        printf("\tCould not successfully allocate array\n");
                    }
                
                }
                break;
            
                case 's' :
                {
                    char fname2[100];
                    printf("Enter file name: ");
                    scanf("%s", fname2);
                    fseek(stdin,0,SEEK_END);
                    pf = fopen(fname2, "w");
                    if (pf == NULL)
                    {   
                        printf("\tError while opening the file\n");
                    }                        
                    else    
                    {
                        printf("\tWriting in %s\n", fname2);
                    }
                
                    for(i=0;i<width;i++)
                    {
                        for(j=0;j<height;j++)
                        {
                            fseek(pf, 0, SEEK_SET);
                            fprintf(pf, "%d ", array[i][j]);
                        }
                    }
                    if (!array[i][j])
                    {
                        printf("File write error");
                    }
                    else
                    {
                        printf("File written successfully");
                    }
                }
                break;

                case 'q' : //If q is pressed the code ends and a message is printed so the user knows the program has been terminated.
                {
                    printf("\tTerminating program...\n");
                }
                break;

                default: //If anything other than the specified case statement key presses is entered, the code is looped again and an error message is printed.
                {
                    printf("\tInvalid Input\n");
                }

                fclose(fp);
                fclose(pf);
                free(array);
                free(array[i]);
                free(img);
            }
        }
    }
    while(key != 'q');
    return 0;    
}

【问题讨论】:

  • 旁白:为什么scanf格式字符串开头有\t
  • array[i] = malloc(width * sizeof(int));你还没有分配i
  • 该行应该在for(i...) 循环内。
  • fscanf(fp, "%d", &amp;array[i][j]); 将尝试读取文本整数。您只想为 rgb 读取 3 个字节的二进制文件。为什么你还有array?您不应该直接读取PPMImage.data 数组吗?

标签: arrays c image-processing file-io switch-statement


【解决方案1】:

您应该创建几个函数:一个用于读取 ppm 文件,一个用于保存一个。这将大大简化main()。此外,我认为不需要中间数组。 malloc() PPMPixel *data; 数组后你知道宽度和高度,并使用fread() 直接将数据读入其中。

// You should not call fflush on stdin. Use this instead
void clear_to_end(FILE *fp)
{
    int c;
    while ((c = fgetc(fp)) != -1 && c != '\n') ;
}

PPMImage* load_file()
{
    char path[1024]
    printf("Enter file name: ");
    if (!fgets(path, sizeof(path), stdin)) return NULL;
    path[strcspn(path, "\n")] = '\0';

    FILE *fp = fopen(path, "rb");
    if (fp) {
        // Create a PPMImage struct
        PPMImage *img = malloc(sizeof(*img));
        if (img) {
            char buffer[1024];
            // Read the header
            fgets(buffer, sizeof(buffer), fp);
            // Some ppm files contain comments
            do {
                fgets(buffer, sizeof(buffer), fp);
            } while (buffer[0] == '#');
            // Get the dimensions
            if (2 == sscanf(buffer, "%d %d", &img->x, &img->y)) {
                int max_color;  // Not used
                fscanf(fp, "%d", &max_color);
                // The header is text, but the rest is binary data
                clear_to_end(fp);
                // Calc the size of the pixel array and allocate
                size_t bytes = sizeof(PPMPixel) * img->x * img->y;
                img->data = malloc(bytes);
                if (img->data) {
                    int items_read = 0;
                    // Read ALL the pixels
                    items_read = fread(img->data, sizeof(PPMPixel), img->x * img->y, fp);
                    if (items_read == img->x * img->y) {
                        // Success!
                        return img;
                    }
                    else {
                        free(img->data);
                    }
                }
            }
            else free(img);
        }
        fclose(fp);
    }
    return NULL;
}

void save_file(PPMImage *img)
{
    // TODO .....
}

int main()
{
    char key = 0;
    PPMImage* img = NULL;
    do {
        puts("\tPress r to read in an image in ppm format");
        puts("\tPress s to save image in ppm format");
        puts("\tPress q to quit");
        
        scanf(" %c", &key);
        clear_to_end(stdin);
        switch (key) {
            case 'r':
                // TODO: if img != NULL, free it
                img = load_file();
                break;
            case 's':
                save_file(img);
                break;
            case 'q':
                puts("\tTerminating program...");
                break;
            default:
                puts("\tInvalid Input");
                break;
        }
    } while (key != 'q');
    return 0;
}

我将函数体留空/稀疏,因为这看起来像是家庭作业。您需要填写空白并添加错误处理。

【讨论】:

  • 我会试一试,谢谢!是的,不幸的是,这是一个非常大的任务的一小部分,它在很大程度上依赖于能够访问这样的数组来进行图像处理,所以我希望能够理解如何使它工作。
  • 所以我已经在我的代码中实现了你的代码,但遇到了一些我不太确定的事情。该数组现在定义为图像,但是当我尝试执行 fscanf(fp, "%d", &image[i][j]);它告诉我它必须是指向指针类型的指针。但其他部分要求它是指向结构的指针。哪个更好用?
  • 不要使用fscanf 读取二进制数据。仅当文件是文本时才有效。我的回答中有如何一次读取所有像素:fread(img-&gt;data, sizeof(PPMPixel), img-&gt;x * img-&gt;y, fp); 首先,解析头部然后调用它。只需一次读取即可获取所有像素数据。我会更新完整的代码...
  • 好的。谢谢。我想我开始明白这一点了......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-03-19
  • 2022-10-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-12-29
  • 1970-01-01
相关资源
最近更新 更多