char *RandStr(void)
{
int i;
char RandStr[5];
for(i = 0; i <= 5; i++)
{
RandStr[i] = rand() % 78;
}
return RandStr;
}
> 1) What is the big deal about * in front of RandStr ? - I guess it
> means pointer to function - but what are the benefits?
In "char *RandStr(void)", the "char *" means "pointer to
character". That is, the * binds to "char", not to RandStr().
> 2) If I call the RandStr in main or another function, would
> char str[6];
> str = RandStr
> work? Why not?
No. This function returns a pointer, but "str" is an array. You
can't assign a pointer to an array. You can't assign anything to
an array (although you may be able to assign to an array's
elements).
--
"Some programming practices beg for errors;
this one is like calling an 800 number
and having errors delivered to your door."
--Steve McConnell
Nope - it means that instead of returning a char, you're
returning a pointer to char. A very different beast.
> 2) If I call the RandStr in main or another function, would
> char str[6];
> str = RandStr
> work? Why not?
>
No, because you can't assign to arrays directly like that. There
was another thread about exactly this earlier today; see if you
can find it on groups.google.com or something.
> char *RandStr(void)
> {
> int i;
> char RandStr[5];
Here you use the same name for a char[5] as you do for the function.
this is legal and won't cause any trouble as long as you don't use
any recursion. But it's terrible style and will confuse people who
are reading the code.
> for(i = 0; i <= 5; i++)
> {
> RandStr[i] = rand() % 78;
This won't give you printable characters on any charset I've used.
(Well, /some/ will be printable. Maybe. Others will be print control
characters and beeps. Maybe.)
Consider using the RandStr() I gave you in the other thread.
> }
> return RandStr;
> }
Yikes! You can't do this because RandStr[] was allocated locally
in your function - so when you return, RandStr[] dies. And you
return a pointer to it, which if used, will result in Undefined
Behavior.
If you allocated RandStr with malloc() (including <stdlib.h>!)
or passed it into the function, it would keep on living after
the function returns, and you'd be safe.
But remember to free() anything you get with malloc(), or you'll
have a memory leak on your hands.
1) Are u saying if "return RandStr" is deleted, then RandStr[] will
not die?
2) Thanks for the malloc recommendation - should it be in the main()
or as a global/static variable or inside the char *RandStr(void) ?
Thanks
1. There are two objects here - RandStr[] and a pointer to
RandStr[]. When you write "return RandStr" your compiler
decays the array to the pointer. So the pointer that you
return keeps right on existing. What it points /at/,
however, dies when the function ends.
2. That's a design consideration. Basically, however you
malloc() it, somebody has to free() it. It depends on
your requirements how best to structure it.
I suggest he studies a decent C textbook first.
<snip>
> > The comp.lang.c FAQ is here:
> > http://c-faq.com/
>
> > I highly recommend you read through that.
>
> I suggest he studies a decent C textbook first.
Try this
http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)
There's another problem with the code above that hasn't been mentioned yet:
the for loop writes past the end of the array.
You probably want to replace ``<='' in the loop condition by ``<'' or ''!=''.
This has to be some sort of puzzle? ('How many things are wrong in this
picture...')
--
Bartc
...
> > I suggest he studies a decent C textbook first.
>
> Try this http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)
Try this <http://en.wikipedia.org/wiki/
The_C_Programming_Language_(book)>
<http://en.wikipedia.org/wiki/The_C_Programming_Language_(book)>
Just wondering if either of the above make the link clickable in
Firefox. It missed the closing paren off the original one.
James
No, none of them work. Tried both Firefox and IE. It seems both omit
the trailing paren....
James
Only British TV watchers will understand why I just heard a voice
saying "little cactus"...
No. "char *RandStr(void)" indicates that RandStr() returns a pointer
to char, not that RandStr is a pointer to a function.
In general:
T f() -- f is a function returning a value of type T
T *f() -- f is a function returning a value of type pointer
to T
T (*f)() -- f is a pointer to a function returning a value
of type T
T *(*f)() -- f is a pointer to a function returning a value of
type pointer to T
Similarly for arrays:
T a[N] -- a is an N-element array of type T
T *a[N] -- a is an N-element array of type pointer to T
T (*a)[N] -- a is a pointer to an N-element array of type T
T *(*a)[N] -- a is a pointer to an N-element array of type
pointer to T
> 2) If I call the RandStr in main or another function, would
> char str[6];
> str = RandStr
> work? Why not?
>
No. First of all, you cannot assign to an array object; the semantics
of the language forbid it. Secondly, since you left the "()" off of
the "RandStr" expression, the expression is evaluated as a pointer to
the RandStr function, rather than as a call to the RandStr function.
That would be a type mismatch, as illustrated in the table below:
Declaration Expression Expression Type Note
----------- ---------- --------------- ----
char str[6] str char [6] "decays" to char *,
but that's not
relevant
here.
str[i] char
char *RandStr() RandStr() char * function call
RandStr char *(*)() function name treated
as pointer to
function
If RandStr() returns a pointer to a sequence of characters, and you
want to copy that sequence to str, you need to use strcpy() or
strncpy(). If you can't guarantee that all strings returned from
RandStr() will be 5 characters or less, then you need to use
strncpy():
#include <string.h>
...
char str[6];
strncpy(str, RandStr(), sizeof str - 1); // copy at most 5
characters
str[5] = 0; // make sure the string is 0-terminated;
> char *RandStr(void)
> {
> int i;
> char RandStr[5];
> for(i = 0; i <= 5; i++)
> {
> RandStr[i] = rand() % 78;
> }
> return RandStr;
>
>
Several problems. First of all, it's best not to use the name of the
function as the name of a variable within the function; that way leads
to confusion. The bigger problem is returning RandStr; instead of
returning a copy of the contents of the array, the function returns
the address of the first element of the array. The problem with that
is that as soon as the function exits, the array is no longer valid;
the memory that it occupied is now available for something else to
use, and it may be overwritten before you can read it.
Finally, "rand() % 78" is not a good way to generate random
characters, especially if you want all of them to be printable.
Assuming ASCII, values 0 through 31 are control characters (including
line feeds, form feeds, tabs, bells, etc.). Printable characters
start with ' ' (ASCII 32) and run through '~' (ASCII 126). At the
very least, you'll want to replace that expression with something
like
dest[i] = ' ' + rand() % ('~' - ' ');
It's not a *good* solution, but it at least gives you something
printable.
It's a better idea to abstract that out into a separate
RandomCharacter() function; that way you can deal with different
character sets or different locales without it affecting the RandStr
function itself.
char RandomCharacter(void)
{
/**
* There are easily a thousand better ways to
* do this that a) aren't tied to a specific
* encoding and b) offer better performance wrt
* randomization, but I've already spent more
* time on this than I should, so we'll just
* adapt your method for ASCII.
*/
char result = ' ' + rand() % ('~' - ' ');
return result;
}
Actually, for situations like this where you need to write the result
of a function into an array, it's best to pass the target array (and
its length) as parameters to the function:
void RandStr(char *dest, size_t destSize)
{
size_t i;
for (i = 0; i < destSize - 1; i++)
{
dest[i] = RandomCharacter();
}
dest[i] = 0; // add 0 terminator
}
...
int main(void)
{
char target[6];
RandStr(target, sizeof target);
printf("target: \"%s\"\n", target);
}
>
> Declaration Expression Expression Type Note
> ----------- ---------- --------------- ----
> char str[6] str char [6] "decays" to char *,
> but that's not
> relevant
> here.
> str[i] char
>
> char *RandStr() RandStr() char * function call
> RandStr char *(*)() function name treated
> as pointer to
> function
>
Argh. Way to go, GG. Let me see if I can't clean that up a bit:
Declaration Expression Expr Type Note
----------- ---------- --------- ----
>On Feb 3, 8:34�pm, Andrew Poelstra <apoels...@localhost.localdomain>
>wrote:
>> On 2010-02-04, 2005 <FW3...@sbcglobal.net> wrote:
>>
>> > 1) What is the big deal about * in front of RandStr ? �- I guess it
>> > means pointer to function - but what are the benefits?
>>
>> Nope - it means that instead of returning a char, you're
>> returning a pointer to char. A very different beast.
>>
>> > 2) If I call the RandStr in main or another function, would
>> > char str[6];
>> > str = RandStr
Without the mandatory () empty argument list, this is not even a
function call.
Using the same name for a function and an array just makes the
conversation unnecessarily confusing.
The array is an automatic array local to the function. It comes into
being when the function is called and ceases to exist when the
function exits. Returning or not returning its address does not
affect its lifespan at all. The point being made was that once the
array dies, its address no longer has any meaning and attempting to
use it for any purpose invokes undefined behavior.
But if you delete the return statement, you have the equally obnoxious
mistake of not returning a value from a function defined to return
one. Any attempt to use the return value in the calling function when
the function didn't actually return one invokes undefined behavior.
>2) Thanks for the malloc recommendation - should it be in the main()
>or as a global/static variable or inside the char *RandStr(void) ?
Why did you interject a completely unrelated issue such as global
variables?
If you call malloc in main, you will need to pass the resulting
address to your function. If you call malloc in the function, you
will need to return the resulting address to the caller and let that
function free it when it is no longer needed.
--
Remove del for email
it is pointer to char.
it means that the fuction RandStr return one pointer to char
(if that pointer to char point to one array that has in his
memory reservation one
value 0: it is one string too)
> 2) If I call the RandStr in main or another function, would
> char str[6];
> str = RandStr
> work? Why not?
if str is a ponter to char "char *str;" this could be ok
> char *RandStr(void)
> {
> int i;
> char RandStr[5];
> for(i = 0; i <= 5; i++)
> {
> RandStr[i] = rand() % 78;
> }
> return RandStr;
> }
this is my first try
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define u8 unsigned char
#define u32 unsigned
#define P printf
#define R return
#define F for
u32 rrand(u32 v)
{u32 a;
if((int)v<=0) R 0;
a=rand(); a>>=2; R a%v;
}
static u8 consonanti[]="BBCCDDFFGGHJKLLMMNNPPQRRSSTTVWXYZ";
static u8 vocali[]="AAEEEIOU";
static u8 *p[2]={consonanti, vocali};
static u32 ps[2]={(sizeof consonanti)-1 , (sizeof vocali)-1};
int is_vocale(u8 c)
{u32 i;
F(i=0; i<ps[1]; ++i)
if(c==vocali[i]) R 1;
R 0;
}
u32 randString(u8* s, u32 len)
{u32 i, r;
// P("Sizeof lettere == %u\n", (u32) sizeof lettere);
F(i=0; i<len; ++i)
{if(i==0) goto cas;
else {if(is_vocale(s[i-1])) // not 2 vocali
{cons:;
s[i]=p[0][rrand(ps[0])];
}
else
{// 0 1 2:3 inna
if(i>2 && s[i-2]==s[i-1]) // vocale
{voc:;
s[i]=p[1][rrand(ps[1])];
} // ri ntr a
else if(i>3&&!is_vocale(s[i-1])&&!is_vocale(s[i-2])
&&!is_vocale(s[i-3]) ) goto voc;
else
{cas:; // casuale
r=rrand(2);
s[i]=p[r][rrand(ps[r])];
}
}
}
}
s[i]=0;
R i;
}
int main(void)
{u8 buffer[128];
srand(time(0));
randString(buffer, rrand( (sizeof buffer)-1 ));
P("RandomString=%s\n", buffer);
R 0;
}
how solve the problem (one existing word: find one word in a dictionary file);
one existing prhase:
find one book file and choose one rand phrase of that book
from point to point.