blazek
blazek

Reputation: 15

How to create an array of 100 random strings in C

I'm trying to create an array of 100 strings of random sizes between 3 and 10 letters long in C but I'm having a bit of trouble. This is what I have so far...

int main() {
    int count, number;
    char *randomWord[100]; // 1-d array of pointers to char
    char randomLetter;
    int wordLength;

    // generate 100 strings or random sizes between 3 and 10 letters
    for (count = 0; count < 100; count++) {
        wordLength = ((rand() % 10) + 3);  // get random size of word
        randomWord[count] = malloc(wordLength + 1); // allocated space for word
        for (number = 1; number < wordLength; number++) {
            randomLetter = 'A' + (rand() % 26);
            //randomWord[count] =
            printf("%d\n", randomLetter);
        }

        printf("%d\n", &randomWord[count]);
    }
}

The output I get looks like this...

72
90
82
73
87
75
66
65
6356712
88
66
71
70
67
66
67
69
89
72
74
6356716
71
73
88
87
6356720

Any help or direction would be appreciated.

Upvotes: 1

Views: 2089

Answers (4)

chqrlie
chqrlie

Reputation: 144540

There are multiple problems:

  • You do not store the characters into the allocated arrays.
  • You compute one random letter too few, starting the loop at 0 would fix this.
  • You do not print the words, but merely their addresses.

Here is how to fix the code:

#include <stdio.h>
#include <stdlib.h>

int main(void) {
    int count, number;
    char *randomWord[100]; // 1-d array of pointers to char

    // generate 100 strings or random sizes between 3 and 10 letters
    for (count = 0; count < 100; count++) {
        int wordLength = 3 + rand() % 8;  // get random word size in 3..10
        randomWord[count] = malloc(wordLength + 1); // allocated space for word
        for (number = 0; number < wordLength; number++) {
            randomWord[count][number] = 'A' + rand() % 26;
        }
        randomWord[count][number] = '\0';
        printf("%s\n", randomWord[count]);
    }
    return 0;
}

Upvotes: 0

David C. Rankin
David C. Rankin

Reputation: 84521

I won't plow the same ground plowed by the other answers. You now understand that:

printf("%d\n", &randomWord[count]);

was attempting to print the address of the pointer randomWord[count] and not at all the character you were attempting to print the ASCII value of. Remember & is the address of unary operator while * is the dereference operator. (which was invoking Undefined Behavior by attempting to print a pointer address with the %d format specifier. Use %p to print addresses)

Rather than invent each character from a modulo operation, it may be easier to simply pick a random index from a literal A-Za-z0-9 (or whatever character set you wish to include). It is really "six to one" a "half-dozen to another", but it may be conceptually easier to keep track of what you are doing.

Before looking at an alternative, let's address using magic numbers in your code. (don't do it). If you need constants for use in your code, then #define them or use a global enum to do the same. For example, if you need constants for the minimum length of string to generate (say MINL) and max length MAXL or the maximum number of strings MAXS (and the number of characters to choose from NCHR), you can simply define constants with:

enum { MINL = 3, MAXL = 10, NCHR = 62, MAXS = 100 };

That way you have a single convenient location at the top of your code to adjust values as required -- without having to pick through your variable and loop declarations to do it.

Now the alternative. You can simply declare a string literal alpha with the characters you wish to create 100 random strings from. Then all that is required is to get a random length for each, allocate length + 1 bytes of storage, and create length random numbers between 0 and NCHR - 1 assigning the character to the indexes in your string and nul-terminating at the end.

(note: by using calloc, you have already filled the final byte in each string with zero, effectively providing for nul-termination, but it is good practice to affirmatively nul-terminate each string)

Putting that altogether, you could do something like the following:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>

enum { MINL = 3, MAXL = 10, NCHR = 62, MAXS = 100 };

int main (void) {

    char *alpha = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"  /* NCHR long literal */
                  "abcdefghijklmnopqrstuvwxyz"  /* of chars to shuffle */
                  "0123456789",
        *a[MAXS] = { NULL };        /* array of pointers to char  */
    int modlen = MAXL - MINL + 1;   /* mod length for 3 - 10 char */

    srand (time (NULL));            /* seed random number generator */

    for (int i = 0; i < MAXS; i++) {    /* loop to create MAXS strings */
        int len = rand() % modlen + MINL;       /* get length 3 - 10 */
        if (!(a[i] = calloc (len + 1, 1))) {    /* allocate memory */
            fprintf (stderr, "error: memory exhausted 'a[%d]'.\n", i);
            return 1;
        }
        for (int j = 0; j < len; j++)       /* loop over len chars */
            a[i][j] = alpha[rand() % NCHR]; /* assing char from alpha */
        a[i][len] = 0;              /* affirmatively nul-terminate */
    }

    for (int i = 0; i < MAXS; i++) {        /* output results */
        printf ("a[%2d] : %s\n", i, a[i]);
        free (a[i]);        /* don't forget to free your memory */
    }

    return 0;
}

Example Use/Output

$ ./bin/str_randshuffle
a[ 0] : KhwC0FhKv
a[ 1] : j4U4zwfHf
a[ 2] : vSd
a[ 3] : 4jWlzWJ725
a[ 4] : q9h
a[ 5] : sxYmHSZ1w
a[ 6] : WSPot
a[ 7] : hTD
a[ 8] : GXQ
a[ 9] : NJD3GksyYE
a[10] : dUvVGPrWe
....
a[92] : vHl5
a[93] : 5LZjkFYl
a[94] : Q4Y
a[95] : 67sWds
a[96] : YlQWDuFKV8
a[97] : PHJwrOLQ6b
a[98] : U0EPiarOi
a[99] : zyZ2gcB2aw

Look over all the answers. There are good points made. Then let us know if you have any further questions.

Upvotes: 0

Stephan Lechner
Stephan Lechner

Reputation: 35154

First, as you know for sure, you do not write into randomWord[count], such that you cannot print out the result later.

Second, you'd need to terminate each string with \0, and you should use printf("%s\n", randomWord[count]);, i.e. without the & and with %s. Not terminating a string and using it in printf("%s"... very likely yields undefined behaviour; When printing a string, use %s, not %d. And when using %s, printf requires a pointer to the first character of the string. As you defined char *randomWord[100], randomWord[count] stands for such a pointer to a character, whereas &randomWord[count] would stand for the address of the pointer, not of the string's first character.

wordLength = ((rand() % 10) + 3);  // get random size of word
randomWord[count] = malloc(wordLength + 1); // allocated space for word
for(number = 0; number < wordLength; number++)
{
    randomLetter = 'A' + (rand() % 26);
    randomWord[count][number] = randomLetter;
    // printf("%c", randomLetter);
}
randomWord[count][wordLength] = '\0';
printf("%s\n", randomWord[count]);

BTW: Note that (rand() % 10) + 3) gives random lengths between 3 and 12, not between 3 and 10.

Upvotes: 2

Karim Manaouil
Karim Manaouil

Reputation: 1249

You are actually using the wrong format specifier:

%d is used to output a signed decimal integer.
%c is used to output a character.

Your inner printf should become : printf("%c\n", randomLetter)

Upvotes: 0

Related Questions