将值设置为 2d 动态数组数组 C

Posted

技术标签:

【中文标题】将值设置为 2d 动态数组数组 C【英文标题】:Setting value to a 2d dynamic array array 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 如果您想回答并希望我删除我的,请告诉我。 【参考方案1】:

您的 img_set 函数有 4 个错误。

    您覆盖了行和列的img_t 配置

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

    不检查上限

    存储值时返回类型错误。

见 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 的预期状态返回值。

【讨论】:

以上是关于将值设置为 2d 动态数组数组 C的主要内容,如果未能解决你的问题,请参考以下文章

在C中操作动态分配的2D char数组

试图将一个连续的动态二维数组从 C 传递到 Fortran

试图将一个连续的动态二维数组从 C 传递到 Fortran

将值从向量分配给动态数组(C++)

如何将值推送到 QML 属性变量二维数组 - 动态?

将值数组放入 CLLocationCoordinate2D 的优雅方式