简体   繁体   English

2D动态数组发送到C函数

[英]2d dynamic arrays sent to a function in C

The purpose of this code is to see whether a 2d array (matrix) of unknown size (it gets read from a file) has a diagonal which is all the same numbers. 此代码的目的是查看未知大小的2d数组(矩阵)(从文件中读取)是否具有对角线,且对角线的个数均相同。 If so the function checkdiag should return 1. 如果是这样,函数checkdiag应该返回1。

the data in the file i`m using is as follows: 我使用的文件中的数据如下:

3

4 5 6

7 8 9

3 6 7

where the initial 3 represents the size of the matrix, (3x3) 其中首字母3代表矩阵的大小(3x3)

I know for a fact it will run and gather the data from the file as it prints the matrix within the for loop with fscanf. 我知道一个事实,它将使用fscanf在for循环中打印矩阵时,它将运行并从文件中收集数据。 But it will crash every time beyond that. 但是除此之外,它每次都会崩溃。 I've tried many way of passing the variable to the function and have done research as to what is going on but I am stumped here. 我尝试了多种将变量传递给函数的方法,并且对正在发生的事情进行了研究,但我对此深感困惑。

I am new to coding and 2d array especially. 我是编码和二维数组的新手。

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



int checkdiag(int size, int matrix[][size])
{
    int i,sum=0,verif;
    for(i=0;i<size;i++)
    {
       sum += matrix[i][i];
    }
    if(matrix[0][0]==((double)sum/(double)size))
        verif=1;
    else
        verif=0;


   return (verif);
}

int main()
{
    FILE *filename;
    char inputfile[25];
    int howmany,confirmdiag;
    int i,j; //Counter varibles
    int **matrix; // points to the first cell of 2d array [0][0]


    /* Type in exact file to open */
    printf("Please type in the exact name of the data file you with to use and please make  sure it is within the program folder.\nFor example: \"matrix1.txt\"\n");
    gets(inputfile);
    filename = fopen(inputfile,"r");

    if (filename==NULL)
    {
        system("cls");
        printf("\nCould not find the file you've requested, please make sure the file is on the   same partition.\n\n");
        getch();
        exit(0);
    }

    fscanf(filename,"%d",&howmany); //Scanning file to find size of the matrix

    matrix =(int **) calloc(howmany,sizeof(int*)); //Allocating memory for the ROWS of the matrix which are pointers of size (int*)

    for (i=0; i<howmany; i++)
    {
        matrix[i] =(int *) calloc(howmany,sizeof(int));//Allocating memory for the COLUMNS of the matrix which are integers of size (int)
    }

    for(i=0;i<howmany;i++)
    {
        for(j=0;j<howmany;j++)
        {
          fscanf(filename,"%d",&matrix[i][j]);//Scanning the file to fill the matrix array.
        }
    }

    confirmdiag=checkdiag(howmany, **matrix);

    if (confirmdiag==1)
    {
        printf("The matrix is %dx%d and all the numbers on the main diagonal are the same.",howmany,howmany);
    }
    else if (confirmdiag==0)
    {
        printf("The matrix is %dx%d. All the numbers on the main diagonal are not the same.",howmany,howmany);
    }

    for (i=0; i<howmany; i++)
        free (matrix[i]);

    free(matrix);

    return 0;
}

Looks good. 看起来不错。 Just a quick reminder: In your function call: **matrix sends only the first element of the matrix matrix(0,0) to the function since you are dereferencing the first entry of the first column. 提醒一下:在函数调用中:** matrix仅将矩阵matrix(0,0)的第一个元素发送给函数,因为您要取消引用第一列的第一项。 You need to send a pointer to pointer. 您需要发送一个指向该指针的指针。 Try: 尝试:

confirmdiag=checkdiag(matrix, howmany, howmany);

and for the method definition: 对于方法定义:

int checkdiag(int** matrix, int sizeCol, int sizeRow)
{
...
}

Good luck! 祝好运!

Change confirmdiag=checkdiag(howmany, **matrix); 更改confirmdiag=checkdiag(howmany, **matrix); to confirmdiag=checkdiag(howmany, matrix); confirmdiag=checkdiag(howmany, matrix); as there is no reason to dereference the pointer. 因为没有理由取消引用指针。

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

int checkdiag(int size, int matrix[][size]){
    int i, v=matrix[0][0];

    for(i=0;i<size;i++){
        if(v != matrix[i][i] || v != matrix[i][size-1-i])
            return 0;
    }

   return 1;
}

int main(void){
    FILE *file;
    char filename[25];

    printf("Please type in the exact name of the data file you with to use and please make sure it is within the program folder.\nFor example: \"matrix1.txt\"\n");
    scanf("%[^\n]%*c", filename);

    if ((file = fopen(filename, "r")) == NULL){
        system("cls");
        printf("Could not find the file you've requested, please make sure the file is on the same partition.\n\n");
        getch();
        exit(EXIT_FAILURE);
    }

    int howmany;
    fscanf(file, "%d", &howmany);

    int (*matrix)[howmany] = malloc(howmany * sizeof(*matrix));

    for(int i=0;i<howmany;i++)
        for(int j=0;j<howmany;j++){
          fscanf(file, "%d", &matrix[i][j]);

    if (checkdiag(howmany, matrix))
        printf("The matrix is %dx%d and all the numbers on the main diagonal are the same.",howmany,howmany);
    else
        printf("The matrix is %dx%d. All the numbers on the main diagonal are not the same.",howmany,howmany);

    free(matrix);

    return 0;
}

While your approach is solid, there are several additional initializations and validations you should make. 尽管您的方法很可靠,但是您应该进行一些其他的初始化和验证。 Your choice of calloc for allocation was excellent. 您选择的calloc分配非常好。 It allocates/initializes the elements to 0 and prevents any attempt to read a value from an uninitialized value. 它将元素分配/初始化为0并防止尝试从未初始化的值中读取值。 However, you need to check that it succeeded before you go forward in the code. 但是,在继续执行代码之前,需要检查它是否成功。

The same applies to howmany . 这同样适用于howmany Before allocating and charging though the code, a simple check that it is a valid number > 0 is needed. 在通过代码分配和计费之前,需要简单检查一下它是一个valid number > 0

While you free the memory allocated to matrix , you leave yourself open to a memory leak by failing to close file (there will be 500-600 bytes associated with the open file descriptor). 在释放分配给matrix的内存的同时,由于无法关闭file而导致内存泄漏(与打开的文件描述符相关联的字节数为500-600)。

fscanf is fine for reading integer values from a file, but unless you know, and can guarantee, the contents of your input file, using line-input commands like fgets or getline and then parsing the line for the numbers you need is a far more flexible way to get input. fscanf可以从文件中读取整数值,但是除非您知道并且可以保证输入文件的内容,使用fgetsgetline类的line-input命令,然后解析该行以获取所需的数字,否则fscanf会大得多。获取输入的灵活方式。 That's just something to keep in mind as you go forward. 这只是您前进时要记住的事情。 One stray character in your code will cause a matching failure with fscanf . 代码中的一个杂散字符会导致fscanf matching failure (the return of fscanf should also be checked to insure you completely fill the matrix with valid values -- omitted below) (也应检查fscanf的返回值,以确保您用有效值完全填充了矩阵-以下省略)

Lastly, there is nothing wrong with prompting to user to enter a filename, but generally, a block of code should operate on the arguments passed to it. 最后,提示用户输入文件名没有任何问题,但是通常,代码块应该对传递给它的参数进行操作。 Making use of int argc, char **argv not only eases moving your test code into your main body of code as a function later, etc.. it also prevents having to retype your input over and over during testing :p . 使用int argc, char **argv不仅可以简化以后将测试代码作为函数移至代码主体中的工作,等等。它还避免了在测试过程中一遍又一遍地重新输入输入内容:p

Putting all of that together, and stealing Bluepixy's diagonal check, here is an updated version of your code. 将所有这些放在一起,并窃取Bluepixy的对角线检查,这是您代码的更新版本。 Look through it and let me know if you have any questions. 查看它,让我知道是否有任何问题。 ( Note you can add getch and conio.h back as needed, but they should be avoided as they are not portable beyond windows) Also included is a quick print routine to print the matrix to stdout that you may find useful. 请注意,您可以根据需要重新添加getchconio.h ,但应避免使用它们,因为它们不能在Windows之外移植。)还包括一个快速打印例程,可以将矩阵打印到stdout ,这可能对您有用。

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

int checkdiag (int size, int **matrix);
void prn_mtrx (int m, int n, int **matrix);

int main (int argc, char **argv)
{
    if (argc < 2) {
        fprintf (stderr, "error: insufficient input. Usage: %s filename\n", argv[0]);
        return 1;
    }

    FILE *file = NULL;
    char *filename = argv[1];
    int howmany = 0;
    int **matrix = NULL;
    int i = 0;
    int j = 0;

    /* open file & validate */
    if (!(file = fopen (filename, "r"))) {
        fprintf (stderr, "error: file open failed '%s'.\n\n", filename);
        exit (EXIT_FAILURE);
    }

    /* read / validate howmany value */
    if (!fscanf (file, "%d", &howmany) && howmany > 0) {
        fprintf (stderr, "error: invalid howmany value. (size not number > 0)\n\n");
        fclose (file);
        exit (EXIT_FAILURE);
    }

    /* allocate memory for matrix, initialize elements to '0' with calloc */
    if (!(matrix = calloc (howmany, sizeof *matrix))) {
        fprintf (stderr, "error: memory allocation failed '%s'.\n\n", filename);
        exit (EXIT_FAILURE);
    }

    for (i = 0; i < howmany; i++)
        if (!(matrix[i] = calloc (howmany, sizeof **matrix))) {
        fprintf (stderr, "error: memory allocation failed '%s'.\n\n", filename);
        exit (EXIT_FAILURE);
    }

    /* read values from file (preferably with fgets/getline, then parse tokens) */
    for (i = 0; i < howmany; i++)
        for (j = 0; j < howmany; j++)
            fscanf (file, "%d", &matrix[i][j]);

    /* print the matrix */
    printf ("\nThe %dx%d matrix is:\n\n", howmany, howmany);
    prn_mtrx (howmany, howmany, matrix);

    /* check the diagonal */
    if (checkdiag (howmany, matrix))
        printf ("\nThe numbers on the main diagonal are the same.\n\n");
    else
        printf ("\nThe numbers on the main diagonal are NOT the same.\n\n");

    /* close file / free memory allocated to file */
    if (file) fclose (file);

    /* free memory allocated to matrix */
    for (i = 0; i < howmany; i++)
        free (matrix[i]);
    free (matrix);

    return 0;
}

/* check values on matrix diagonal */
int checkdiag (int size, int **matrix)
{
    int i, v = matrix[0][0];

    for (i = 0; i < size; i++) {
        if (v != matrix[i][i] || v != matrix[i][size - 1 - i])
            return 0;
    }

    return 1;
}

/* print a (m x n) matrix (with pad) */
void prn_mtrx (int m, int n, int **matrix)
{
    register int i, j;

    for (i = 0; i < m; i++)
    {
        char *pad = " [ ";
        for (j = 0; j < n; j++)
        {
            printf ("%s%3d", pad, matrix [i][j]);
            pad = ", ";
        }
        printf ("%s", " ]\n");
    }
}

Output 输出量

$ ./bin/matrix_diagonal dat/matrix_5.txt

The 5x5 matrix is:

 [   1,   2,   3,   4,   5 ]
 [   6,   7,   8,   9,  10 ]
 [  11,  12,  13,  14,  15 ]
 [  16,  17,  18,  19,  20 ]
 [  21,  22,  23,  24,  25 ]

The numbers on the main diagonal are NOT the same.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM