簡體   English   中英

用 calloc 分配指針 arrays 而不是 malloc

[英]Allocating pointer arrays with calloc and malloc not

我在 C 中獲得了一項學校作業,以創建一個乘法矩陣的程序。 我將在下面列出分配限制,這樣人們就不會回答我為什么要這樣做的問題。 來自導師的限制:

  • 不能在代碼中的任何地方使用方括號(改用指針表示法)
  • 矩陣 A、B、C 必須是單個 integer 指針變量(int *A、*B、*C)
  • 只能使用主 function 和 header 指定的那些
  • 必須使用“gcc -ansi -Wall -o p2 p2.c”編譯

我還沒有實現矩陣乘法 function,因為我遇到的問題與文件讀取或 memory 分配有關。

我遇到的具體問題是,當我使用 malloc 或 calloc(兩者都嘗試過)為指針矩陣分配空間時,程序在 output 的某些地方插入 33 而不是 0。此時我已經嘗試了所有方法並確信我對指針的了解從根本上是有缺陷的。

p2.h(由講師提供)

#include <stdio.h>
#include <stdlib.h>
/* This function reads m, n, and p from the datafile.  
    It then allocates the correct amount of memory required for matrices
    A, B, and C.
    Then matrices A and B are filled from the datafile.
    The values for m, n, and p are passed by reference, and are
    thus filled in by this function
    PARAMETERS in order are:
    int **      matrix A
    int **      matrix B
    int **      matrix C    
    int *       m   The number of rows in matrix A
    int *       n   The number of columns in matrix A and
                    The number of rows in matrix B
    int *       p   The number of columns in matrix B
    char *      The name of the datafile, from the command line
*/
void read_matrices(int **, int **, int **,  int *, int *, int *, char *);
/*  This function prints a matrix.  Rows and columns should be preserved.
    PARAMETERS in order are:
    int *       The matrix to print
    int         The number of rows in the matrix
    int         The number of columns in the matrix
*/    
void print_matrix(int *, int, int);
/*  The two matrices A and B are multiplied, and matrix C contains the
    result.
    PARAMETERS in order are:
    int *       Matrix A
    int *       Matrix B
    int *       Matrix C
    int         m
    int         n
    int         p
*/    
void mult_matrices(int *, int *, int *, int, int, int);

p2.c (很抱歉,進行了很多調試)

#include <stdio.h>
#include <stdlib.h>
#include "./p2.h"

/* constants for testing */
#define cM 3
#define cN 2
#define cP 5

int main(int argc, char **argv) {
    if (argc < 2) {
        printf("Must include an argument.\n");
        exit(1);    
    }
    char *path = *(argv + 1);

    int *m = (int *) malloc(sizeof(int));
    int *n = (int *) malloc(sizeof(int));
    int *p = (int *) malloc(sizeof(int));
    *m = cM; *n = cN; *p = cP;

    int i,j; /* loop counters */
    /* allocate space for 2d pointer arrays */
    int **A = NULL; 
    A = (int **) malloc(*m * sizeof(int *));
    for (i = 0; i < *m; i++) {
        *(A+i) = (int *) malloc(*n * sizeof(int)); 
    }   

    int **B = NULL;
    B = (int **) malloc(*n * sizeof(int *));
    for (i = 0; i < *n; i++) {
        *(B+i) = (int *) malloc(*p * sizeof(int)); 
    }   

    int **C = NULL;
    C = (int **) malloc(*m * sizeof(int *));
    for (i = 0; i < *m; i++) {
        *(C+i) = (int *) malloc(*p * sizeof(int)); 
    }   

    /* write data to A */
    for (i = 0; i < *m; i++) {
        for (j = 0; j < *n; j++) {
            *(*(A+i)+j) = 0;    
        }
    }

    /* testing a */
    for (i = 0; i < *m; i++) {
        for (j = 0; j < *n; j++) {
            if (*(*(A+i)+j) != 0) {
                printf("[x]");
            } else {
                printf("[0]");  
            }
        }
    }
    printf("\n");

    /* write data to B */
    for (i = 0; i < *n; i++) {
        for (j = 0; j < *p; j++) {
            *(*(B+i)+j) = 0;    
        }
    }

    /* testing b */
    for (i = 0; i < *n; i++) {
        for (j = 0; j < *p; j++) {
            if (*(*(B+i)+j) != 0) {
                printf("[x]");
            } else {
                printf("[0]");  
            }
        }
    }
    printf("\n");

    /* write data to C */
    for (i = 0; i < *m; i++) {
        for (j = 0; j < *p; j++) {
            *(*(C+i)+j) = 0;    
        }
    }

    /* testing c */
    for (i = 0; i < *m; i++) {
        for (j = 0; j < *p; j++) {
            if (*(*(C+i)+j) != 0) {
                printf("[x]");
            } else {
                printf("[0]");
            }
        }
    }
    printf("\n");



    printf("Matrix A: \n");
    print_matrix(*A, *m, *n);
    printf("Matrix B: \n");
    print_matrix(*B, *n, *p);
    printf("Matrix C: \n");
    print_matrix(*C, *m, *p);

    return 0;
}

void read_matrices(int **A, int **B, int **C, int *m, int *n, int *p, char *path) {
    FILE *fptr;
    fptr = fopen(path, "r");
    if (fptr == NULL) {
        printf("Cannot open file: ./p2 [filename].txt\n");  
        exit(1);
    }

    /* get first 3 numbers from file, set m,n,p */
    *m = fgetc(fptr);
    fgetc(fptr);
    *n = fgetc(fptr);
    fgetc(fptr);
    *p = fgetc(fptr);
    fgetc(fptr);

    /* read first matrix */
    /* 1) calculate matrix size m x n
     * 2) loop through malloc'ed matrix
     * 3) each loop, insert char in loc
     * 4) if next char NOT 10/32, add nextchar*10 to value in loc 
     */
    char cur;
    while ( (cur = fgetc(fptr)) != EOF ) {
        if (cur == 10 || cur == 32) {
            /* do nothing :) */
        } else {
            *m = cur;
            *n = cur;
            *p = cur;
            break;
        }
    }
    
    printf("m: %c\n", *m);
    printf("n: %c\n", *n);
    printf("p: %c\n", *p);
    printf("next: %c\n", fgetc(fptr));

    fclose(fptr);
}

void print_matrix(int *X, int rows, int cols) {
    int r, c;
    int k = 0;
    for (r = 0; r < rows; r++) {
        for (c = 0; c < cols; c++)  {
            printf("\t%d", *(X+k));
            k++;
        }
        printf("\n");
    }
}

void mult_matrices(int *A, int *B, int *C, int m, int n, int p) {

}

d2.txt(數據文件)

3
2
4
1 2
3 4
5 6
7 8 9 10
11 12 13 14

Output:./p2 d2.txt

[0][0][0][0][0][0]
[0][0][0][0][0][0][0][0][0][0]
[0][0][0][0][0][0][0][0][0][0][0][0][0][0][0]
Matrix A:
        0       0
        0       0
        0       0
Matrix B:
        0       0       0       0       0
        0       33      0       0       0
Matrix C:
        0       0       0       0       0
        0       33      0       0       0
        0       0       0       0       33

如果您注意到,我有一些調試代碼檢查數組中的當前項是否為 0。它似乎表明它們都是 0,讓我認為這是一個打印問題,但我更迷失在什么會造成這種情況。 33 的 ascii 代碼是一個感嘆號,但我不確定它有什么相關性。

如果我忘記了任何重要信息或需要詳細說明,請告訴我。 任何幫助是極大的贊賞:)

根據您應該使用的 function 簽名,您需要使用正確的索引數學將 2D arrays 實現為 1D。 這將導致所有 memory 被連續布局,這根本無法保證您現在分配 memory 的方式(每個矩陣的兩次調用malloc 例如:

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

void print_matrix(int* A, int rows, int cols)
{
  for (int r=0; r<rows; r++)
  {
    for (int c=0; c<cols; c++)
    {
      // If you want to treat A as a 2D matrix, this is where we have to do a bit of
      // fancy index math to give you what double bracket notation [][] does for you
      //    r * cols gives you the index of the right row
      //      + c give you the column offset in that row
      //        add that offset to A then dereference
      printf("%d\t", *(A + (r * cols + c)));
    }
    printf("\n");
  }
}

int main(void)
{
  // matrix A is supposed to be m by n
  int* A;
  // read these from file, or where ever they're supposed to come from
  int m = 2;
  int n = 10;
  // Allocate the memory in one chunk. This makes the memory all contiguous, just the
  // same as if you had done A[m][n]. However, the double call malloc for each int**
  // matrix probably will not give you contiguous memory for the entire matrix. Each
  // call to malloc is independent.
  A = malloc(m * n * sizeof(int)); // or sizeof(*A) would be even better
  if (A == NULL)
  {
      // handle error
  }

  // We can initialize values for A at this point, still not needing to care about
  // rows or columns
  for (int i=0; i<m*n; i++)
  {
    *(A + i) = i;  // using i for a better visual when we print
  }

  print_matrix(A, m, n);
  free(A);

  return 0;
}

演示

你把簡單的事情復雜化了。 使用指向 arrays 的指針並分配二維數組。

使用正確類型的大小變量。

盡量避免副作用。 使用參數和 function 返回值。

//this function is for the test purposes only
int writefile(const char *fn)
{
    FILE *fo = fopen(fn, "w");
    fprintf(fo, 
    "3\n"
    "2\n"
    "4\n"
    "1 2\n"
    "3 4\n"
    "5 6\n"
    "7 8 9 10\n"
    "11 12 13 14\n");
    fclose(fo);
}

void *allocIntMatrix(size_t rows, size_t cols)
{
    int (*m)[cols] = malloc(rows * sizeof(*m));
    return m;
}

void printIntMatrix(size_t rows, size_t cols, int (*m)[cols])
{
    for(size_t row = 0; row < rows; row++)
    {
        for(size_t col = 0; col < cols; col++)
        {
            printf("[%5d] ", m[row][col]);
        }
        printf("\n");
    }
}

int readData(FILE *fi, size_t rows, size_t cols, int (*m)[cols])
{
    for(size_t row = 0; row < rows; row++)
    {
        for(size_t col = 0; col < cols; col++)
        {
            fscanf(fi, "%d", &m[row][col]);
        }
    }
    return 0;
}

int main(int argc, char **argv) 
{
    size_t n,m,p;

    writefile("a.aaa");

    FILE *fi = fopen("a.aaa", "r");
    fscanf(fi, "%zu", &m);
    fscanf(fi, "%zu", &n);
    fscanf(fi, "%zu", &p);

    printf("n = %zu, m = %zu, p = %zu\n", n, m, p);

    int (*A)[n] = allocIntMatrix(m, n);
    int (*B)[p] = allocIntMatrix(n, p);

    readData(fi, m, n, A);
    readData(fi, n, p, B);

    fclose(fi);

    printIntMatrix(m, n, A);
    printf("\n");
    printIntMatrix(n, p, B);

    return 0;
}

https://godbolt.org/z/adoEx1r4f

您需要檢查錯誤(文件、memory 等)。 為了示例的簡單起見,我跳過了它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM