0

I checked and there are no syntax errors. I am using Code::Blocks for coding in C and this is the first time that I encounter a similar error. When I run the code, the console starts and closes after a second. It doesn't even print what is inside the printf.

#include <stdio.h>

int main(void)
{
    int n;
    int vet[n];
    int t;
    int i;
    int lim;
    int lastswap;
    int swap;

    printf("Array lenght:");
    scanf("%d\n", &n);
    for (i = 0; i < n; i++)
    {
        scanf("%d\n", &vet[i]);
    }
    lim = 0;
    do
    {
        swap = 0;
        for (i = n - 1; i > lim; i--)
        {
            if (vet[i] < vet[i - 1])
            {
                t = vet[i];
                vet[i] = vet[i - 1];
                vet[i - 1] = t;
                swap = 1;
                lastswap = i;
            }
            lim = lastswap;
        }

    } while (swap != 0);
    for (i = 0; i < n; i++)
    {
        printf("%d\n", vet[i]);
    }
}
Wolf
  • 9,679
  • 7
  • 62
  • 108
Iceyj
  • 1
  • 1
    Where do you initialize 'n'? – Igor R. Jan 24 '21 at 11:58
  • ...and where is the first use of `n`. What C standard are you using? – Wolf Jan 24 '21 at 12:00
  • 1
    If you say "console", what do you mean? A separated window or a part in the IDE? – the busybee Jan 24 '21 at 12:01
  • 1
    In most GUI environments such as Windows, when a process terminates its window closes. Your code runs to completion and terminates with no user interaction required. Wait for user input to confirm exit, or run the code from a separate command line session rather then directly from the IDE or the GUI desktop. You could also place a breakpoint at the end and run it in the debugger. I ran it and entered 3 at the prompt, and it waited for and sorted 4 entries. It is not a coding issue, it is a "how computers work" issue. – Clifford Jan 24 '21 at 12:03
  • @Clifford no in Code:Blocks, the console waits for a key at the end. The closing is caused by an error here. – Wolf Jan 24 '21 at 12:05
  • *this is the first time that i encounter a similar error* -- did you successfully use arrays before? – Wolf Jan 24 '21 at 12:06
  • I insert the n in the fifth row and then I use it in a scanf. I'm trying to ask the user to insert an array lenght, represented by the n. – Iceyj Jan 24 '21 at 12:06
  • @Iceyj what do you do with `n` in the sixth row? – Wolf Jan 24 '21 at 12:07
  • 1
    @Wolf maybe - he says he is using Code::Blocks to build it, he does not say he is running it in Code::Blocks, and it runs to completion https://onlinegdb.com/rJpe71j1d. If you are correct, then the solution is still to use the debugger. – Clifford Jan 24 '21 at 12:08
  • Yes, i did succesfully use arrays before – Iceyj Jan 24 '21 at 12:08
  • @Clifford I tried unchanged above code within the Code::Block IDE. If I run it in the debugger console from within the IDE, it stops with a Windows exception even before the initial `printf`, that is, *before* the first write access to `vet`. Looks like UB which I expected. IOW, I can confirm the behavior OP observes. After fixing the issues using the VLA version in my answer (with some minor improvments), the program works, sort of: it doesn't sort correctly. – Wolf Jan 25 '21 at 09:03
  • @Wolf : Good spot (uninitialised `n`). It is unsurprising that that is not the only issue, and reinforces my suggestion to use the debugger - surely that is a primary reason for using something like Code::Blocks? When it crashes, it indicates where it crashed. – Clifford Jan 25 '21 at 09:11
  • The "habit" of declaring all the variables at the top of the function is a hangover from C89 and has been unnecessary since C99 and is partially the cause of the error here. If you are going to use the ill-advised VLA feature, you have to declare the VLA _after_ you have determined the required size. In this case place `int vet[n];` _after_ `scanf("%d\n", &n);`. – Clifford Jan 25 '21 at 09:15
  • @Clifford If I recall correctly, even K&A and ANSI C allow declaring variables at the beginning of any scope. Maybe the fear of shadowing caused the convention to declare all local variables at the beginning of the function. It becomes really interesting in combination with the fear of function-call overhead that makes functions grow until they burst (i.e. break). – Wolf Jan 25 '21 at 09:40
  • 1
    @Wolf That is true, but the common practice (and mistaken belief amongst many) was to declare all variables at the top of the function. The point here is that the VLA can be declared immediately following the assignment of `n` which is not the case in C89. – Clifford Jan 25 '21 at 12:43

2 Answers2

4

Main issue

The value of n is undefined when it is being used to specify the size of array vet. This is an error and a C compiler should stop you from doing this (even if it's configured to C99 or C11).[1][2]

Dynamic array (on the heap)

The preferred approach to create an array of a size that is determined at runtime is to allocate memory on the heap.[2] For this, these steps should be taken in the correct order:

  • declare n
  • input n (also validate input: check scanf result, also if the input has a reasonable size)
  • allocate vet (as an int pointer via malloc)

... before you write to the array. BTW: Don't forget to free the memory after having used it.

So something like this could be your basic "framework" (change UPPER_LIMIT to your needs):

#define UPPER_LIMIT 1024 /* or enum { UPPER_LIMIT=1024 }; */

int n;
if (scanf("%d", &n) == 1) {
    if (0 < n && n < UPPER_LIMIT) {
        int* vet = malloc(n*sizeof *vet);
        if (vet) {

            /* work on vet */
        }
        free(vet);
    }
}

Fixed-size array

Another option is to use an array of fixed dimension, then you have to check the n from input to be within the range of the fixed array:

#define UPPER_LIMIT 1024 /* or enum { UPPER_LIMIT=1024 }; */

int n;
int vet[UPPER_LIMIT];
if (scanf("%d", &n) == 1) {
    if (0 < n && n < UPPER_LIMIT) {

        /* work on vet */
    }
}

Secondary issue

To use newlines in the format string of scanf causes issues discussed in Behaviour of scanf when newline is in the format string. So better switch to scanf("%d", &n); and scanf("%d", &vet[i]);. BTW: Don't forget to check the return value of scanf and the input.

Footnotes

[1] It's not clear why GDB online Debugger accepts this as valid code but this could be the topic of another question.

[2] C99 supports variable-length arrays (VLA), that is a way to declare arrays with a size that is determined at runtime. For this the size variable must be defined before the array declaration with a value greater than zero. (read more in Array declaration, section Variable-length arrays). C11 incorporates variable-size arrays as a implementation defined feature - that means that standard-compliant C99 code may not be portable. There is also no consensus about the actual benefit of VLAs see for example Difficulty in understanding variable-length arrays in C

Variable-size array C99(+):

#define UPPER_LIMIT 1024 /* or enum { UPPER_LIMIT=1024 }; */

int n;
if (scanf("%d", &n) == 1) {
    if (0 < n && n < UPPER_LIMIT) {
        int vet[n];

        /* work on vet */
    }
}
Wolf
  • 9,679
  • 7
  • 62
  • 108
  • 1
    It *is* possible to declare an array with size determined by a variable in a C implementation that supports the variable-length array feature (mandatory in C99, but optional in later versions of C). However, in that case it is the value of the variable at the point of the array declaration that matters, so you would need to move your declaration of `vet` to after you read `n`. – John Bollinger Jan 24 '21 at 16:36
  • @JohnBollinger I'm not sure it's a good idea to bring up that VLA facet in this case. – Wolf Jan 24 '21 at 20:43
  • See also this interesting [answer to *Why aren't variable-length arrays part of the C++ standard?*](https://stackoverflow.com/a/21519062/2932052) – Wolf Jan 24 '21 at 20:54
0

I kinda figured it out. I declared n as a constant deleted the scanf and it worked.

Wolf
  • 9,679
  • 7
  • 62
  • 108
Iceyj
  • 1
  • if you just declare `n` as constant, how can it work if you use `scanf` on it? Hereby you are causing undefined behaviour. – Wolf Jan 24 '21 at 12:24
  • 1
    I declared n as constant and deleted the scanf. – Iceyj Jan 24 '21 at 14:38
  • Seems you removed the first `scanf`. If you still `scanf` all the test values, it maybe better to have a look on [`rand`](https://en.cppreference.com/w/c/numeric/random/rand) in `` – Wolf Jan 24 '21 at 16:23
  • @Iceyj Please consider accepting Wolf answer, which provided a lot of good insides. – dreamcrash Jan 24 '21 at 20:46
  • All you needed to to was declare `vet[n]` _after_ the `scanf()`. That is not to say it would be "safe" from unreasonable input, applying some maximum check would be in order. If you take the trouble to post an answer to your own question , you probably ought to post the code. As it happens the unitialised `n` is already in @Wolf's more comprehensive answer, so this serves little purpose and could have simply been a comment. SO is not a discussion forum. – Clifford Jan 25 '21 at 09:24