Thread: how to create an user input for 2D array

  1. #1
    Registered User
    Join Date
    Aug 2014
    Posts
    26

    how to create an user input for 2D array

    if i want the user to input (via 'scanf' i guess) a number .
    lets say 4.
    and then the computer will build a 4x4 board.
    and after i will want to add elements to the array.

    i tried a way to build an array with variables.
    for example
    Code:
    int myarray[i][j];
    but then i got error
    Code:
    "expected constant expression"
    i'm guessing there's a way with maybe allocate memory for a two-star pointer like this :
    Code:
     int rows;
    int **ptr = malloc(rows*sizeof(int*);
    can you help figure this out ?
    Last edited by Idan Damri; 08-22-2014 at 07:03 PM.

  2. #2
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You were attempting to use variable length arrays (VLAs). They are possible in C as of the 1999 version of the C standard, so you need a compiler that supports that, and you must make sure that feature is enabled. How to do that can be found in your compiler documentation. What compiler are you using? Providing the smallest, compileable example that exhibits this error message would be helpful too. You could allocate memory dynamically, as you suggest, with malloc -- this is easy, just remember to free all the memory when you're done. See this link for some ideas, however I would stick with the VLA if possible.

    A few more notes. First, prefer using fgets to read a whole line of user input, then use strtol to parse out an integer. Second, you should use the thing pointed to in the sizeof expression when malloc'ing, e.g.
    Code:
    int **ptr = malloc(rows * sizeof(*ptr));
    Note the * in front, to make it the size of the thing pointed to, i.e. the size of an int *, which is what each row will contain. Then you do similar when allocating each row
    Code:
    ptr[0] = malloc(cols * sizeof(*ptr[0]));
    That will give you the size of an int.

    The main reason for this is so that if you change the type of ptr to be char, long, whatever, you only need to change the declaration -- all the malloc calls will malloc the correct amount of memory for your new type without you having to do anything.

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Update your compiler so it complies with the 1999 C standard (or more recent) and your first way will work. For older compilers it will not.

    If you are stuck with an older compiler, there are two ways depending on whether you are adamant that the array has to be two-dimensional.

    The first is to malloc() enough memory, but index it as a one-dimensional array;
    Code:
        /*  read value for row and columns */
        int *p = malloc(rows*columns*sizeof(*p));
    
        /*   get values i and j representing element you want to access */
    
        p[i*rows + j] = 42;    /*  42 = meaning of life, the universe, and everything */
    or (if you really want a pointer to pointer and 2D array syntax) ....
    Code:
        /*  read value for row and columns */
        int **p = malloc(rows*sizeof(*p));
        for (i = 0; i < rows; ++i)
           p[i] = malloc(columns*sizeof(**p));
    
        /*   get values i and j representing element you want to access */
    
        p[i][j] = 42;
    It's also necessary to check that ALL of the malloc() calls succeed and, when done with the arrays, to call free(). In the second approach, ALL of the individual malloc() calls need corresponding free() calls.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Aug 2014
    Posts
    26
    I have the latest visual studio compiler.

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Idan Damri View Post
    I have the latest visual studio compiler.
    Microsoft has cared more about compliance with C++ standards rather than C for at least a decade. No surprises that some of the more recent features of C are not supported.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Registered User
    Join Date
    Aug 2014
    Posts
    20
    they're right, visual studio is definitely not C99.

  7. #7
    Registered User
    Join Date
    Aug 2014
    Posts
    26
    Quote Originally Posted by grumpy View Post
    Update your compiler so it complies with the 1999 C standard (or more recent) and your first way will work. For older compilers it will not.

    If you are stuck with an older compiler, there are two ways depending on whether you are adamant that the array has to be two-dimensional.

    The first is to malloc() enough memory, but index it as a one-dimensional array;
    Code:
        /*  read value for row and columns */
        int *p = malloc(rows*columns*sizeof(*p));
    
        /*   get values i and j representing element you want to access */
    
        p[i*rows + j] = 42;    /*  42 = meaning of life, the universe, and everything */
    or (if you really want a pointer to pointer and 2D array syntax) ....
    Code:
        /*  read value for row and columns */
        int **p = malloc(rows*sizeof(*p));
        for (i = 0; i < rows; ++i)
           p[i] = malloc(columns*sizeof(**p));
    
        /*   get values i and j representing element you want to access */
    
        p[i][j] = 42;
    It's also necessary to check that ALL of the malloc() calls succeed and, when done with the arrays, to call free(). In the second approach, ALL of the individual malloc() calls need corresponding free() calls.
    Why you wrote 42? If the user will want to input an 4x4 2d array?

    And i know that in the collage i will learn they use visual studio 2012.
    So theres no point for me now to use gcc for c 99. Or any other compiler that supports c99.
    Last edited by Idan Damri; 08-23-2014 at 10:02 AM.

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    42 is just an example value. For the array size, look at the variables named rows and columns.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  9. #9
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by Idan Damri View Post
    Why you wrote 42? If the user will want to input an 4x4 2d array?
    You clearly have not read the work of Douglas Adams.

    In any event, the value of 42 has no relationship to the dimensions of the array.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  10. #10
    Registered User
    Join Date
    Aug 2014
    Posts
    26
    Quote Originally Posted by grumpy View Post
    You clearly have not read the work of Douglas Adams.

    In any event, the value of 42 has no relationship to the dimensions of the array.
    yes.. ok i understood.
    i have 2 problems. you may read the code below first.
    1) for example if the user input is 4 . the output will be 7-8 rows and 4 columns. and i want it to be identical 2d array (in this case 4x4)
    or if the users input '2' so i want 2x2 2d array.
    2)the numbers are repeating themselfs. each row is the same. and i wants real random numbers.
    and , again, only for example, if the users input is 4 ... an int* in my compiler is 4 bytes. so when i use malloc (4*sizeof(int*) for the rows its 16.
    and for the columns also 16. so if my array is 4*4 i need total allocation of 64 bytes ( 16* int which is 4 ) and its allocating only 32 bytes. i could simply allocate rows*colms*sizeof int*. but i want to figure this way below.
    this is the code :
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    
    int main(){
     int rows ;
    scanf("%d", &rows);
     int colms = rows;
     int i = 0;
     int j= 0;
    
    
    int **board = malloc(rows*sizeof(*board));
    printf("%d\n",rows*sizeof(*board));     //to check.
    board[i] = malloc(colms*sizeof(*board));
    printf("%d\n", colms*sizeof(*board)); //to check
    
    
    for (; i < rows; i++){
    for(; j<colms; j++){
    
    
    srand((unsigned)time(NULL));
    board[i][j] = rand() %(rows*colms) ;
    
    
    printf("%d\n", *board);
    
    
     }
    }
    return 0;
    }
    Last edited by Idan Damri; 08-24-2014 at 10:18 AM.

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    You need to indent your code properly, e.g.,
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    int main() {
        int rows;
        scanf("%d", &rows);
        int colms = rows;
        int i = 0;
        int j = 0;
    
        int **board = malloc(rows * sizeof(*board));
        printf("%d\n", rows * sizeof(&board));   //to check.
        board[i] = malloc(colms * sizeof(*board));
        printf("%d\n", colms * sizeof(*board)); //to check
    
        for (; i < rows; i++) {
            for(; j < colms; j++) {
                srand((unsigned)time(NULL));
    
                board[i][j] = rand() %(rows*colms) ;
    
                printf("%d\n", *board);
            }
        }
    
        return 0;
    }
    A few comments:
    • You should check that scanf returns 1 before proceeding.
    • Your check for number of rows allocated contains a typo error, i.e., sizeof(&board) should be sizeof(*board)
    • You need to loop to allocate for each row.
    • You should call srand only once, typically near the start of the main function.
    • *board is a pointer, so you presumably don't want to print it but rather want to print board[i][j].
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Registered User
    Join Date
    Aug 2014
    Posts
    26
    Quote Originally Posted by laserlight View Post

    A few comments:
    • You should check that scanf returns 1 before proceeding.
    • Your check for number of rows allocated contains a typo error, i.e., sizeof(&board) should be sizeof(*board)
    • You need to loop to allocate for each row.
    • You should call srand only once, typically near the start of the main function.
    • *board is a pointer, so you presumably don't want to print it but rather want to print board[i][j].
    when i wrote &board it was by mistake . ok i will apply what you said and i will reply in couple of minutes

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Oh, one more thing. This:
    Code:
    board[i] = malloc(colms * sizeof(*board));
    should be:
    Code:
    board[i] = malloc(colms * sizeof(**board));
    of course within a loop. You might find it easier see by writing:
    Code:
    int **board = malloc(rows * sizeof(board[0]));
    and:
    Code:
    board[i] = malloc(colms * sizeof(board[0][0]));
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Aug 2014
    Posts
    26
    Quote Originally Posted by laserlight View Post
    Oh, one more thing. This:
    Code:
    board[i] = malloc(colms * sizeof(*board));
    should be:
    Code:
    board[i] = malloc(colms * sizeof(**board));
    of course within a loop. You might find it easier see by writing:
    Code:
    int **board = malloc(rows * sizeof(board[0]));
    and:
    Code:
    board[i] = malloc(colms * sizeof(board[0][0]));
    but it all doesnt really matter because **board, or *board, or board[0] are all 4 bytes in size.
    and i tried what you wrote before. it wont change something accept now its print only the columns.
    thats worked for you ? if you're trying to compile it ?

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by Idan Damri
    but it all doesnt really matter because **board, or *board, or board[0] are all 4 bytes in size.
    It would be sloppy to assume that just because this is the case for now, that it will always be the case.

    Quote Originally Posted by Idan Damri
    and i tried what you wrote before. it wont change something accept now its print only the columns.
    What is your current code?
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Create file from user input
    By Yash Agrawal in forum C Programming
    Replies: 1
    Last Post: 06-27-2013, 11:36 AM
  2. Odd results on user input array
    By deadrabbit in forum C Programming
    Replies: 4
    Last Post: 08-15-2011, 07:59 PM
  3. How to create a multi-dimensional user array?
    By stevedawg85 in forum C++ Programming
    Replies: 5
    Last Post: 03-22-2006, 02:01 AM
  4. array and user input
    By enlinux in forum C Programming
    Replies: 2
    Last Post: 07-20-2003, 02:08 AM
  5. How to let the user input values for an array...
    By TerranAce007 in forum C++ Programming
    Replies: 2
    Last Post: 08-24-2002, 03:54 AM