1

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.

2
  • try printf("%d\n", &randomWord[count]); with %s instead of %d, but make sure you zero-terminate the strings before. Commented Nov 1, 2017 at 21:54
  • What do you think &randomWord[count] is? Commented Nov 1, 2017 at 22:11

4 Answers 4

2

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.

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

3 Comments

You may want to comment additionally on just how wrong &randomWord[count] is and what that actually does.
@David C. Rankin: Done. Hope it helps OP.
Good job. That was just wonky as heck and indicated a clear misunderstanding of what was going on. I'm sure it will help. Letting that misconception go would just be down right dangerous.... (not the mention the Undefined Behavior invoked by printing the pointer address with %d)...
0

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;
}

Comments

0

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)

Comments

0

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.

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.