Thread: Unable to allocate array size at runtime

  1. #1
    Registered User
    Join Date
    Apr 2004
    Posts
    27

    Exclamation Unable to allocate array size at runtime

    Hello all,

    I have the array
    Code:
    char string[5000];
    that I use to read in characters from a text file. I would like the size at run time to be changed to the number returned by my function totalcharacters(location), instead of me making this array big enough all the time to fit the text file I'm reading in.

    Here is what I have tried:

    PHP Code:
    char *string;
    string=(char*)calloc(totalcharacters(location),1); 
    My reasoning here is that I would like the array to have elements of size equal to the number of characters from my function totalcharacters() all at one byte each, as characters only take one byte of space.

    However this does not allow the array “string” to be what I want.

    My pseudo code of what I would like to achieve is

    Code:
    string[number of total characters from text file]
    Any guidance greately appreciated,
    CookieMonster
    Last edited by CookieMonster; 04-02-2004 at 05:57 PM.

  2. #2
    Novice C++ Programmer
    Join Date
    Nov 2003
    Posts
    96
    Try using realloc() like this:

    Code:
    temporary_variable = realloc(string,totalcharacters(location));
    
    string = temporary_variable;

    But my advice to you would be making the array a little bit bigger than the amount of characters it is going to hold. Also, your totalcharacters() function will need to return an int for this to work.
    Last edited by Padawan; 04-02-2004 at 06:07 PM.

  3. #3
    Hi CookieMonster,

    Well, I have some news. When using a char array[] you don't have to worry about allocation memory. Only when using a char pointer. Example:

    Code:
    char string1[5000];
    char *string2;
    char *string3;
    
    // When using array, use null terminator to truncate string size
    string1[0] = 'a';
    string1[1] = 'b';
    string1[2] = 'c';
    string1[2] = '\0'; // null terminator
    // Now string1 is only 3 bytes long instead of 1000
    
    // When using pointers, you need to allocation and free memory
    //string2[0] = 'a'; // will not work, it will crash
    
    string2 = (char*) malloc (5000); // be sure to allocate memory first
    string2[0] = 'a'; // will work, memory has been allocated
    string2[1] = 'b';
    string2[2] = 'c';
    string2[2] = '\0'; // now 3 bytes, but 4997 bytes of blank memory still hanging out there.
    
    free(string2); // all memory deleted
    
    // Using a better version of malloc, new
    string3 = new char[5000];
    strcpy(string3, "abc"); // still 3 bytes but still 4997 still hanging out there.
    
    string3 = (char*)realloc(string3, strlen(string3)); // ah, now only three bytes
    	if( string3 == NULL )
    		return 0; // error reallocating memory
    // Used strlen() to get totaly amount of bytes in string, in this case 3
    
    delete [] string3; // deleting memory allocated using new
    Example 1.1: How to use char's

    Simply stating, char array's don't need to be re-allocated. It's all local memory, once the program is destroyed, the memory goes with it. Unlike char pointers, if you allocate memory and close the program all the memory is still there, causing memory leaks.

    Also, strcpy() is just like setting each array spot to equal a char. Using the string library can be very helpful. Be sure to #include <stdio.h> and to learn more visit the C++ reference page.


    Hope this helps,
    - Stack Overflow
    Last edited by Stack Overflow; 04-02-2004 at 06:12 PM.
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  4. #4
    Registered User The Dog's Avatar
    Join Date
    May 2002
    Location
    Cape Town
    Posts
    788
    Firstly, when using C you should drop the *alloc() casts. Secondly, you cannot use new in C. And besides, *alloc() functions shouldn't be mixed with new just as free() shouldn't be mixed with delete.

  5. #5
    Hmm TheDog,

    I was actually displaying the three ways to handle characters, mind you.

    Besides, no one took the initiative to tell CookieMonster you don't use alloc() when dealing with char[]. So I went to the next level, malloc(). Then again I know alot of people whine about it so I decided to move to new and delete. Oh, and I also made three different strings. string1[], *string2, and *string3 differentiating the analogies.

    Last thing, I did not mix malloc with new, and free with delete. Most programmers would see and read my comments saying delete [] just deleted the memory used with new, not with malloc().

    Also, when using C why drop the *alloc() casts? You can't use new or delete, that's only compatible with C++. Are there any other string allocation techniques you know and would like to share, or are you just stating your opinion without facts to back it up?


    Edit: You could do it this way, but its only static and will delete immediately non constant like malloc() or new:

    Code:
    static char allocation[128];
    char *string;
    
    string = &allocation[0];
    
    strcpy(string, "what you want");
    Other than that, most of the allocation techniques get dumber and dumber. Including more bashing...


    Suit yourself,
    - Stack Overflow
    Last edited by Stack Overflow; 04-02-2004 at 06:29 PM. Reason: ...
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  6. #6
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Code:
    char *string; 
    string=(char*)calloc(totalcharacters(location),1);
    CookieMonster, assuming totalcharacters() returns the correct value, there is nothing wrong with this code(but the cast is not needed).

    >> However this does not allow the array “string” to be what I want. <<

    You'll have to expand on what the problem is.

    StackOverflow, "The Dog" was pointing out that you can not realloc() memory that has been allocated with new().
    Your post was generally helpful and complete but it may also be a good idea, when posting on the C board, to point out C++ only features(or not use them) to avoid confusing people.

    Anyway, two new members in the one thread! Welcome to the boards!
    Last edited by anonytmouse; 04-02-2004 at 06:29 PM.

  7. #7
    Registered User The Dog's Avatar
    Join Date
    May 2002
    Location
    Cape Town
    Posts
    788
    The fact that you initialised string3 with new, and then used realloc() on that pointer is what I was referring to. It's just plain wrong.

    And about casting malloc, read this.

  8. #8
    Hey anonytmouse,

    Yeah thanks for pointing that out. I wasn't sure how if there was a way to re allocate memory with C++, because the whole 4997 bytes would be annoying to tow around in the program. Only use realloc() when using other alloc() casts, otherwise try to only alloc what you might need in C++.


    - Stack Overflow
    Segmentation Fault: I am an error in which a running program attempts to access memory not allocated to it and core dumps with a segmentation violation error. This is often caused by improper usage of pointers, attempts to access a non-existent or read-only physical memory address, re-use of memory if freed within the same scope, de-referencing a null pointer, or (in C) inadvertently using a non-pointer variable as a pointer.

  9. #9
    Registered User
    Join Date
    Apr 2004
    Posts
    27
    Thank you for your replies.

    I’ve tried everything given to me so far, but I think I should supply more code with what my aim is because I have not got anywhere.

    The function I’m trying to do is a word counter for a text file. The reason I want a dynamic array size for the array “string” is because when then size of array “string” is less than the total number of characters, the number of words returned by the function is more than it should be (as you shall see further down). So I would like to make sure that the array “string” has the correct size to cater for all the characters in the text file.

    Please try to have a glance at my funciton. I have tried my best to explain what is going on so it will be quick to digest, btw I’m a newbie to c programming in all honesty so my methods might be very repetitive.

    PHP Code:
    int countwords (char *location)
    {
        
    /*The aim of this function is as titled, to count the number of words from a text file*/
        
    int countwords=0,count=0;    
        
    char *currentword;

        
    char string[5000];
        
    FILE *text,*text2;
        
    text=fopen(location,"r");//location has been given outside this function to where the text file exists.
        
    text2=fopen(".\\textfiles\\temp.txt","w");//using a file because I cnanot find a way of strtok can to delimit a newlines

        
    while((fgets (stringsizeof(string), text)) != NULL)//getting strings from the text file.
        
    {
            for(
    count=0;(string[count]!=NULL);count++) //going through the characters of teh selected string here
            
    {
                if ((
    string[count]==10)||((string[count]>=58)&&(string[count]<=63))) fprintf(text2," "); //changing the new lines and other characters to spaces.
                    
    else
                    
    fputc(string[count],text2);//the original text file is now one long text string to the FILE pointer *text2
            
    }
        }
        
    fclose (text);
        
    fclose(text2);

        
    text2=fopen(".\\textfiles\\temp.txt","r"); //the long text string is now read
        
    while((fgets (stringsizeof(string), text2)) != NULL)//getting strings from text file
        
    {
            
    currentword strtok(string," \t\r\n"); //delimiting the strings so that words can be counted
            
    while(currentword!=NULL)
            {
                
    countwords++;//number of words being counted
                
    currentword strtok(NULL," \t\r\n"); //null being put in place to follow by the last call strtok found a delimiter
            
    }
        }
        
    fclose(text2);
        return 
    countwords;

    And here is my function that counts the total characters that I mentioned earlier:

    PHP Code:
    int totalcharacters (char *location)
    {
        
    FILE text;
        
    int n 0;
        
    char c;
        
    text=fopen (location,"r");
        do
        {
            
    c=fgetc(text);
            
    n++;
        } while (
    c!=EOF);
        return 
    n;



  10. #10
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    I suspect your problem is the use of sizeof. Using sizeof on an array produces different results to using sizeof on a char pointer.
    Code:
    char string2[100];
    char * string = calloc(100, 1);;
    
    printf("sizeof(string)  = %d", sizeof(string));  /* prints sizeof(char *), probably 4 */
    printf("sizeof(string2) = %d", sizeof(string2)); /* prints 100 */
    Therefore when dynamically allocating your memory you need to keep the size of the buffer in a variable and use that instead of sizeof.

    Code:
    int countwords (char *location) 
    { 
        /*The aim of this function is as titled, to count the number of words from a text file*/ 
        int countwords=0,count=0;     
        char *currentword; 
    
        char * string;
        size_t string_size;
        FILE *text,*text2; 
    
        text=fopen(location,"r");//location has been given outside this function to where the text file exists. 
        text2=fopen(".\\textfiles\\temp.txt","w");//using a file because I cnanot find a way of strtok can to delimit a newlines 
    
        string_size = totalcharacters(location);
        string = calloc(string_size, sizeof(char)); 
    
        while((fgets (string, string_size, text)) != NULL)//getting strings from the text file. 
        { 
            for(count=0;(string[count]!=NULL);count++) //going through the characters of teh selected string here 
            { 
                if ((string[count]==10)||((string[count]>=58)&&(string[count]<=63))) fprintf(text2," "); //changing the new lines and other characters to spaces. 
                    else 
                    fputc(string[count],text2);//the original text file is now one long text string to the FILE pointer *text2 
            } 
        } 
        fclose (text); 
        fclose(text2); 
    
        text2=fopen(".\\textfiles\\temp.txt","r"); //the long text string is now read 
        while((fgets (string, string_size, text2)) != NULL)//getting strings from text file 
        { 
            currentword = strtok(string," \t\r\n"); //delimiting the strings so that words can be counted 
            while(currentword!=NULL) 
            { 
                countwords++;//number of words being counted 
                currentword = strtok(NULL," \t\r\n"); //null being put in place to follow by the last call strtok found a delimiter 
            } 
        } 
        fclose(text2); 
        return countwords; 
    }
    As a side note, you need to check the return value from calloc() as well as from fopen().

    P.S Please post your code in [code] tags rather than [PHP] tags.

  11. #11
    Registered User
    Join Date
    Apr 2004
    Posts
    27
    Hi anonytmouse,

    When using your code I got this error message (which I've got many times when trying to use calloc )

    Code:
    C:\Documents and Settings\TextStyleMeasurer.cpp(130) : error C2440: '=' : cannot convert from 'void *' to 'char *'
            Conversion from 'void*' to pointer to non-'void' requires an explicit cast
    Line 130 is

    Code:
    string = calloc(string_size, sizeof(char));
    Why does it not work? it seems fine to me.

  12. #12
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Because the file you are compiling has the extension ".cpp", the compiler is compiling it as C++. If you want to compile your code as C give the file the extension ".c".

    One of the differences between C and C++ is that malloc/calloc/realloc requires a cast in C++. As mentioned, this is generally avoided in C.

    Code:
    string = calloc(string_size, sizeof(char)); /* C */
    
    string = (char *) calloc(string_size, sizeof(char)); /* C++ */
    There are other differences between C and C++, so it is recommended that you compile your C code as C.

  13. #13
    Registered User
    Join Date
    Apr 2004
    Posts
    27
    YYYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYYYYYY!

    It worked. So it was that casting difference and size_t thing that I didn't know about which was stopping me from getting my array at runtime. I'm shall be looking this "size_t" thing up now, just so I understand what it is.

    Thank you not only for showing me how to get the array size at runtime, but for also alerting me that I have been compiling in c++ all along.

    I always thought I have been (due to the icon of the .cpp extension!). I'm going to have a few words with my lecturer when easter holiday is over, he's always said I will see no difference, BUT THERE ARE!

    BTW, this place rocks out of all the other c forums I've been to.

  14. #14
    Registered User
    Join Date
    Dec 2003
    Posts
    53
    umm... with regards to your mention of what size_t is, it's actually a unsigned long int or unsigned int, depending on your compiler IIRC...

    Also, a bit of clarification regarding the .c and .cpp thing... It's a minor nitpick an dI probrably won't mention it at all if it wasn't for the lack of sleep, but actually .c and .cpp files are actually just .txt files with another extension...

    so actually, the differences lies in your compiler... if your complier automatically decides to compile all .cpp files as C++, and all .c files as C, it's actually because the guy who wrote the program wanted to make things easier for you...

  15. #15
    Registered User
    Join Date
    Apr 2004
    Posts
    27
    Thanks for that tzuchan. Interesting nitpick there.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. c++ a very simple program
    By amjad in forum C++ Programming
    Replies: 1
    Last Post: 05-27-2009, 12:59 PM
  2. size of array
    By goran00 in forum C Programming
    Replies: 38
    Last Post: 04-02-2008, 09:57 AM
  3. Replies: 16
    Last Post: 11-23-2007, 01:48 PM
  4. How do you use variable to initialize array size?
    By yougene in forum C Programming
    Replies: 11
    Last Post: 09-04-2007, 02:50 PM
  5. Hi, could someone help me with arrays?
    By goodn in forum C Programming
    Replies: 20
    Last Post: 10-18-2001, 09:48 AM