Thread: String Handling in C

  1. #1
    Registered User
    Join Date
    Jan 2006
    Posts
    29

    String Handling in C

    Hi, here is a theory question, which makes my coding painful. I beleive that understanding the concept of "strings" in C is the hardest for people with previous coding experience in other languages.

    I am aware that C doesnt have a native string class like most other languages. And from long painful experimenting and reading which is more and more confusing, I understood that the 3 ways of declaring a string would be

    1. char string[] <- being a char array with non defined length
    2. char string[length] <-being a char array with defined length
    3. char *string <- being the pointer version

    Usually to simplify your life in all languages you create functions and here is where i am stuck.

    I need to create a function in C that takes no parametre and returns a "string", usually you would declare it the following way:

    Code:
    char * MyFunc(void)
    works great, this is what i need. However here is the deal. Inside there is a process that can return ANY length of string, and that value should be accessible from outside my function (obviously i am returning it), lets say for the sake of discussion i want to return the contents of a text file. it might simply be 1 character or 10,000 impossible to know. impossible to predict. Still good i can handle that. lets guess... what is the worst that can happen.

    Code:
    char string[50000];
    OR

    Code:
    char *string;

    But here is the issue, when i try to return the function it says i am returning the contents of a local variable...and obviously i get garbaged dumped dUH! so i google a bit more and discover i have to malloc...

    so here goes

    Code:
    char *string=malloc(50000);
    mind you this is a huge allocation, in general the value returned is something between 10-500 characters and my program calls that function say 500 times?

    outside the function lets just say i want to MessageBox(0,MyFunc(),"Test Output",0);

    How do i go without making a memory leak or wasting resources. I do not wish to have a parameter to return to, simply because
    1. length is unknown
    2. i want to use the value directly as a constant.

  2. #2
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    If the length was known at compile time, it would be possible to wrap the string in a struct something like;
    Code:
    typedef struct {char buffer[20];} MyString;
    and return that type.

    With a string length that is unknown at compile time, there are some choices, but none are perfect.

    1) Use a memory pool (aka a static pointer that is local to your function, and reallocated as required). For example;
    Code:
    char *FunctionThatReturnsString(int length)
    {
         static char *buffer = NULL;
         if (buffer != NULL)   /*  be pessimistic */
             free(buffer);
        buffer = malloc(length);
        /*  put something into buffer */
        return buffer;
    }
    One problem with that the strings returned may not have sufficient lifetime, and the function therefore cannot be called more than once between two sequence points. For example, the call;
    Code:
       SomeFunction(FunctionThatReturnsString(10), FunctionThatReturnsString(20));
    will yield undefined behaviour if SomeFunction() dereferences it's arguments, as one of the arguments will be a dangling reference. It also yields a memory leak on the last call.

    2) Use a buffer that exceeds any length needed by your program. Apart from the problem of picking a buffer length that is "enough", this also has problems with multiple calls between sequence points (the value copied to the buffer may not survive) and is also extravagant use of memory if the largest required buffer size is significant. But it does not cause a memory leak as such.

    3) Wrap the call to MessageBox in a suitable manner that cooperates with your MyFunc(). For example;
    Code:
    char *MyFunc()
    {
          char *buffer = malloc(1000);
           /* put something in buffer */
          return buffer;
    }
    
    void MyMessageBox()
    {
            char *temp = MyFunc();
            MessageBox(0, temp, "Test Output", 0);
            free(temp);
    }
    A problem with this is that it relies on the programmer (who may or may not be yourself) being disciplined enough to use MyMessageBox() rather than MessageBox(). Another problem is that it may be necessary to write a significant number of such functions.

    4) Program in C++, and use the standard string class from C++. Technically, this has a trade-off as effective programming techniques in C are not necessarily the most effective in C++ (and vice versa). It also has a political trade-off, as bigoted C programmers will accuse you of going to the "dark side" but bigoted C++ programmers will welcome you with open arms for coming from the "dark side".

  3. #3
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    If you want length to be dynamic - you can malloc it in the function with the exact length you need...
    Bu in any case you should store the function return value to free it after the use:
    Code:
    const char* temp;
    MessageBox(0,temp=MyFunc(),"Test Output",0); 
    free(temp);
    But think about case when malloc failed... So better way I see:
    Code:
    const char* temp = MyFunc();
    if(temp)
       MessageBox(0,temp,"Test Output",0); 
    free(temp);
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  4. #4
    Registered User
    Join Date
    Jan 2006
    Posts
    29
    in what case does malloc fail?

  5. #5
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    Quote Originally Posted by mas0
    in what case does malloc fail?
    Have you read a programmers reference?
    Return Value

    malloc returns a void pointer to the allocated space, or NULL if there is insufficient memory available. To return a pointer to a type other than void, use a type cast on the return value. The storage space pointed to by the return value is guaranteed to be suitably aligned for storage of any type of object. If size is 0, malloc allocates a zero-length item in the heap and returns a valid pointer to that item. Always check the return from malloc, even if the amount of memory requested is small.
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  6. #6
    Registered User
    Join Date
    Jan 2006
    Posts
    29
    so if i want to be totally safe and efficient i will have to make my code full of malloc() checks and a whole lot of free(). sounds tedious. what are my other options? if any.

    bearing in mind that the most important thing for me is size then efficiency. C++ is not an option i am a beginner and trying to learn C.

  7. #7
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    You can use statically allocated buffer big enough to store the string
    And pass it as a parameter to be filled by your function (together with buffer length to check the memory overruns)
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  8. #8
    The larch
    Join Date
    May 2006
    Posts
    3,573
    bearing in mind that the most important thing for me is size then efficiency. C++ is not an option i am a beginner and trying to learn C.
    C knowledge is not a pre-requirement if you want to learn C++. On the contrary, it could be a hindrance.

    C++ isn't necessarily harder to learn than C. As far as strings are concerned, I find it much easier: you don't have to worry about how you implement your char array, but can start using the string right away. The string class takes care of the low-level stuff automagically (memory allocations/deallocations), and you can concentrate on your actual goals instead.

  9. #9
    Algorithm Dissector iMalc's Avatar
    Join Date
    Dec 2005
    Location
    New Zealand
    Posts
    6,318
    Quote Originally Posted by mas0
    so if i want to be totally safe and efficient i will have to make my code full of malloc() checks and a whole lot of free(). sounds tedious. what are my other options? if any.
    Yes; Yes you would, and yes it is tedious and theoretically necessary. Your other options are to use C++.
    bearing in mind that the most important thing for me is size then efficiency. C++ is not an option i am a beginner and trying to learn C.
    Well so far you have learnt that C is no good for doing what you want to do. In C, it is impossible to fulfil all the requirements of what you want to do (no leak, no assigning to temporary first, no restriction when using sequence points etc). In C++ it is very easy!

    So, you either give in to one of your requirements (ideally: having to assign to a temporary first so that you can free it) or you use C++. Those are your options.

  10. #10
    Registered User
    Join Date
    Jan 2006
    Posts
    29
    C++ is not an option unfortunately. I am learning C and will stick to that for the time being. Most if not all of my coding will be api oriented, system calls etc and so far i have been doing a great deal of mixing up languages, starting C then adding C++ code... very confusing and very very bad. but thanx for the pointers, this forum is great

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. string & eof handling problems
    By spudval in forum C++ Programming
    Replies: 4
    Last Post: 07-11-2007, 11:46 AM
  2. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  3. Linked List Help
    By CJ7Mudrover in forum C Programming
    Replies: 9
    Last Post: 03-10-2004, 10:33 PM
  4. Classes inheretance problem...
    By NANO in forum C++ Programming
    Replies: 12
    Last Post: 12-09-2002, 03:23 PM
  5. creating class, and linking files
    By JCK in forum C++ Programming
    Replies: 12
    Last Post: 12-08-2002, 02:45 PM