0

I want to get numbers from user in a single line for example:

2 1 2 3 4 

The first number: 2 means that my Matrix should be with size of 2x2 and the next 4 numbers should insert into my Matrix (Matrix dimension should be ).

Currently I have this:

int dimension, num;
int *mat;
int numcounter = 0;
int i = 0;
int j, k, t;
char temp;

printf("Please enter numbers: ");
do {
    scanf("%d%c", &num, &temp);
    i++;        
    if (i == 1)
    {
        /* Set Matrix dimension. */
        dimension = num;
        if (dimension < 2)
        {
            printf("Size must be a valid number");
            return 1;
        }
        else
            /* Allocate dimension size. */
            mat = (int*)malloc(dimension * dimension * sizeof(int*));

    }
    else
    {
        /* Fill Matrix. */          
    }

} while (temp != '\n' || temp == EOF)

So here I have all the number and now I need to fill my Matrix but instead of put all the numbers inside temp array and then fill my Matrix I wonder how to do that without another memory allocation.

Toby Speight
  • 27,591
  • 48
  • 66
  • 103
Dana Yeger
  • 617
  • 3
  • 9
  • 26

2 Answers2

1

You can do it simply using a VLA. The OP's initial question never mentioned that OP needs to get the input in a line and parse it. I have given that as an answer in the second part. But simply that is not needed. It is not a feasible reason that you have to get the numbers all at once. You can get the size using one scanf and then the elements in another scanf.

scanf("%d", &num);
//Then you know the dimension of the array.

int arr[num][num];
for(size_t i=0;i<num; i++)
  for(size_t j =0; j< num; j++)
     if( scanf("%d",&arr[i][j]) != 1)
     {
        fprintf(stderr,"Error in input");
        exit(1);
     }

Also as you know how many numbers will be read you don't need to continue scanning until you get '\n' or EOF.

Given your case your over complicating things IMHO. As you know the numbers you can get the benefit of VLA.


If you have to get all the numbers in a single line you need to look at 3 functions. fgets() and strtol. Those will help you achieving reading everything in a line and then tokenizing.

To give you a demo of what I said you can do this

#include <stdio.h>
#include <stdlib.h>
#define BUFSIZE 256

int main(void)
{
    char line[BUFSIZE];
    long temp[BUFSIZE];
    int i = 0;
    if (fgets(line, sizeof line, stdin) != NULL)
    {
        const char *ptr = line;
        while (*ptr != '\0')
        {
            char *endptr = NULL;
            long val = strtol(ptr, &endptr, 10);
            if (endptr != ptr)
              temp[i++] = val;
            else
                break;
            ptr = endptr;
        }
    }
    int sz = temp[0];
    if( sz <= 0 )
    {
        fprintf(stderr,"Error in size input");
        exit(1);
    }
    int tempIn = 1;
    long arr[sz][sz];
    for(size_t i = 0; i < sz; i++)
        for(size_t j = 0; j < sz; j++)
            arr[i][j]= temp[tempIn++];

    for(size_t i = 0; i < sz; i++)
        for(size_t j = 0; j < sz; j++)
            printf("%ld ",arr[i][j]);

}

In the second code, as you can see fgets has been used which basically read a line and then strtol has been used. As you have mentioned that you will give a single line input of numbers.

Now what we did?

The line scanned and the parsed number by number using strtol. For a brief overview of strtol check this.


Also OP asked for how to use dynamic memory allocation to do the same thing. And there is no way a while loop is needed here. This is redundant. So while modifying I will add the code that will be able to do it much more simpler way.

scanf("%d", &num);
int matIndex = 0;      
/* Set Matrix dimension. */
dimension = num;
if (dimension <= 0)
{
    printf("Size must be posiitve integer");
    return 1;
}
else
{
    mat = malloc(dimension * dimension * sizeof *mat);
    if ( mat == NULL ){
        fprintf(stderr, "%s\n", "Error in malloc");
        exit(1);
    }
}

// All the numbers will be taken as elements of the dynamically allocated array,
for(size_t i = 0; i < dimension*dimension ; i++)
    if( scanf("%d",&mat[i]) == 1){
         //ok
    }
    else{
        fprintf(stderr,"Some error occured");
        break;
    }

When you want to access the i-th row and j-th column element, you can do this mat[i*dimension+j] //equivalent to mat[i][j]

Some useful information:-

  • Allocating dim*dim memory doesn't let you access the element in the form of mat[i[[j]. Because you allocated a single chunk of memory - you have to calculate the positions explicitly and access the element in the linear array.

  • You can do all the scanning using scanf() but you need to be careful when having scanf(). But yes you can get this thing done using scanf also.

  • Also there is another thing to know about. The VLA will have automatic storage duration and limiting the memory you can have use this way. The dynamically allocated memory has much higher limit giving you a scope of having much larger dimensions array.

  • Note that in dynamic memory allocation you will need to free the allocated memory when you are done working with it.

  • If you want to use mat[i][j] not mat[i*dim+j] you can consider creating one jagged array.

Few things that you will need:

Reading Suggestion:

Community
  • 1
  • 1
user2736738
  • 30,591
  • 5
  • 42
  • 56
0

You can use following code:
Note: You can redirect STDIN to your file. See posts available here

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

int main()
{
    int D, i, j;
    freopen("testfile.txt","r",stdin);
    printf("Ender dimention of matrix: ");
    scanf("%d",&D);

    int** matrix =  malloc(D*D*sizeof(int));
    for(i=0; i<D; i++)
    {
        for(j=0; j<D; j++)
        {
            printf("Ender element of matrix: ");
            scanf("%d",&matrix[i][j]);
        }
    }

    printf("Matrix is: \n");
    for(i=0; i<D; i++)
    {
        for(j=0; j<D; j++)
        {
            printf("%d ", matrix[i][j]);
        }
        printf("\n");
    }
    free(matrix);
    return 0;
}
cse
  • 4,066
  • 2
  • 20
  • 37
  • This should be in a single line, i cannot first get martix dimension and then the numbers – Dana Yeger Nov 24 '17 at 12:48
  • It will work in that way. If you are getting the input from any file then associate the file with `STDIN`. – cse Nov 24 '17 at 12:50
  • Again you wrote Ender dimention of matrix and Ender element of matrix but all this numbers should be in the same line – Dana Yeger Nov 24 '17 at 13:21
  • @DanaYeger From where you are reading the line? If you're reading input from any file then above code is perfectly fine. If you are reading it from standard input then just skip the freopen statement. – cse Nov 24 '17 at 16:03