3

I know that I can scanf certain amount of numbers with scanf for example for 3 numbers

scanf("%d %d %d",array[0],array[1],array[2]);

but how can I scan it if I didn't know how many numbers (integer, not float) I would input into an array before enter (NOT EOF)? for example

input : 12 43 23(enter) --> array[0]=12, array[1]=43, array[2]=23
input : 10 20 30 40 50(enter) --> array[0]=10, array[1]=20, array[2]=30, array[3]=40, array[4]= 50
etc..

It's about how to input the numbers into an integer array.

And if it's possible, I want to save it into an 2 dimensions array, for example

input : 12 43 23(enter) --> array[0][0]=12, array[0][1]=43, array[0][2]=23
input : 10 20 30 40 50(enter) --> array[1][0]=10, array[1][1]=20, array[1][2]=30, array[1][3]=40, array[1][4]= 50
juliussin
  • 295
  • 3
  • 20
  • 1
    Read the whole line and parse it some other way? The [`fgets`](http://en.cppreference.com/w/c/io/fgets) and [`strtol`](http://en.cppreference.com/w/c/string/byte/strtol) function can be used for this. – Some programmer dude Dec 05 '16 at 10:50
  • Wait, are you asking about how to make an array of the right size and add the numbers once you have them? – Iluvatar Dec 05 '16 at 10:53
  • @iluvatar yes something like that, I don't know how to explain what i want properly. – juliussin Dec 05 '16 at 10:55
  • so i should declare variable with [1000] ? That would be waste of memory right? – juliussin Dec 05 '16 at 11:02
  • You don't know how many numbers there may be. In this case, they just assumed you'd never have more than 1000, and 4000 bytes isn't that bad unless you're really low. – Iluvatar Dec 05 '16 at 11:04
  • You said "it is not about size, but how to input the numbers". But you can allocate memory, then `realloc` when you run out of space. – Weather Vane Dec 05 '16 at 11:04
  • 1
    dynamic memory will be handy here. – RoadRunner Dec 05 '16 at 11:05
  • Also the question was closed, so I can't answer directly (and I think what you're asking isn't quite a duplicate). You want to save them, so you could again make a large array `int buf[1000]` and then just keep a counter (use the `i` in the example) and do `buf[i] = a` to store the value (and make sure you don't get more than 1000 entries on a line). – Iluvatar Dec 05 '16 at 11:07
  • @Iluvatar I reopened now the OP has said it *is* about array size. This was the [proposed dup](http://stackoverflow.com/questions/11839712/how-do-i-use-scanf-to-take-an-arbitrary-amount-of-integers). – Weather Vane Dec 05 '16 at 11:08
  • @WeatherVane with the link u gave me, the numbers wasn't saved into an integer array, and if my array was 2 rows i cant use that codes – juliussin Dec 05 '16 at 11:13
  • This is getting less clear by the minute. You said you were ok with arrays, so why are you putting down an answer that satisified what you asked in the first place? Two rows - do you mean two lines of numbers each ending with `Enter`? And exactly how will the program know there are 2 and not 3 or 4 lines, without using `EOF`? – Weather Vane Dec 05 '16 at 11:15
  • @WeatherVane sorry, i have edited my post already, so how i input a EOF character into my program? I plan to use a certain symbol as the sign of end of row. Consider it some kind of matrix – juliussin Dec 05 '16 at 11:20
  • @WeatherVane with unknown columns and rows – juliussin Dec 05 '16 at 11:21
  • is there a maximum number of chars per line? – RoadRunner Dec 05 '16 at 11:21
  • On a unix system at least, you can send EOF with ctrl-d in a terminal. – Iluvatar Dec 05 '16 at 11:25

3 Answers3

1

Here's how you can store things in a (dynamically allocated) array. This does assume that the line length is limited to 1000 chars though. (Code adapted from How do I use scanf() to take an arbitrary amount of integers?)

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

int main() {
    int val_size = 2;
    int* vals = (int*)malloc(val_size * sizeof(int)); // initial array size
    char buffer[1000]; // for reading in the line
    int pos, bytes_read, num;
    int num_read = 0;

    if (fgets(buffer, sizeof(buffer), stdin) != 0) {
        for (pos = 0; sscanf(buffer+pos, "%d%n", &num, &bytes_read) != EOF; pos += bytes_read) {
            // resize the array if needed
            if (num_read >= val_size) {
                val_size *= 2;
                vals = (int*)realloc(vals, val_size * sizeof(int));
            }

            // store the value in the array
            vals[num_read] = num;
            num_read++;
        }
    }

    // print the values to prove it works
    for (int i = 0; i < num_read; i++) {
        printf("%d ", vals[i]);
    }
    printf("\n");

    free(vals); // important after you're done with it
}

You can wrap a while around the if to get multiple lines.

Community
  • 1
  • 1
Iluvatar
  • 1,537
  • 12
  • 13
  • let me try this program, wait please – juliussin Dec 05 '16 at 11:24
  • 1
    you should not cast return value from malloc/realloc. http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – AndersK Dec 05 '16 at 11:25
  • 1
    This seems like a religious war, yes? Or at least in the same vein as `if (a == 0)` vs `if (0 == a)`? Perhaps strictly speaking it alleviates some user error, there are pros and cons both ways. – Iluvatar Dec 05 '16 at 11:29
  • @Iluvatar dont see any pros – AndersK Dec 05 '16 at 11:31
  • 1
    http://stackoverflow.com/a/14879184/3761456 Granted, it's got a tenth the upvotes of the top one, yet they're there and it seems mostly stylistic to me at this point. – Iluvatar Dec 05 '16 at 11:32
  • 2
    Honeslty speaking `int *vals = malloc(val_size * sizeof *vals);` looks less cluttered than `int* vals = (int*)malloc(val_size * sizeof(int));` – RoadRunner Dec 05 '16 at 11:33
  • 1
    @lluvatar i dont buy that. this question is marked C, not C++. If you are using malloc in C++ you are definitely doing something wrong. – AndersK Dec 05 '16 at 11:34
  • There is nothing wrong with casting the result of malloc--it's just preference. –  Dec 05 '16 at 12:27
  • @Jerry, That is true. But it does feel silly to typecast `malloc` when it already returns `void*`. It just seems pointless. – RoadRunner Dec 05 '16 at 13:12
1

Here is come code showing how to scan the integers into a 2D array:

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

#define INITSIZE 5
#define BUFFSIZE 1000

void print_and_free(int **array, int rowsize, int colsize);
void check_ptr(void *ptr, const char *msg);

int
main(void) {
    int **array;
    size_t rowsize = INITSIZE, colsize = INITSIZE;
    int row = 0, col, numdigits;

    char buffer[BUFFSIZE];
    char *number;

    array = malloc(rowsize * sizeof(*array));
    check_ptr(array, "Allocation");

    printf("Enter digits(Enter blank line to end):\n");
    while (fgets(buffer, BUFFSIZE, stdin) != NULL && strlen(buffer) != 1) {
        col = 0;
        numdigits = 0;
        if (rowsize == row) {
            rowsize *= 2;
            array = realloc(array, rowsize * sizeof(*array));
            check_ptr(array, "Reallocation");
        }

        array[row] = malloc(colsize *sizeof(int));
        check_ptr(array[row], "Allocation");

        number = strtok(buffer, " ");
        while (number != NULL) {
            numdigits++;
            if (colsize == numdigits) {
                colsize *= 2;
                array[row] = realloc(array[row], colsize * sizeof(int));
                check_ptr(array[row], "Reallocation");
            }
            array[row][col] = atoi(number);
            col++;
            number = strtok(NULL, " ");
        }
        row++;
    }

    print_and_free(array, row, col);

    return 0;
}

void
print_and_free(int **array, int rowsize, int colsize) {
    int row, col;

    printf("Your numbers:\n");
    for (row = 0; row < rowsize; row++) {
        for (col = 0; col < colsize; col++) {
            printf("array[%d][%d] = %d", row, col, array[row][col]);
            if (col != colsize - 1) {
                printf(", ");
            }
        } 
        free(array[row]);
        array[row] = NULL;
        printf("\n");
    }

    free(array);
}

void
check_ptr(void *ptr, const char *msg) {
    if (!ptr) {
        printf("Unexpected null pointer: %s\n", msg);
        exit(EXIT_FAILURE);
    }
}
RoadRunner
  • 25,803
  • 6
  • 42
  • 75
  • Thank you, by the way what `size_t rowsize = INITSIZE, colsize = INITSIZE;` for? – juliussin Dec 05 '16 at 17:17
  • No worries @juliussin. Yeah they are just starting sizes to allocate space from `malloc`. I just assumed `5` would be a good starting size, and if your arrays end up being bigger, then just `realloc` more space. You can replace `size_t` with `int` if you want, that might be clearer for you. – RoadRunner Dec 05 '16 at 22:57
0

You may use a while loop and check for the return value of scanf. For example:

int num = 0;
int idx = 0;
int arr[100] = { 0 };
while( scanf( "%d", &num ) == 1 )
{
    arr[idx++] = num;
    if( idx == 99 )  // protect from array overflow
    {
        break;
    }
}
for( int i = 0; i < idx; i++ )
{
    printf( "%d\n", arr[i] );
}
artm
  • 17,291
  • 6
  • 38
  • 54