Моя функция правильно возвращает указатель на структуру? - PullRequest
0 голосов
/ 21 марта 2020

У меня есть проект на zybooks. И мой код, кажется, работает должным образом, поскольку он может правильно выделить края различных изображений. Но zybooks автоматизирован, и он не выполняет мою функцию определения края. the description of the questionfurther information on the project Это мой код для обеих функций:

#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;
}

Любой совет будет полезен. Я знаю, что код может сбивать с толку, поскольку он может не соответствовать стандартному форматированию, но это буквально мой первый класс кодирования.

1 Ответ

1 голос
/ 21 марта 2020

относительно:

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. отдельные блоки кода: for if else while do...while switch case default следует разделить одной пустой строкой.
  2. последовательно отступать от кода. Отступ после каждой открывающей скобки '{'. Отступ перед каждой закрывающей скобкой '}'. Предложите для каждого уровня отступа 4 пробела

  3. вставьте соответствующее горизонтальное пространство: внутри скобок, внутри скобок, внутри скобок, после запятых, после точек с запятой, около C операторов

функция: malloc() ожидает, что параметр имеет тип size_t, однако; операторы типа:

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

передаются int как часть параметра. (IE img->height) Это приводит к неявному преобразованию между int и size_t, которое «обычно» безвредно, но все же является рискованным преобразованием.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...