0

I'm trying to make an array with variable starting length to get a string. The code should count the words and adjust the size of the array, but this is only a test and I expose it here because I want to know if it's a good practice or one error. And if there is something I should know about, or I must have in mind.

Note, I talk about C, not C++

#include <stdio.h>
int main()
{       int c,b,count;
        scanf("%d",&c);
        count=c+1;
        getchar();
        char a[count];
        for ( c=b=0 ; c!=count && b!='\n' ; c++ )
        {
                b=getchar();
                a[c]=b;
        }
        a[c]='\0';
        printf("%s",a); printf("%d",c-1);
}

I don't need change the size of the array at the execution time.

I was testing and I don't remember well why I'm using the c variable at first time instead of count directly, but I remember the first getchar was to flush the buffer, because it didn't work without the getchar.

I don't know why I need to put getchar. If I delete the getchar the program fails.

Anyway the program works fine. The first time you run, it expects a number with scanf and then expects the text.

If the text is larger than the size of the array the program will ignore it.

The number is the size of the array.

My questions are:

It is a good practice do a[variable] to do this job?

Why I need the getchar?

It will be portable? I mean, I don't know if some systems or standards don't accept this like some old C compilers or somewhat.

There are better methods?

  • VLA is supported in C99, but not in legacy C nor in C++, which makes your code pretty unportable, hence probably not a very good practice. – goodvibration Dec 03 '17 at 22:12
  • ty. I had no idea what was happening with the getchar –  Dec 03 '17 at 22:20
  • 2
    @goodvibration it's 18 years since C99 now, surely that is enough time to update compiler for everyone. Other languages are irrelevant – M.M Dec 03 '17 at 22:26
  • 1
    @goodvibration "pretty unportable"?! It has been the standard for 18 years. It is as if you'd recommend the use of `` on HTML page to be compatible with Netscape 2.0. Also C and C++ are different languages. What kind of pidgin creole are you suggesting? – Antti Haapala -- Слава Україні Dec 03 '17 at 22:27
  • This question is really about the `getchar()` and nothing to do with the array (besides the case of overflowing the array) – M.M Dec 03 '17 at 22:27

3 Answers3

1

It is a good practice do a[variable] to do this job?

It depends on someone's compiler configuration. It has been supported since C99. However since there's not a good reason to use it in such a simple program, use the standard malloc instead. Here's an in-depth discussion of the topic.

Why I need the getchar?

There's likely some input still buffered up in your terminal, and that first character is discarding it. Try printing the value out to the screen to see what it is, that might help as figure it out.

It will be portable?

See my answer to your first question. It will probably work on modern versions of gcc, but for example it doesn't work in Windows C (which is still basically on C89).

Tim Sweet
  • 636
  • 5
  • 15
  • 1
    Seriously?! Non-standard extension?! So what do the ISO and ANSI produce? Toilet paper?! – Antti Haapala -- Слава Україні Dec 03 '17 at 22:13
  • Sorry, that was a mistake, I fixed it and clarified that the latest standards support it. – Tim Sweet Dec 03 '17 at 22:14
  • 1
    There are no "latest standards". There is only one standard. The C programming language. It has only one revision in effect, C11. All others have been revoked. Granted, the VLA are now *optional* but MSVC too now supports them. – Antti Haapala -- Слава Україні Dec 03 '17 at 22:16
  • @AnttiHaapala I clarified my answer again, thanks. MSVC does not support VLAs in C by default, do you have a reference for an option that enables them? – Tim Sweet Dec 03 '17 at 22:22
  • @Thewackomadman yes, you'd use `char *a = (char*)malloc(count);` – Tim Sweet Dec 03 '17 at 22:23
  • 2
    Also one doesn't cast the return value of `malloc`. This question was tagged in [tag:c], not [tag:c++]. – Antti Haapala -- Слава Україні Dec 03 '17 at 22:28
  • @AnttiHaapala I found the same MSDN article but it is just a copy of the OpenMP documentation. I cannot find anywhere else which specifically lists an option for enabling it. – Tim Sweet Dec 03 '17 at 22:30
  • @TimSweet dammm you might be correct about that. I've always thought it does support them. Yeah, when compiling C I guess one should use a *C* compiler :-/ – Antti Haapala -- Слава Україні Dec 03 '17 at 22:33
  • @AnttiHaapala is correct that it is not **required** to cast the result of `malloc` (for OP's reference: this is because `void*` is automatically converted to any other compatible type). [Some people](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) say specifically not to do it, however there are plenty of cases (especially when a company's code standard requires it) where you still would cast the result. A static analysis tool would have caught the other issues in the linked post. Cluttering the code is the only real reason left over, and that is subjective. – Tim Sweet Dec 03 '17 at 22:35
  • @AnttiHaapala I wouldn't be surprised if there was an undocumented command line option hidden down in Microsoft's compiler (so you may have even used code within MSVC that enabled it!), but I am yet to find it. – Tim Sweet Dec 03 '17 at 22:37
  • I've not used MSVC for *10 years*. – Antti Haapala -- Слава Україні Dec 03 '17 at 22:41
0

It is a good practice do a[variable] to do this job?

Where the size is determined by arbitrary user input without imposed limits, it is not good practice. A user could easily enter a very large value and overrun the stack.

Use either dynamic allocation, or check and coerce the input value to some sensible limit.

Also worth noting that VLAs are not supported in C++ or some C compilers, so the code lacks portability.

Why I need the getchar?

The user has to enter at least a newline for scanf() to return, but the %d format specifier does not consume non-digit characters, so it remains buffered. However your code is easily broken by entering additional non-digit characters for example "16a<newline>" will assign 16 to c, and the a will be discarded leaving the newline buffered as before. A better solution is:

while( getchar() != `\n` ) {}

It will be portable? I mean, I don't know if some systems or standards don't accept this like some old C compilers or somewhat.

Adoption of C99 VLAs is variable, and in C11 they are optional in any case.

There are better methods?

I hesitate to say "better", but safer and more flexible and portable ways sure. With respect to the array allocation, you could use malloc().

Clifford
  • 88,407
  • 13
  • 85
  • 165
-1

Using malloc or calloc would be a better choice in C

https://www.tutorialspoint.com/c_standard_library/c_function_malloc.htm

Waqas
  • 615
  • 1
  • 8
  • 20