0

I have a console-input space separated list of integers of n length(n is read in through the console) which needs to be split into the integers and placed in an array of size n. I have attempted this with both fscan and fgets, to either a segmentation fault or the console locking and not letting me enter the list. Any advice:

int main()
{
        int n;
        scanf("%d", &n);
        int buffer = n + n -1;
        char input[buffer];
        //char * input;
        //int buffer = n+n-1;
        //fgets(input, buffer, stdin);
        scanf("%*c", &input);
        printf("c is %c", input[0]);
        char * end;
        long int l;
        end = input;
        int base = 10;
        int ele = 0;
        long int vals[n];
        while(l = strtol(end, &end, base)){
                vals[ele] = l;
                ele += 1;
        }
        return 0;
user8232299
  • 37
  • 1
  • 7

2 Answers2

0

There are a number of things going on in your code. Here is a basic example of reading a variable-sized array from standard input:

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

int main()
{
  int n;
  int *xs;

  /* read n */
  if (!scanf( "%d", &n ) || (n <= 0))
  {
    fprintf( stderr, "%s\n", "invalid n: n <= 0 or n is not an integer" );
    return 1;
  }

  /* allocate xs[n] */
  xs = (int*)malloc( n * sizeof(int) );
  if (!xs)
  {
    fprintf( stderr, "failure to allocate %d integers\n", n );
    return 1;
  }

  /* read xs[] */
  { 
    int i;
    for (i = 0; i < n; i++)
      if (!scanf( "%d", &(xs[i]) ))
      {
        fprintf( stderr, "%s\n", "invalid x: x is not an integer" );
        free( xs );
        return 1;
      }
  }

  /* ... */

  /* print xs[] in reverse order */
  {
    int i = n;
    while (i--)
      printf( "%d ", xs[i] );
    puts( "" );        // Here's your newline
    fflush( stdout );  // POSIX only mandates flush to terminal, and only by default
  }

  free( xs );
}

This should help you get on track.

[edit] Modified as per commentary below:

  • Casting to (int*) is not necessary in C, but it:
    • declares intent
    • can be compiled with a C++ compiler without error
  • Added very simple error handling
    ("dog" will now refuse to be accepted as input)
  • Added newline. Note that using fflush() is fully POSIX compliant. POSIX only mandates that terminal default to flush on newline. No newline → need to flush. Piping to file → please flush.
Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • 1
    There is no need to cast the return of `malloc`, it is unnecessary. See: [**Do I cast the result of malloc?**](http://stackoverflow.com/q/605845/995714). What would happen if the input was `1 2 3 4 cat 5 dog 6 ... 7`? How would you know? What about checking the **return** of `scanf` and handling any *matching* or *input* failures? Removing `fflush( stdout );` and adding `putchar ('\n')` after the loop would help make your program POSIX compliant. – David C. Rankin Sep 28 '17 at 04:59
0

Whether your compiler supports the Variable Length Array extensions:

#include <stdio.h>

int main (void) {

    int n, tmp, ndx = 0;
    if (scanf ("%d", &n) != 1 || n < 1) {
        fprintf (stderr, "error: invalid input - n.\n");
        return 1;
    }
    int a[n];

    while (ndx < n && scanf ("%d", &tmp) == 1) {
        a[ndx] = tmp;
        printf ("a[%3d] : %d\n", ndx, a[ndx]);
        ndx++;
    }

    return 0;
}

or you choose to allocate your array dynamically:

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

int main (void) {

    int n, *a, tmp, ndx = 0;
    if (scanf ("%d", &n) != 1 || n < 1) {
        fprintf (stderr, "error: invalid input - n.\n");
        return 1;
    }

    if (!(a = calloc (n, sizeof *a))) { /* allocate/validate */
        fprintf (stderr, "error: virtual memory exhausted.\n");
        return 1;
    }

    while (ndx < n && scanf ("%d", &tmp) == 1) {
        a[ndx] = tmp;
        printf ("a[%3d] : %d\n", ndx, a[ndx]);
        ndx++;
    }

    free (a);   /* don't forget to free allocated memory */

    return 0;
}

Always, always, validate all user input (before assigning the value from the conversion to your array) scanf has a return just for that purpose. You must handle matching or input failures in some fashion.

Example Input

$ cat dat/n_10_ints.txt
10
8572
-2213
6434
16330
3034
12346
4855
16985
11250

Example Use/Output

$ ./bin/readnints <dat/n_10_ints.txt
a[  0] : 8572
a[  1] : -2213
a[  2] : 6434
a[  3] : 16330
a[  4] : 3034
a[  5] : 12346
a[  6] : 4855
a[  7] : 16985
a[  8] : 11250
a[  9] : 1495

Look things over and let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85