【问题标题】:Is my function correctly returning a pointer to a struct?我的函数是否正确返回了指向结构的指针?
【发布时间】:2020-03-21 18:10:23
【问题描述】:

我有一个关于 zybooks 的项目。而且我的代码似乎工作正常,因为它可以正确突出显示不同图像的边缘。但是,zybooks 是自动化的,它使我的边缘检测功能失败。 这是我的两个函数的代码:

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#include<string.h>
#include<limits.h>
typedef struct _image {
    int** pixels;
    int width;
    int height;
} Image;


Image* readImage(char* filename) {
    Image *pic= malloc(sizeof(Image));
    char type[3];
    int maxvalue;
    FILE *f1=NULL;
    f1= fopen(filename,"r");
        if(f1==NULL){
            printf("Unable to read image: %s\n",filename);
             return NULL;
        }
    fscanf(f1,"%s",type);
    fscanf(f1,"%d",&pic->width);
    fscanf(f1,"%d",&pic->height);
    fscanf(f1,"%d",&maxvalue);
    pic->pixels = (int **)malloc(sizeof(int *) * pic->height);
         for (int i = 0; i < pic->height; i++) {
            pic->pixels[i] = (int *)malloc(sizeof(int) * pic->width);
         }
     for (int i = 0; i < pic->height; i++) {
        for (int j = 0; j < pic->width; j++) {
           fscanf(f1,"%d",&pic->pixels[i][j]);
        }

    }
    fclose(f1);
  return pic;


}

Image* edgeDetect(Image* img, int threshold) {
    Image *edges;
    edges=malloc(sizeof(Image));
        edges->pixels = (int **)malloc(sizeof(int *) * img->height);
            for (int i = 0; i < img->height; i++) {
                edges->pixels[i] = (int *)malloc(sizeof(int) * img->width);
            }
    edges->height = img->height;
    edges->width = img->width;
     for (int i = 0; i < img->height; i++) {
        for (int j = 0; j < img->width; j++) {
            edges->pixels[i][j]=0;
        }
     }
     for(int i=0; i< edges->height;i++){
         for(int j=0; j<edges->width; j++){
             if( i > 0 && i< (edges->height-1) && j>0 && j<(edges->width-1) ){
                if(abs(img->pixels[i][j] - img->pixels[i][j+1]) > threshold || abs(img->pixels[i][j] - img->pixels[i-1][j]) > threshold)
                     edges->pixels[i][j]=255;
             }
            }
         }
    return edges;
}

int saveImage(char* filename, Image* img) {
   FILE* f1= NULL;
    f1= fopen(filename,"w");
    if(f1==NULL){
        printf("Unable to write image: %s\n",filename);
    return 1;
    }
    fprintf(f1,"P2\n");
    fprintf(f1,"%d %d\n",img->width,img->height);
    fprintf(f1,"255\n");
    for (int i = 0; i < img->height; i++) {
        for (int j = 0; j < img->width; j++) {
           fprintf(f1,"%d ",img->pixels[i][j]);
        }
        fprintf(f1,"\n");
    }
        fclose(f1);
        return 0;
}

void freeImage(Image* img) {
    for (int i = 0; i < img->height; i++) {
         free(img->pixels[i]);
}
free(img->pixels);
free(img);
}

int main(int argc, char** argv) {
    if( argc !=4){
         printf("Usage: ./a.out input.pgm output.pgm threshold\n");
    return 1;
    }
    int threshold= atoi(argv[3]);
    Image *data;
    data=readImage(argv[1]);
    if (data==NULL)
        return 1;
     Image *edge;
    edge= edgeDetect(data,threshold);
    freeImage(data);
    int result= saveImage(argv[2],edge);
    if (result==1)
        return 1;
    freeImage(edge);


    return 0;
}

任何提示都会有所帮助。我知道代码可能会令人困惑,因为它可能不遵循标准格式,但这确实是我的第一个编码课程。

【问题讨论】:

  • ⟼请记住,尤其是在 Stack Overflow 上学习和提问时,尽可能让代码保持井井有条是很重要的。 Consistent indentation 有助于传达结构,更重要的是传达意图,这有助于我们快速找到问题的根源,而无需花费大量时间来尝试解码正在发生的事情。
  • 这看起来像是内存泄漏,因为你从来没有free 任何东西,但它确实返回了指向已分配内存的指针。
  • 贴出的代码无法编译!除其他外,它缺少头文件所需的 #include 语句:stdio.hstdlib.h
  • 我没有发布完整的代码。我现在就这样做
  • 您了解 PPM 图像中的 光栅 样本(R、G、B)可以是 ASCII 文本(类型 "P3")或原始 - 二进制(类型 @ 987654332@) 其中如果maxcolor &lt; 256 每个样本为 1 个字节,否则每个样本为 2 个字节。您是否仅限于基本"P3" 图像类型?

标签: c multidimensional-array struct function-pointers


【解决方案1】:

关于:

Image *pic= malloc(sizeof(Image)); 

始终检查 (!=NULL) 返回值以确保操作成功。如果不成功,调用

perror( "your error message" );

将您的错误消息和系统认为发生错误的文本原因输出到stderr

关于:

printf("Unable to read image: %s\n",filename); 

错误消息应该输出到stderr,而不是stdout。建议使用:

fprintf( stderr, "Unable to read image: %s\n %s\n", filename, strerror( errno ) );

当调用任何scanf() 系列函数时,例如fscanf(),始终检查返回值(而不是参数值)以确保操作成功。注意:该系列函数返回成功的“输入格式转换”说明符的数量。

关于:

fscanf(f1,"%s",type); 
  1. 除 1 以外的任何返回值都表示发生了错误。
  2. 当使用 %s 和/或 %[...] 时,总是包含一个 MAX CHARACTERS 比输入缓冲区的长度小一的修饰符 避免任何缓冲区溢出和由此产生的未定义行为,因为这些“输入格式转换”说明符总是将 NUL 字节附加到输入。

关于:

pic->pixels = (int **)malloc(sizeof(int *) * pic->height);

在 C 中,返回的类型是 void*,可以分配给任何指针。强制转换只会使代码混乱。建议移除演员表。

为了便于阅读和理解:

  1. 分隔代码块:forifelsewhiledo...whileswitchcasedefault 应通过一个空行分隔。
  2. 始终缩进代码。在每个左大括号“{”后缩进。 在每个右大括号 '}' 之前取消缩进。建议每个缩进级别 为4个空格

  3. 插入适当的水平空间:在括号内, 大括号内,括号内,逗号后,分号后, 围绕 C 运算符

函数:malloc() 期望参数是size_t 类型,但是;像这样的陈述:

edges->pixels = (int **)malloc(sizeof(int *) * img->height);

正在传递 int 作为参数的一部分。 (即img-&gt;height)这会导致intsize_t 之间的隐式转换,这“通常”是无害的,但仍然是有风险的转换。

【讨论】:

  • 首选edges-&gt;pixels = malloc (img-&gt;height * sizeof *edges-&gt;pixels); 请参阅Do I cast the result of malloc? 并使用取消引用的指针设置type-size 确保您永远不会出错。
  • @user3629249 我已根据您的回答更正了我的代码,但 zybooks 仍然无法通过我的 edgedetect 和 main 功能。您能看看是否有任何错误或错误导致我似乎无法弄清楚吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-12-30
相关资源
最近更新 更多