0

I learned in the text book, that there are only a few ways you can initialize an array.

Method one:

int ary[5] = {1,2,3,4,5};

Method two:

int ary[] = {1,2,3,4,5};

But what if I want to input user defined values into the array. Would this code be ok? Can anyone teach me a better way to do this?

#include<stdio.h>
#include<conio.h>

int main()
{
    int i, n;
    printf("Enter array parameter: \n");
    scanf("%d",&n);
    int a[n]; 
    int b[n];
    
    for(i=0;i<n;i++)
    {
        printf("Enter value for array a[%d]: \n",i+1);
        scanf("%d",&a[i]);
    }
    n -= 1; 
    for(i=0;i<=n;i++)
    {
        b[i]=a[n-i];
    }
    printf("Value of array b[] is: \n");
    for(i=0;i<=n;i++)
    {
        printf("%d ",b[i]);
    }
    for(i=0;i<=n;i++)
    {
        printf("\narray b[%d] = %d ",i,b[i]);
    }
    
    getch();
}

enter image description here

phatx88
  • 35
  • 5
  • 2
    `int ary[5] {1,2,3,4,5};` - you cannot do it in C. It's valid in C++11 – Jorengarenar Jul 13 '20 at 05:36
  • 4
    Your code is fragile. You cannot use any user-input function, e.g. `scanf("%d",&n)` correctly unless you **check the return**, e.g. `if (scanf("%d",&n) != 1) { fputs ("error: invalid integer input.\n", stderr); return 1; }` Otherwise, understand you are using *Variable Length Arrays* (VLAs) which may not be supported by all compilers beginning with C11. Don't include `conio.h`, that ancient DOS header makes your code 100% non-portable to anything other than window. `stdio.h` provides all you need. Just use `getchar()` to hold your window open instead of `getch()`. – David C. Rankin Jul 13 '20 at 05:36
  • I digest but what is C11? and I use Dev C++ 5.11. What are the compiler version people been talking about? – phatx88 Jul 13 '20 at 06:00
  • Your output is just plain text. No need to add a screenshot instead of simply copy&paste it as text into your question. – Gerhardh Jul 13 '20 at 07:35
  • C11 is the 2011 version of the C standard. But beware, the first comment did not mention C11, but C++11 which is 2011 version of C++. And as we know, C and C++ are very different languages. – Gerhardh Jul 13 '20 at 07:36

5 Answers5

1
int ary[5] {1,2,3,4,5};

This is not a valid array initialization. It should be

int ary[5] = {1,2,3,4,5};

Note the equal sign.

Other wise your array initialization is valid for C99 and above. Plain c would not allow the use of a variable to initialize the array size.

kereh
  • 41
  • 3
  • That is the ISO/IEC 9899:1999[9] C standard. See the link for details on C standards: [link](https://en.wikipedia.org/wiki/ANSI_C) – kereh Jul 13 '20 at 06:19
0

Array initializing in C:

int ary[5] {1,2,3,4,5};

This is invalid syntax in c (this is valid in c++).

there is 3 ways to initialize c arrays:

  1. with the curly brackets {} like you did (int ary[] = {1,2,3,4,5};)
  2. iterating on the array elements one by one in for loop and initialize each one of them.
  3. via : memset(void *str, int c, size_t n);, for padding the whole array in the same value. e.g. if i want to initialize the array with 0x0, then, memset call will lokks like: memset(arr, 0x0, sizeof(arr));

Regarding the you code:

  1. for each scanf(..) in the code you have to check and validate scanf("%d",&n);, return/errors and user input in n before make any progress in your code. How you check? see later.
  2. In you situation, it's good to limit the user input n and validating that n in defined range (N_min <= n <= N_max), rather than causing to huge array allocating on the stack in case n was set to maximum value by user!
if(scanf("%d",&n) == EOF){
    /*errors ocuured*/
    f_invoke_error_handling_rotuine(); 
}

In f_invoke_error_handling_rotuine(..), you can do what ever your code needs to perform, maybe abort() with error message, maybe setting default values to n...etc.

see reference for memset and scanf in man7.org: scanf, memset

Adam
  • 2,820
  • 1
  • 13
  • 33
0

You have a large number of issue, Undefined Behavior being the most critical:

n -= 1; 
for(i=0;i<=n;i++)
{
    b[i]=a[n-i];
}

When i == n, you index one beyond the end of your b[] array. All arrays in C are zero-indexed, so your loop limits are 0 <= i < n. By using i<=n you loop one-too-many times.

You fail to check the return of any user-input. Try entering '"one"', or accidentally hitting 'r' instead of 4 and see what happens. You must check the return for every user-input and handle the error. What happens if the user enters 1, 2, 'r', 5? You must also empty stdin of any extraneous characters or they will bite you again on your next input.

Don't use conio.h. That makes your code 100% non-portable. You can use the functions in stdio.h for your needs.

That said, when you need to do repetitive tasks like taking integer input, write a short function to do it. You can write one that takes a pointer to the integer to fill, and a pointer to the prompt to display and returns 0 on success or -1 if the user cancels input by generating a manual EOF with Ctrl+d on Linux or Ctrl+z on windows. You can add a helper-function to empty stdin, e.g.

void empty_stdin (void)
{
    int c = getchar();
    
    while (c != '\n' && c != EOF)
        c = getchar();
}

int getint (int *n, const char *prompt)
{
    int rtn;
    
    for (;;) {
        fputs (prompt, stdout);
        rtn = scanf ("%d", n);
        if (rtn == EOF) {
            fputs ("  (user canceled input)\n", stderr);
            return -1;
        }
        else if (rtn == 0) {
            fputs ("  error: invalid integer input.\n", stderr);
            empty_stdin();
        }
        else
            break;
    }
    empty_stdin();
    
    return 0;
}

The rest of your program to read an array in a[] and reverse it in b[] is simply:

int main (void) {
    
    int i = 0, n;
    
    if (getint (&n, "Enter array parameter: ") == -1)
        return 0;
    
    int a[n], b[n];
    
    for (i = 0; i < n; i++) {
        char buf[128];
        sprintf (buf, "enter value for a[%d]: ", i+1);
        if (getint (&a[i], buf) == -1)
            return 0;
    }
    for (i = 0; i < n; i++)
        b[i] = a[n - 1 - i];
    
    puts ("\nvalue of array b[]:");
    for (i = 0; i < n; i++)
        printf (" %d", b[i]);
    putchar ('\n');

#if defined (_WIN32) || defined (_WIN64)
    getchar();  /* hold terminal open on windows - type any char, hit return */
#endif
}

Example Use/Output

All valid inputs:

$ ./bin/getarray
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]: 2
enter value for a[5]: 1

value of array b[]:
 1 2 3 4 5

Errors in input:

$ ./bin/getarray
Enter array parameter: foo
  error: invalid integer input.
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: four
  error: invalid integer input.
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]: I'm getting tired of this game...
  error: invalid integer input.
enter value for a[4]: 2
enter value for a[5]: 1

value of array b[]:
 1 2 3 4 5

User cancels input:

$ ./bin/getarray
Enter array parameter: 5
enter value for a[1]: 5
enter value for a[2]: 4
enter value for a[3]: 3
enter value for a[4]:   (user canceled input)

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

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

As someone noted, the first way does not work in C. It is valid C++ though.

The second way int ary[] = {1,2,3,4,5}; works, the array ary is initialized with 5 items at compile time (before you even run the program). The memory is allocated on the stack.

You could also do it like this int ary[6] = {1,2,3,4,5};, where you specify what length you want the array to be. You can then access ary[5] and change it to whatever value you want (by default it is 0).

NOTE: ary[6] is out of bounds, since the array's elements go from 0 to 5.

In your code, you make use of something called Variable Length Arrays (VLAs), and as noted by Wikipedia, they are allocated with automatic storage duration on the stack. This means that when the function where you declared them ends, their life duration also ends (they are local to the function scope you declare them in). To understand why this is important, consider this piece of code:

int *func(int n) {
   int v[n]; // variable length array

   v[0] = 1;
   v[1] = 2;
   v[2] = 3;

   return v;   // this will not work, variable length arrays will be destroyed
               // when the function they belong to goes out of scope
}

int main() {
   int *v;
   v = func(3);  // when you will try to access the memory in v, it will be undefined 
                 // behaviour (can seg fault, the memory is not yours anymore)
   // print values in v
   return 0;
}

To fix this issue, you need to use malloc defined in stdlib.h.

int *func(int n) {
   int *v = malloc(sizeof(int) * n); // allocate memory for n elements

   v[0] = 1;
   v[1] = 2;
   v[2] = 3;

   return v;   // this will now work
}

int main() {
   int *v;
   v = func(3); // this will work
   // print values in v
   free(v);
   return 0;
}

The reason this works is because memory allocated using malloc is allocated on the heap, meaning it survives the whole duration of the program unless you deallocate it yourself (this means that you need to free the memory at the end using the function free).

Alex Gh
  • 55
  • 5
0

"Would this code be ok? Can anyone teach me a better way to do this?"

This code is okay from a syntactical perspective (you corrected the wrong initialization), but not portable since you use variable length arrays (VLAs) which might not supported by any implementation (They are provided my compiler extensions) and were only fully compliant to the C99 standard.

A better way to do this, is to use malloc() instead and allocate the memory for the array on the heap.

This also has the advantage that you can resize the array if you want to (make it larger f.e.) and free() the memory for the array when no longer needed.

Related stuff:


int i, n;

printf("Enter amount of array elements: \n");
if (scanf("%d",&n) != 1)
{ 
    fputs("Error at input!", stderr);
    return EXIT_FAILURE;
}

int* a = malloc ( sizeof(*a) * n );
if (!a)
{ 
    fputs("Error at allocation for a!", stderr);
    return EXIT_FAILURE;
}

int* b = malloc ( sizeof(*b) * n );
if (!b)
{ 
    fputs("Error at allocation for b!", stderr);
    return EXIT_FAILURE;
}

for (i = 0; i < n; i++)
{
    printf("Enter value for array a[%d]: \n", i);
    if (scanf("%d", &a[i]) != 1)
    { 
       fprintf(stderr, "Error at input for a[%d]!", i);
       return EXIT_FAILURE;
    }
}

...

free(a);
free(b);