# random words

Discussion in 'C Programming' started by Olaf \El Blanco\, May 2, 2006.

1. ### Olaf \El Blanco\Guest

How can i generate random words? ('a'..'z')

Is there any function that convert a number to it ascci char?

My english is horrible! Here an example:
function(65)
return 'a';

Thank you!

Olaf \El Blanco\, May 2, 2006

2. ### Richard HeathfieldGuest

Olaf "El Blanco" said:

> How can i generate random words? ('a'..'z')

If you just want random collections of letters, use srand to seed your
pseudorandom number generator (with the result of a call to time(NULL) if
you don't want successive runs to repeat the same results), once only.

Put your "alphabet" into an array (this allows you easy flexibility - for
example, you might want some letters to be more common than others), and
keep track of its length, e.g.:

char alphabet[] = "aaaaaaaaaaabbbccccddddddeeeeeeeeeeeee"
"fffggghhhhiiiiiijklllmmnnnnnnoooooooo"
"wxyz ";

size_t alphasize = strlen(alphabet);

A quick function to get a pseudorandom number:

int getrand(int low, int high)
{
return (high + 1 - low) * (rand() / (RAND_MAX + 1.0)) + low;
}

Do a random letter like this:

offset = getrand(0, alphasize - 1);
putc(alphabet[offset]);

in a loop, obviously. Including spaces in the "alphabet" makes word
separation a cinch, but you might want to be a bit cleverer than that to
avoid big gaps between some w ords. (A simple flag will do the
trick.)

If, on the other hand, you want to have a list of words from which you print
random extracts, then the principle is exactly the same except that,
instead of an array of char, you have an array of char *, like this:

char *dictionary[] =
{
"now", "is", "the", "time", "for", "all", "good", "men",
"to", "come", "aid", "of", "party"
};

size_t dictionarysize = sizeof dictionary / sizeof dictionary[0];

apart from which the principle is the same.

> Is there any function that convert a number to it ascci char?
>
> My english is horrible! Here an example:
> function(65)
> return 'a';

Well, firstly C doesn't understand about ASCII - it uses your local
character collating sequence (which, in your case, is indeed ASCII, but not
everybody uses the same kind of computer that you do).

Secondly, 'a' is actually ASCII 97, not ASCII 65 (which is 'A').

Thirdly, C supplies no such function, because it isn't necessary.

Observe:

#include <stdio.h>

int main(void)
{
printf("The character with code point %d, on your", 65);
printf(" current set-up (but not necessarily other");
printf(" people's!), is %c\n, 65);

return 0;
}

In other words, on your computer at any rate, 65 and 'A' are just two
different ways of writing the same value. (On a mainframe using EBCDIC
rather than ASCII, 'A' would have some other numerical value.)

If you can avoid relying on ASCII values, it's better to do so as it makes
your code more portable. (It's very rare to have any /real/ need to rely on
ASCII in typical C code.)

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006

3. ### arunGuest

Olaf "El Blanco" wrote:
> How can i generate random words? ('a'..'z')
>
> Is there any function that convert a number to it ascci char?
>

Is it mandatory that you should make a function call there to do it ?
You can simply assign the number to a character or do a cast when
required.
That will do it.

> My english is horrible! Here an example:

Is it an example for your original english ?
> function(65)
> return 'a';
> I cant understand why the function returns 'a' for 65.

I believe 65 is the ASCII value of 'A' and your fuction should return
that.

> Thank you!

arun, May 2, 2006
4. ### Richard HeathfieldGuest

arun said:

>
> Olaf "El Blanco" wrote:
>> How can i generate random words? ('a'..'z')
>>
>> Is there any function that convert a number to it ascci char?
>>

> Is it mandatory that you should make a function call there to do it ?
> You can simply assign the number to a character or do a cast when
> required.

Under which circumstances would a cast be required?

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006
5. ### Olaf \El Blanco\Guest

Richard Heathfield, Thank you! amazing explication!

> int getrand(int low, int high)
> {
> return (high + 1 - low) * (rand() / (RAND_MAX + 1.0)) + low;
> }

It works perfecty, but why RAND_MAX and why + 1.0?

Olaf \El Blanco\, May 2, 2006
6. ### Richard HeathfieldGuest

Olaf "El Blanco" said:

> Richard Heathfield, Thank you! amazing explication!
>
>> int getrand(int low, int high)
>> {
>> return (high + 1 - low) * (rand() / (RAND_MAX + 1.0)) + low;
>> }

>
> It works perfecty,

Naturellement.

> but why RAND_MAX and why + 1.0?

Let's look at it in detail, then.

RAND_MAX is the highest legal value rand() can return. So if we divide the
result of rand() by RAND_MAX plus one, we'll get a result in, say, the
range 0 to 0.999+ (or, if you prefer, >= 0 and < 1).

But to do RAND_MAX + 1 would result in an integer addition with an integer
result, and dividing rand()'s return value by this would give us a result
of 0, which would get a bit repetitive after a while. So we use 1.0
instead, which makes (RAND_MAX + 1.0) a double, and thus dividing it into
rand()'s result is done using floating point arithmetic rather than integer
arithmetic.

That whole ball of wax gives us, as I say, a value in the range [0.0, 1.0) -
we will call this value R. Note the apparently mismatched brackets [) which
indicate that it is a "half-open interval" - i.e. the range includes all
the numbers from the lower value up to, but *not* including, the higher
value.

What we want is a result in the range [low, high]. The number of items in
the range is high + 1 - low. For example, if we want a number in the range
7 to 10, the acceptable answers are 7, 8, 9, 10 - i.e. four results, i.e.
high (10) - low (7) is one short, so we add 1 to the result of the
subtraction.

Multiplying this by our "random" value R gives us a number in the range [0,
high - low + 1). Adding low to this gives us a value in the range [low,
high + 1), which is almost what we want. At this point, though, it's still
a double, but since the function returns int, a conversion is supplied for
us - this conversion forces the value into the range [low, high], which is
exactly right.

HTH. HAND.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006
7. ### Olaf \El Blanco\Guest

/*
This is an english translation of part of my code
In which I need to generate a lot of 1024 chars phrases
-MAX = 1024-
*/

char * phrase_generate(void)
{
char phrase[MAX];
int i, size_alphabet=strlen(alphabet);
for (i=0; i<=MAX; i++)
printf ("%c", phrase = alphabet[getrand(0, size_alphabet-1)]);
return frase; /* Address of local var??? */
}

void testing(void)
{
char *phrase;
phrase =(char*)malloc(sizeof(char)*MAX);
phrase = phrase_generate();
printf ("\n\n\n");
printf ("%s", phrase);
free(phrase);
}

Don't appear the same phrases, the second one is shorter... Why?

Olaf \El Blanco\, May 2, 2006
8. ### Richard HeathfieldGuest

Olaf "El Blanco" said:

>
>
> /*
> This is an english translation of part of my code
> In which I need to generate a lot of 1024 chars phrases
> -MAX = 1024-
> */
>
> char * phrase_generate(void)
> {
> char phrase[MAX];
> int i, size_alphabet=strlen(alphabet);
> for (i=0; i<=MAX; i++)

You only have MAX characters, one of which is needed for a null terminating
character (which you appear to have overlooked completely). The loop,
however, runs from 0 to MAX, inclusive, which comes to MAX + 1 characters.
That's two too many, once you remember the null terminator.

> printf ("%c", phrase = alphabet[getrand(0, size_alphabet-1)]);
> return frase; /* Address of local var??? */

(You meant phrase, not frase - you defined it as phrase, earlier in the
function.)

Yeah, don't do that - or, at least, the simplest fix is to make it static.
That'll work, although I happen to think it's a bug-ugly solution.

> }
>
> void testing(void)
> {
> char *phrase;
> phrase =(char*)malloc(sizeof(char)*MAX);

Lose the cast.

phrase = malloc(MAX * sizeof *phrase);

Don't forget malloc can fail, so:

if(phrase != NULL)
{

> phrase = phrase_generate();

Whoa, stop there. You just lost track of your malloc'd space. Instead, do
this:

strcpy(phrase, phrase_generate());

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006
9. ### Olaf \El Blanco\Guest

Finally...

I will call that function getrand() X times...
And I need differents phrases... You talked about that, but I didn't
understand... Something like pascal randomise() ?
Thanks again...

Olaf \El Blanco\, May 2, 2006
10. ### Robert LatestGuest

On 2006-05-02, Richard Heathfield <> wrote:

[ complete answer to homework question snipped ]

Since when are we doing this?

robert

Robert Latest, May 2, 2006
11. ### Richard HeathfieldGuest

Robert Latest said:

> On 2006-05-02, Richard Heathfield <> wrote:
>
> [ complete answer to homework question snipped ]
>
> Since when are we doing this?

Since when were a few hints and a few lines of code a "complete answer"? If
the guy wants to learn, he will learn from my article. If he doesn't want
to learn, he won't be able to provide his lecturer with a complete
solution, just from the material I provided.

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006
12. ### Richard HeathfieldGuest

Olaf "El Blanco" said:

> Finally...
>
> I will call that function getrand() X times...
> And I need differents phrases... You talked about that, but I didn't
> understand... Something like pascal randomise() ?

Use srand(), to which you supply an argument which controls the commencement
of a new stream of pseudo-random numbers to be supplied by rand(). You need
only call srand() once, at the beginning of your program. If you supply the
same seed each time you run the program, you will get the same stream of
numbers each time you run the program. So if you want each run to be
"fresh", you will need to find a source of entropy elsewhere. One
commonly-used source of entropy is the system clock.

Lawrence Kirby once posted the following code in comp.lang.c:

++ S T A R T +++ Lawrence Kirby, comp.lang.c, 4 Dec 1999 +++++++++

The only satisfactory solution I can think
of (and this has come up before) is to create a hash value based on the
bytes of whatever value is returned i.e.

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

void randomize(void)
{
time_t timeval = time(NULL);
unsigned char *ptr = (unsigned char *)&timeval;
unsigned seed = 0;
size_t i;

for (i = 0; i < sizeof timeval; i++)
seed = seed * (UCHAR_MAX+2U) + ptr;

srand(seed);

}

It contains a loop but efficiency isn't an issue since you shouldn't
be calling it more than about once per program execution.
+++ E N D ++ Lawrence Kirby, comp.lang.c, 4 Dec 1999 +++++++++++++

--
Richard Heathfield
"Usenet is a strange place" - dmr 29/7/1999
http://www.cpax.org.uk
email: rjh at above domain (but drop the www, obviously)

Richard Heathfield, May 2, 2006