【问题标题】:Setting value to a 2d dynamic array array C将值设置为 2d 动态数组数组 C
【发布时间】:2021-10-04 18:08:03
【问题描述】:

我必须确保 row 和 col 有效,我必须将 im->pixels[row][col] 的值设置为 val 并返回 IMG_OK
否则,数组将不被修改并返回。我知道问题出在img_result_t img_set(),但我无法弄清楚。
我无法将 val 设置为我的数组。在运行main() 时,我得到的输出是,

        Creating test_im by calling 'img_create(10, 10)'
        test_im created successfully.
    
        Testing img_set.
        Cannot set value at index 0

代码:

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

typedef struct { 
    uint8_t** pixels;
    unsigned int rows;
    unsigned int cols;
} img_t;

/// A type for returning status codes 

typedef enum {
    IMG_OK,
    IMG_BADINPUT,
    IMG_BADARRAY,
    IMG_BADCOL,
    IMG_BADROW,
    IMG_NOTFOUND
} img_result_t;


img_t *img_create(unsigned int rows, unsigned int cols){

    img_t* arr = malloc(sizeof(img_t));
  if(arr == NULL) return arr;

  arr->rows = rows;
  arr->cols = cols;

  arr->pixels = malloc(rows * sizeof(*arr->pixels));
  if(arr->pixels == NULL){
    free(arr);
    return NULL;
  }
  for(unsigned int i = 0; i<arr->rows; i++){
        arr->pixels[i] = malloc(cols*sizeof(img_t));
        if(arr->pixels[i] == NULL){
          for(int j= 0; j < i; j++){
            free(arr->pixels[i]);
          }
          free(arr->pixels);
          free(arr);
          return NULL;
          
        }
      }return arr;
}

void img_destroy(img_t* im){

    if(im != NULL){
      for(unsigned int i = 0; i < im->rows; i++){
        free(im->pixels[i]);
      }
        free(im->pixels);
        free(im);
    }
}


img_result_t img_set(img_t* im, unsigned int row, unsigned int col, int val){
  
  if(im == NULL) return IMG_BADARRAY;

  im->rows = row;
  im->cols = col;
  
  unsigned int empty = 0;

  if(row <= empty){
    return IMG_BADROW;
  }
  if(col <= empty){
    return IMG_BADCOL;
  }
  im->pixels[row][col] = val;
  return val;

}

// helper function that prints the content of the img
void print_img(img_t* im) {
    if (im == NULL) {
        printf("Invalid img (null).\n");
        return;
    }

    printf("Printing img of row length %d and col length %d:\n", im->rows, im->cols);
    for (unsigned int i=0; i<im->rows; i++) {
        for (unsigned int j=0; j<im->cols; j++) {
            printf("%d ", im->pixels[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

int main() {
    // test variables to hold values returned by the functions
    img_t* test_im = NULL;
    img_t* null_im = NULL;
    img_t* test2_im = NULL;
    img_result_t test_result = IMG_OK;
    int val;
    
    printf("Creating test_im by calling 'img_create(10, 10)'\n");
    test_im = img_create(10, 10);
    if (test_im == NULL) {
        printf("test_im == NULL\n");
        return 1; //exit with a non-zero value
    }
    printf("test_im created successfully.\n\n");

    

    printf("Testing img_set.\n");
    for (unsigned int i=0; i<test_im->rows; i++) {
        for (unsigned int j=0; j<test_im->cols; j++) {
            if (img_set(test_im, i, j, (rand()%100)) != IMG_OK) {
                printf("Cannot set value at index %d\n", i);
                return 1; //exit with a non-zero value
            }
        }
    }
}

【问题讨论】:

  • 进行基本调试。 img_set 中的哪个条件失败?使用调试器逐步执行代码。 if(row &lt;= empty)if(col &lt;= empty) 问问你自己 rowcol 的值是什么,你用什么来调用函数,为什么会触发这些错误条件?您可以通过任何基本的调试量轻松找到它。 How to debug small programs
  • 您在img_set() 的末尾有return val;,但您应该返回IMG_OK。在您知道一切正常之前,您不应该更改任何内容,但是您从该位置设置了im-&gt;rowsim-&gt;cols。这可能意味着当您设置row = 0col = 0 像素时,您的图像会缩小。
  • 当您检查img_set(test_im, i, j, (rand()%100)) != IMG_OK时,该函数也会执行return val;
  • 我认为最后的评论是一个答案,可能是答案。 @kaylum 如果您想回答并希望我删除我的,请告诉我。

标签: c memory-management malloc heap-memory dynamic-memory-allocation


【解决方案1】:

您的 img_set 函数有 4 个错误。

  1. 您覆盖了行和列的img_t 配置

  2. 您对下边界的检查是错误的

  3. 不检查上限

  4. 存储值时返回类型错误。

见 cmets。

img_result_t img_set(img_t* im, unsigned int row, unsigned int col, int val){
  
  if(im == NULL) return IMG_BADARRAY;

  im->rows = row;  <--- Changing im->rows and cols are wrong.
  im->cols = col;  <--- Once im is created you never want to change them
  
  unsigned int empty = 0;  <--- why ? zero is always lower boundary

  if(row <= empty){ <--- This makes index zero invalid
    return IMG_BADROW;
  }
  if(col <= empty){ <--- This makes index zero invalid
    return IMG_BADCOL;
  }

  // Here should check for upper boundary

  im->pixels[row][col] = val;
  return val; <-------- Wrong return type

}

试试看:

img_result_t img_set(img_t* im, unsigned int row, unsigned int col, int val)
{
  if(im == NULL) return IMG_BADARRAY;

  if(row < 0 || row >= im->rows) return IMG_BADROW;

  if(col < 0 || col >= im->cols) return IMG_BADCOL;

  im->pixels[row][col] = val;
  return IMG_OK;
}

另外你在创建函数中有一个错误:

arr->pixels[i] = malloc(cols*sizeof(img_t));
                                    ^^^^^
                                    wrong type

那我想知道为什么当你真正想要存储uint8_t 时你的set-function 将值设为int。这不违法,但有点奇怪。

【讨论】:

    【解决方案2】:

    我得出了和凯勒姆一样的结论:

    该函数在您检查img_set(test_im, i, j, (rand()%100)) != IMG_OK 时执行return val;

    通读您的代码,我会解释您的 API 概念,因此解决方案就是简单地更改

    return val;
    

    return IMG_OK;
    

    因为这是成功情况下来自img_result_t 的预期状态返回值。

    【讨论】:

      猜你喜欢
      • 2011-01-18
      • 1970-01-01
      • 2016-10-05
      • 1970-01-01
      • 2012-11-23
      • 1970-01-01
      • 1970-01-01
      • 2013-01-24
      • 1970-01-01
      相关资源
      最近更新 更多