Thread: Little Array Difficulty

  1. #1
    Registered User
    Join Date
    Mar 2008
    Posts
    71

    Little Array Difficulty

    Hello all,

    I'd first like to say that I'm pretty much a beginner in C, so this and other problems I post may seem trivial to many of you. All I can ask for is patience and forgiveness

    Now, on to my problem. For some time now, I have been bugged with the issue of making a "really dynamic array". To be more specific, an array whose size would be defined by the length of the string. If the array content where to be, say "Hello World", the array would be of size [12]. If the content of the array were to be "C", the array would be size [2]. You can always just define a big enough array (something like ar_word[500]; ) but thats just way too...inelegant. Anyway, I had an idea solving this problem that pretty much worked out:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      int x = 0;                                        /*Will be the size of the array*/
      char word[x];                                     /*The actual array*/
      while ((word[x] = getchar()) != '\n') {           /* User presses a key, the corresponding character is then loaded into word[x]. AFTER that the program determines whether or not "Enter" was pressed*/
    	char word[++x];                             /*x is enlarged by one, thus also the array size*/
      }
      word[x]='\0';                                     /*When the loop ends, the last "column" of word has the value of "\n". That is replaced with the value of "\0"*/
      printf("%s",word); 
      return 0;
    }

    The problem with this code is that the limit is 32. Once you go above 32 characters, the array size goes back to zero (I've strlen'd the array and then compared it to the value of x. While x is 33 or more, the length of "word" is zero). I guess this has something to do with the 32bit environment I'm working in, but then again I'm not sure.

    My question: does anyone know how I can get around this? Either that, or does anyone know another whay of making a "really dynamic array"?

    Thanks in advance for all help and advice.

  2. #2
    Nub SWE
    Join Date
    Mar 2008
    Location
    Dallas, TX
    Posts
    133
    Look into the topic of linked lists for a truly dynamic array, in my opinion. This way, you can allocate each node as you need it and keep track of the "array" length as you add or subtract nodes. If you're familiar with pointers (or willing to learn), I would suggest this approach.

  3. #3
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    I would also suggest you turn on warnings and switch to a decent compiler...

    First of all, this isn't correct
    Code:
    int x = 0;
    char word[x];
    Since you can't declare the size of an array with something else than a CONSTANT expression (i think, C99 might have change something about this, but i'm not sure actually...). Also, declaring an array of size 0 is semantically really poor. And i'm a bit surprise it actually works.

    Also
    Code:
    char word[++x];                             /*x is enlarged by one, thus also the array size*/
    First, the syntax is incorrect (the word char shouldn't be there since word as already been declared). Second, if you change the value of x, it doesn't change the size of an array, once it is set (at declaration) it cannot be resized.

    Of course, if you use malloc or calloc, then you can make a dynamic array. I bet there's some link about dynamic arrays in the FAQ.

    As to how to solve your problem, it isn't that simple to make something efficient (that's it, not calling realloc at every loop iteration) who don't "waste" no memory directly. The simplest way is to have a big enough array for the user input to be stored, than copy that input into an dynamically allocated array with just the right size (strlen(...) + 1).
    I hate real numbers.

  4. #4
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    This is a standard programming task for strings. It's done with an array of pointers to char, and does just what you want.

    Lists are OK, if you like LISTS, but google or search the forum tutorial for it, and you'll be good to go.

  5. #5
    Registered User
    Join Date
    Mar 2008
    Posts
    71
    I'm not familiar with pointers, since pointers were the point where I stopped learning C. However, that was with online tutorials, no I have a book that I can carry everywhere, and I think it'll be explained nicely there. Or, to be more precise, I hope I'll have a look, thanks ;-)

    As for malloc/calloc, I was sort of expecting them to come up. That's another thing I'm not familiar with (I mean usage), but will try to learn. Again, thank you.

    As for the compiler, I am using Code::Blocks, and the code compiled and executed fine. I'm also extremely surprised about the zero length of the array, but when I changed x to one, it didn't work anymore. Strange...

    Anyway. Thanks again, I'll have a look at the stuff you recommended and see what I can do

  6. #6
    Registered User sndpchikane's Avatar
    Join Date
    Mar 2008
    Posts
    5
    hey dude,

    As i studies C Programming last semester in my college.

    C program is divided into 3 sections

    1)preprocessor declarartion like "#include <stdio.h>"

    2)Declaration statements like "int a; char b[20]"

    3)Actual code logic

    The above order is predefined and can not b changed

    As your program contains:

    Code:
    char word[++x];
    which is in code i.e. logic section.

    you will get error like "Declaration not allowed here"

    Have you got my point?

    In you havent please reply.

  7. #7
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by sndpchikane View Post
    The above order is predefined...
    Actually, it isn't. There's no rule where you can place pragmas and although C89 says that variables must be defined at the beginning of a block, C99 and C++ does not. They can be defined anywhere.

    As for the problem at hand, to make a dynamic array, what you need to do is this:
    1) Allocate a block of memory with malloc.
    2) Keep track of the current size.
    3) Use array.
    4) If the size exceeds what you currently have, reallocate with realloc to extend the size.
    5) Repeat.
    6) Free allocated memory with free.

    Also note that you might want to allocate say 100 bytes first, then double it on the next realloc and so on because extending by one byte all the time is extremely inefficient.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  8. #8
    Registered User
    Join Date
    Mar 2008
    Posts
    71
    You know, I was seriously thinking about writing what you have in your signature for the sixth time, but since five is my lucky number, I won't. Consider it said however

    I'm about to get to malloc in the book I'm reading, so I'll see what I can do after that.

    As for the char word[++x]; part, I know it's inelegant. I don't like it either. To be honest, I'm surprised it even worked (yes, it did work, I repeat, I compiled and ran the program under Code::Blocks without any problems whatsoever) but with my current (and very insufficient I might add) knowledge of C, this was the only solution I could come up with.

  9. #9
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    First, Code::Blocks isn't a compiler, but it's an IDE.

    Second, it's not because it compiles "fine" that your source code is fine.

    Third, here's the errors Visual Studio 2005 generated when i compiled your code with it

    Code:
    Error	1	error C2057: expected constant expression		7	
    Error	2	error C2466: cannot allocate an array of constant size 0		7	
    Error	3	error C2133: 'word' : unknown size		7	
    Error	4	error C2057: expected constant expression		9	
    Error	5	error C2466: cannot allocate an array of constant size 0		9	
    Error	6	error C2133: 'word' : unknown size		9
    I suggest you turn on warnings on your compiler.
    I hate real numbers.

  10. #10
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    gcc acting in C99 mode seems to have masked a number of issues for G4B3(?).
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  11. #11
    Registered User
    Join Date
    Mar 2008
    Posts
    65
    Here is a real simple answer, and I think it works. I really don't know much about c, so don't blame me if it doesn't, but if you re declare the string length every time, shouldn't it not reset?

    Anyway, here is what I found to work pretty well:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      int x = 0;                                        
      char word[x];                                     
      while ((word[x] = getchar()) != '\n') {           
    	++x; 
        char word[x];                            
      }
      word[x]='\0';                                     
      printf("%s",word); 
      getchar();
      return 0;
    }
    If this doesn't work, or my logic is flawed, please point that out.
    Thanks
    -Matt

  12. #12
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    Which word is the word that you think is word?
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  13. #13
    Chinese pâté foxman's Avatar
    Join Date
    Jul 2007
    Location
    Canada
    Posts
    404
    Indeed, i just compiled the code with gcc (version 3.4.4, on Windows) using the -std=c99 and -Wall options, and now i understand a bit more G4B3 situation. I might have jumped to conclusion to early. Sorry for this.

    But what i do not understand, is why gcc isn't complaining about declaring an array of 0 elements ? Is it because the standard says nothing about this ?

    Anyway, the source code might be syntactically correct, the semantic is poor.

    I would be curious to run the code in a debugger or have a look at the assembly code generated. But for now, it's bed time.
    I hate real numbers.

  14. #14
    Just Lurking Dave_Sinkula's Avatar
    Join Date
    Oct 2002
    Posts
    5,005
    I didn't find anything about declaring a VLA with zero size. (But I have missed a number of things lately.)
    6.7.5.2 Array declarators
    Constraints
    1 In addition to optional type qualifiers and the keyword static, the [ and ] may delimit
    an expression or *. If they delimit an expression (which specifies the size of an array), the
    expression shall have an integer type. If the expression is a constant expression, it shall
    have a value greater than zero. The element type shall not be an incomplete or function
    type. The optional type qualifiers and the keyword static shall appear only in a
    declaration of a function parameter with an array type, and then only in the outermost
    array type derivation.
    2 Only an ordinary identifier (as defined in 6.2.3) with both block scope or function
    prototype scope and no linkage shall have a variably modified type. If an identifier is
    declared to be an object with static storage duration, it shall not have a variable length
    array type.
    Semantics
    3 If, in the declaration ‘‘T D1’’, D1 has one of the forms:
    D[ type-qualifier-listopt assignment-expressionopt ]
    D[ static type-qualifier-listopt assignment-expression ]
    D[ type-qualifier-list static assignment-expression ]
    D[ type-qualifier-listopt * ]
    and the type specified for ident in the declaration ‘‘T D’’ is ‘‘derived-declarator-type-list
    T’’, then the type specified for ident is ‘‘derived-declarator-type-list array of T’’.121)
    (See 6.7.5.3 for the meaning of the optional type qualifiers and the keyword static.)
    4 If the size is not present, the array type is an incomplete type. If the size is * instead of
    being an expression, the array type is a variable length array type of unspecified size,
    which can only be used in declarations with function prototype scope;122) such arrays are
    nonetheless complete types. If the size is an integer constant expression and the element
    type has a known constant size, the array type is not a variable length array type;
    otherwise, the array type is a variable length array type.
    5 If the size is an expression that is not an integer constant expression: if it occurs in a
    declaration at function prototype scope, it is treated as if it were replaced by *; otherwise,
    each time it is evaluated it shall have a value greater than zero. The size of each instance
    of a variable length array type does not change during its lifetime. Where a size
    expression is part of the operand of a sizeof operator and changing the value of the
    size expression would not affect the result of the operator, it is unspecified whether or not
    the size expression is evaluated.
    6 For two array types to be compatible, both shall have compatible element types, and if
    both size specifiers are present, and are integer constant expressions, then both size
    specifiers shall have the same constant value. If the two array types are used in a context
    which requires them to be compatible, it is undefined behavior if the two size specifiers
    evaluate to unequal values.
    7. It is easier to write an incorrect program than understand a correct one.
    40. There are two ways to write error-free programs; only the third one works.*

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Quote Originally Posted by G4B3 View Post
    You know, I was seriously thinking about writing what you have in your signature for the sixth time, but since five is my lucky number, I won't. Consider it said however
    That doesn't count

    Quote Originally Posted by mcotter222 View Post
    Here is a real simple answer, and I think it works. I really don't know much about c, so don't blame me if it doesn't, but if you re declare the string length every time, shouldn't it not reset?

    Anyway, here is what I found to work pretty well:
    Code:
    #include <stdio.h>
    #include <string.h>
    
    int main()
    {
      int x = 0;                                        
      char word[x];                                     
      while ((word[x] = getchar()) != '\n') {           
    	++x; 
        char word[x];                            
      }
      word[x]='\0';                                     
      printf("&#37;s",word); 
      getchar();
      return 0;
    }
    If this doesn't work, or my logic is flawed, please point that out.
    Thanks
    -Matt
    Nope, what this does is define another variable word inside the while loop which hides the other word array outside the loop. Further, the array is destroyed and redefined on each iteration. Again, this requires C99.
    Also note that you get undefined behavior since x > 0 at the end of the loop and your array size == 0.

    To create a dynamic array, you need to do so with malloc and free. That's just the way it works. Consider an example:

    Code:
    int size = 100;
    char* word = malloc(size);
    while ((word[x] = getchar()) != '\n')
    {
    	x++;
    	if (x == size)
    	{
    		size *= 2;
    		char* temp = realloc(word, size);
    		if (!temp) { /* ERROR! DO ERROR HANDLING HERE! */ }
    		word = temp;
    	}
    }
    Requires C99.
    Last edited by Elysia; 03-19-2008 at 12:59 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. from 2D array to 1D array
    By cfdprogrammer in forum C Programming
    Replies: 17
    Last Post: 03-24-2009, 10:33 AM
  2. Replies: 7
    Last Post: 11-25-2008, 01:50 AM
  3. 1-D array
    By jack999 in forum C++ Programming
    Replies: 24
    Last Post: 05-12-2006, 07:01 PM
  4. Class Template Trouble
    By pliang in forum C++ Programming
    Replies: 4
    Last Post: 04-21-2005, 04:15 AM
  5. Quick question about SIGSEGV
    By Cikotic in forum C Programming
    Replies: 30
    Last Post: 07-01-2004, 07:48 PM