0

I need a working code for a function that will return a random string with a random length.

What I want to do would be better described by the following code.

char *getRandomString()
{
    char word[random-length];
    // ...instructions that will fill word with random characters.
    return word;
}
void main()
{
    char *string = getRandomString();
    printf("Random string is: %s\n", string);
}

For this, I am strictly forbidden to use any other include than stdio.h. Edit: This project will be adapted to be compiled for a PIC Microcontroller, hence I cannot use malloc() or such stuff. The reason why I use stdio.h here, is for me to be able to inspect the output using GCC.

Currently, this code gives this error.-
“warning: function returns address of local variable [enabled by default]”

Then, I thought this could work.-

char *getRandomString(char *string)
{
    char word[random-length];
    // ...instructions that will fill word with random characters.
    string = word;
    return string;
}
void main()
{
    char *string = getRandomString(string);
    printf("Random string is: %s\n", string);
}

But it only prints a bunch of nonsense characters.

16
  • 2
    You can't return a pointer to data on the stack if you wish for predictable results. Have the caller pass the memory target (e.g. char*, and size limit) or return something on the heap (allocated via malloc, caller must free). Commented Aug 25, 2011 at 17:42
  • stdio.h is not a library, it is a header. Are you saying including stdlib.h is not allowed, hence malloc is not an option? Commented Aug 25, 2011 at 17:43
  • 1
    Why are you strictly forbidden? If this is homework, please add the homework tag. What are your specific requirements? Commented Aug 25, 2011 at 17:47
  • 1
    void main() is wrong. Use int main(void). Complain to the author of whatever book told you to use void main(). Commented Aug 25, 2011 at 17:50
  • what do you mean by random-length is it random minus length ? or random_length, ie, a single variable. Commented Aug 25, 2011 at 17:56

5 Answers 5

4

There are three common ways to do this.

  1. Have the caller pass in a pointer to (the first element of) an array into which the data is to be stored, along with a length parameter. If the string to be returned is bigger than the passed-in length, it's an error; you need to decide how to deal with it. (You could truncate the result, or you could return a null pointer. Either way, the caller has to be able to deal with it.)

  2. Return a pointer to a newly allocated object, making it the caller's responsibility to call free when done. Probably return a null pointer if malloc() fails (this is always a possibility, and you should always check for it). Since malloc and free are declared in <stdlib.h> this doesn't meet your (artificial) requirements.

  3. Return a pointer to (the first element of) a static array. This avoids the error of returning a pointer to a locally allocated object, but it has its own drawbacks. It means that later calls will clobber the original result, and it imposes a fixed maximum size.

None if these is an ideal solution.

Sign up to request clarification or add additional context in comments.

4 Comments

@alvin: Not if you're not allowed to use <stdlib.h>.
A variant on #2 is to define a symmetric freeRandomString() function which takes care of clear-up. This may be overkill in this simple example, but is much, much cleaner when you're dealing with more complex data structures.
@Oli: Another approach I've used is to have static array of N results and a static index into the array. Increment the index on each call, setting it back to 0 when it reaches the end. This means the caller doesn't have to worry as much about each call clobbering the result of the previous one, but it can fail badly if you try to save more than N results.
I have used the Third Keith’s approach which worked perfectly. Thanks for your suggestion.
2

It points to nonsense characters because you are returning local address. char word[random-length]; is defined local to char *getRandomString(char *string)

Dynamically allocate the string with malloc, populate string, and return the returned address by malloc. This returned address is allocated from the heap and will be allocated until you do not manually free it (or the program does not terminate).

char *getRandomString(void)
{
    char *word;
    word = malloc (sizeof (random_length));
    // ...instructions that will fill word with random characters.
    return word;
}

After you have done with the allocated string, remember to free the string.

Or another thing can be done, if you cannot use malloc which is define the local string in the getRandomString as static which makes the statically declared array's lifetime as long as the program runs.

char *getRandomString(void)
{
    static char word[LENGTH];
    // ...instructions that will fill word with random characters.
    return word;
}

Or simply make the char word[128]; global.

5 Comments

I dont think he can use malloc.
then either declare the array as static, or make it global.
I cannot use malloc. If I declare the array as static in the function, compiler throws the error “error: storage size of ‘str’ isn’t constant”. And I am unable to reserve too much memory since I will be compiling for a PIC microcontroller with very very little memory available.
@Mario: There's three ways to designate storage in C: statically, locally (on the stack), and dynamically (malloc/calloc/realloc). You can't do it dynamically, and you can't return local storage, so you have to do it statically. That means you need to specify the maximum string size at compile time.
@David-Thornley thanks for your answer, it was the most clarifying one, I would have choosen your answer as the correct one if you added it as answer but thanks anyway.
0

As I understand, malloc is not an option.

Write a couple of functions to a) get a random integer (strings length), and b)a random char.

Then use those to build your random string.

For example:

//pseudocode
static char random_string[MAX_STRING_LEN];
char *getRandomString()
{
    unsigned int r = random_number();

    for (i=0;i<r;i++){
        random_string[i] = random_char();
    }

    random_string[r-1] = '\0';
}

Comments

0

If you are not allowed to use malloc you'll have to declare an array that can be the maximum possible size at file scope and fill it with random characters.

#define MAX_RANDOM_STRING_LENGTH  1024
char RandomStringArray[MAX_RANDOM_STRING_LENGTH];

char *getRandomString(size_t length)
{
  if( length > ( MAX_RANDOM_STRING_LENGTH - 1 ) ) {
    return NULL; //or handle this condition some other way

  } else {
    // fill 'length' bytes in RandomStringArray with random characters.
    RandomStringArray[length] = '\0';
    return &RandomStringArray[0];

  }
}

int main()
{
    char *string = getRandomString(100);
    printf("Random string is: %s\n", string);

    return 0;
}

2 Comments

It doesn't have to be declared at file scope. It can be declared inside the function with the static keyword. And return &RandomStringArray[0]; can be written as return RandomStringArray;.
@Keith Thompson Yes on both counts. About the latter, I prefer the syntax I've used over the one you've mentioned.
0

Both of your examples are returning pointers to local variables - that's generally a no-no. You won't be able to create memory for your caller to use without malloc(), which isn't defined in stdio.h, so I guess your only option is to make word static or global, unless you can declare it in main() and pass the pointer to your random string function to be filled in. How are you generating random numbers with only the functions in stdio.h?

1 Comment

Actually the numbers are generated by a different mechanism that does not matter at all here, the only important thing is that after that function, the array of a determined-at-runtime length will be filled with random data. I am using stdio only to inspect this in GCC, I will later adapt the solution to be compiled for a PIC Microcontroller.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.