0

I'm new to the C language and I'm working in this program as a way to study matrices. The program below is intended to read the rows and columns from the user (I will implement other tasks that are accessed by choosing the number). The matrix is given randomly according to the size given by the user. When 1 is given, the program should ask again about the rows and columns, but it is not working, it only changes the matrix, not its size. It is probably something related to pointers, but I couldn't figure it out. Below is a compilable code.

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

#define max_row 20
#define max_col 20

typedef int Matrix[max_row][max_col];

void Read_Matrix(int *row, int *col)
{
    while(*row > max_row || *row < 1 || *col > max_col || *col < 1)
    {
        printf("\n***** Matrix *****");
        printf("\nEnter rows >> ");
        scanf(" %d", row);
        printf("\nEnter columns >> ");
        scanf(" %d", col);
    }
}

void Random_Matrix(Matrix M, int row, int col)
{
    time_t seg = time(NULL);
    srand(seg);
    int i, j;

    for(i = 0; i < row; i++)
    {
        for(j = 0; j < col; j++)
        {
            M[i][j] = rand()%10;
        }
    }
}

void Show_Matrix(Matrix M, int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
       printf("\n");
       for (j = 0; j < col; j++)
       {
           printf(" %d ", M[i][j]);
       }
   }
   printf("\n");
}

int main()
{
    int choice, row, col;
    Matrix M;

    while(1)
    {
        /*

        Tasks concerning the Matrix

        */

        printf("\n\nEnter the task >> ");
        scanf(" %d", &choice);

        switch(choice)
        {
            case 1:
               Read_Matrix(&row, &col);
               Random_Matrix(M, row, col);
               Show_Matrix(M, row, col);
               break;
           case 2:
               printf("\nExit\n");
               exit(0);
               break;
        }
    }
}
欲しい未来
  • 121
  • 1
  • 9
  • You need to test the return value from `scanf()` every time to ensure it doesn't fail. – Jonathan Leffler Dec 20 '20 at 10:23
  • See also [`srand()` — why call it only once?](https://stackoverflow.com/questions/7343833/srand-why-call-it-only-once/). Granted, if there is a user typing then you'll probably get different seeds, but it's better to get in the habit of not calling `srand()` more than once. – Jonathan Leffler Dec 20 '20 at 10:26
  • 1
    The problem is that when you call `Read_Matrix()` the second time, the values in `*row` and `*col` already meet the loop criteria, so it never reenters the loop. You need to add `*row = *col = 0;` or equivalent to the top of the function. Also, it's conceivable that the values in `*col` and `*row` meet the criteria before you first call the function — you don't initialize `row` and `col` in `main()` so you don't know what their initial values are. – Jonathan Leffler Dec 20 '20 at 10:34
  • @Jonathan Leffler Now it is working, but I will study more about srand(). Thank you very much. – 欲しい未来 Dec 20 '20 at 10:38

1 Answers1

1

As I noted in the comments:

  1. You need to test the return value from scanf() every time to ensure it doesn't fail.
  2. See srand() — why call it only once?. Granted, if there is a user typing then you'll probably get different seeds, but it's better to get in the habit of not calling srand() more than once.
  3. The primary problem is that when you call Read_Matrix() the second time, the values in *row and *col already meet the loop criteria, so it never reenters the loop. You need to add *row = *col = 0; or equivalent to the top of the function. Also, it's conceivable that the values in *col and *row meet the criteria before you first call the function — you don't initialize row and col in main() so you don't know what their initial values are.

Putting those changes together yields (source mat17.c, program mat17):

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

#define max_row 20
#define max_col 20

typedef int Matrix[max_row][max_col];

static
void Read_Matrix(int *row, int *col)
{
    *row = *col = 0;
    while (*row > max_row || *row < 1 || *col > max_col || *col < 1)
    {
        printf("\n***** Matrix *****");
        printf("\nEnter rows >> ");
        if (scanf(" %d", row) != 1)
        {
            fprintf(stderr, "Unexpected error or EOF\n");
            exit(1);
        }
        printf("\nEnter columns >> ");
        if (scanf(" %d", col) != 1)
        {
            fprintf(stderr, "Unexpected error or EOF\n");
            exit(1);
        }
    }
}

static
void Random_Matrix(Matrix M, int row, int col)
{
    time_t seg = time(NULL);
    srand(seg);
    int i, j;

    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            M[i][j] = rand() % 10;
        }
    }
}

static
void Show_Matrix(Matrix M, int row, int col)
{
    int i, j;
    for (i = 0; i < row; i++)
    {
        printf("\n");
        for (j = 0; j < col; j++)
        {
            printf(" %d ", M[i][j]);
        }
    }
    printf("\n");
}

int main(void)
{
    int choice, row, col;
    Matrix M;

    while (1)
    {
        printf("\n\nEnter the task >> ");
        if (scanf("%d", &choice) != 1)
        {
            fprintf(stderr, "Unexpected error or EOF\n");
            exit(1);
        }

        switch (choice)
        {
        case 1:
            Read_Matrix(&row, &col);
            Random_Matrix(M, row, col);
            Show_Matrix(M, row, col);
            break;
        default:
            printf("\nExit\n");
            exit(0);
            break;
        }
    }
}

Sample output

$ mat17


Enter the task >> 1 2 2 1 3 3 1 4 4 1 2 2 2

***** Matrix *****
Enter rows >> 
Enter columns >> 
 4  5 
 0  3 


Enter the task >> 
***** Matrix *****
Enter rows >> 
Enter columns >> 
 4  5  0 
 3  2  0 
 1  3  8 


Enter the task >> 
***** Matrix *****
Enter rows >> 
Enter columns >> 
 4  5  0  3 
 2  0  1  3 
 8  4  1  3 
 4  3  7  2 


Enter the task >> 
***** Matrix *****
Enter rows >> 
Enter columns >> 
 4  5 
 0  3 


Enter the task >> 
Exit
$

Note that this run enters the date describing 4 matrices on one line of input. It shows that calling srand() too often means the same sequence of data is generated for each of the 4 matrices. There are several possible fixes:

  1. Only call srand() once.
  2. Read a line (e.g. fgets()) and parse that line once (e.g. with sscanf()), possibly rejecting input if it contains more than one number, or possibly processing the input in a loop (see How to use sscanf() in loops?.

Applying both option 1 and 2 is probably best; applying option 1 is pretty much mandatory, or you have to devise a mechanism to ensure that the seed is different on each call, even if the calls happen multiple times in a single second. For example, capture unsigned seed = time(0); once and use srand(seed++) for each call.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278