Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #109866 > unrolled thread
| Started by | DFS <nospam@dfs.com> |
|---|---|
| First post | 2017-05-13 00:39 -0400 |
| Last post | 2017-05-15 20:18 -0400 |
| Articles | 18 — 9 participants |
Back to article view | Back to comp.lang.c
What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 00:39 -0400
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 01:03 -0400
Re: What am I doing wrong here? jt@toerring.de (Jens Thoms Toerring) - 2017-05-13 06:55 +0000
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 08:59 -0400
Re: What am I doing wrong here? bartc <bc@freeuk.com> - 2017-05-13 14:15 +0100
Re: What am I doing wrong here? Gareth Owen <gwowen@gmail.com> - 2017-05-13 14:19 +0100
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 11:06 -0400
Re: What am I doing wrong here? Manfred <noname@invalid.add> - 2017-05-13 17:38 +0200
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 13:38 -0400
Re: What am I doing wrong here? bartc <bc@freeuk.com> - 2017-05-13 19:03 +0100
Re: What am I doing wrong here? bartc <bc@freeuk.com> - 2017-05-13 16:43 +0100
Re: What am I doing wrong here? Barry Schwarz <schwarzb@dqel.com> - 2017-05-13 07:44 -0700
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-13 11:25 -0400
Re: What am I doing wrong here? Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-05-13 19:23 +0100
Re: What am I doing wrong here? Keith Thompson <kst-u@mib.org> - 2017-05-13 13:58 -0700
Re: What am I doing wrong here? jt@toerring.de (Jens Thoms Toerring) - 2017-05-13 23:43 +0000
Re: What am I doing wrong here? Tim Rentsch <txr@alumni.caltech.edu> - 2017-05-14 13:43 -0700
Re: What am I doing wrong here? DFS <nospam@dfs.com> - 2017-05-15 20:18 -0400
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 00:39 -0400 |
| Subject | What am I doing wrong here? |
| Message-ID | <of62cn$4ji$3@dont-email.me> |
Just trying to get some random chars and ints:
---------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
char *randName;
int randRate;
char *randJob;
char *names[] = {"A","B","C","D","E"};
int rates[] = {10,20,30,40,50};
char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
int namescount = sizeof(names) / sizeof(names[0]);
int ratescount = sizeof(rates) / sizeof(rates[0]);
int jobscount = sizeof(jobs) / sizeof(jobs [0]);
for(i=0;i<atoi(argv[1]);i++)
{
srand(time(NULL));
sprintf(randName ,"%s", names[rand()%namescount]);
srand(time(NULL));
sprintf(randRate ,"%d", rates[rand()%ratescount]);
srand(time(NULL));
sprintf(randJob ,"%s", jobs [rand()%jobscount]);
printf("%s, %d, %s\n",randName, randRate, randJob);
}
return 0;
}
---------------------------------------------------------
This line near the end:
sprintf(randRate ,"%d", rates[rand()%ratescount]);
throws "warning: assignment makes pointer from integer without a cast"
It compiles, but errors out on that line when I run it.
Thanks
[toc] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 01:03 -0400 |
| Message-ID | <of63r7$75q$1@dont-email.me> |
| In reply to | #109866 |
On 5/13/2017 12:39 AM, DFS wrote:
> for(i=0;i<atoi(argv[1]);i++)
> {
> srand(time(NULL));
> sprintf(randName ,"%s", names[rand()%namescount]);
> srand(time(NULL));
> sprintf(randRate ,"%d", rates[rand()%ratescount]);
> srand(time(NULL));
> sprintf(randJob ,"%s", jobs [rand()%jobscount]);
> printf("%s, %d, %s\n",randName, randRate, randJob);
> }
Edit: not causing the warning, but I found out the rand seed needs to
happen once, outside the for loop.
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2017-05-13 06:55 +0000 |
| Message-ID | <ennoubFn8ntU1@mid.uni-berlin.de> |
| In reply to | #109866 |
DFS <nospam@dfs.com> wrote:
> Just trying to get some random chars and ints:
> ---------------------------------------------------------
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <time.h>
> int main(int argc, char *argv[])
> {
> int i;
> char *randName;
> int randRate;
> char *randJob;
> char *names[] = {"A","B","C","D","E"};
> int rates[] = {10,20,30,40,50};
> char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
> int namescount = sizeof(names) / sizeof(names[0]);
> int ratescount = sizeof(rates) / sizeof(rates[0]);
> int jobscount = sizeof(jobs) / sizeof(jobs [0]);
> for(i=0;i<atoi(argv[1]);i++)
> {
> srand(time(NULL));
> sprintf(randName ,"%s", names[rand()%namescount]);
Already this line is broken like all the others where you
use sprintf(). sprintf() tries to put a string into the
memory pointed to by the first argument. For that to work
the first argument must be a (pointer to a) char array
large enough to hold the complete string sprintf() will
try to put into it. But what you pass it here is an un-
initilaozed pointer, thus pointing to some random place
in memory. If you're lucky that will crash your program
on the first attempt with a segmentation fault, but if you
are unlucky it will seem to work but will corrupt the
memory of your program with unpredictable consequences.
> srand(time(NULL));
> sprintf(randRate ,"%d", rates[rand()%ratescount]);
Now here you don't even pass the required pointer to a
char array but an int as the first argument. That's what
the compiler notices and complains about. This seems to
indicate that you should again think about what sprintf()
actually does, i.e. producing a string from the rest of
the arguments, and that it's your resonsibility to supply
it with the memory (via the first argument) it needs to
put that string into.
> srand(time(NULL));
> sprintf(randJob ,"%s", jobs [rand()%jobscount]);
> printf("%s, %d, %s\n",randName, randRate, randJob);
> }
There doesn't seen to be any good reason here for using
sprintf() at all. All you want to do seems to be to out-
put the results, so your whole loop can bxse shortened to
srand(time(NULL));
for (i = 0; i < atoi(argv[1]); i++)
printf("%s, %d, %s\n", names[rand() % namescount],
rates[rand() % ratescount],
jobs[rand() % jobscount]);
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 08:59 -0400 |
| Message-ID | <of6vp1$m8g$2@dont-email.me> |
| In reply to | #109871 |
On 5/13/2017 2:55 AM, Jens Thoms Toerring wrote:
> DFS <nospam@dfs.com> wrote:
>> Just trying to get some random chars and ints:
> There doesn't seen to be any good reason here for using
> sprintf() at all. All you want to do seems to be to out-
> put the results, so your whole loop can bxse shortened to
>
> srand(time(NULL));
> for (i = 0; i < atoi(argv[1]); i++)
> printf("%s, %d, %s\n", names[rand() % namescount],
> rates[rand() % ratescount],
> jobs[rand() % jobscount]);
>
> Regards, Jens
Thanks. That's perfect.
If I did want to use sprintf, just for string handling and getting the
data into variables, why doesn't the below work?
------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
char *randName[2];
int randRate[8];
char *randJob[11];
char *names[] = {"A","B","C","D","E"};
int rates[] = {10,20,30,40,50};
char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
int namescount = sizeof(names) / sizeof(names[0]);
int ratescount = sizeof(rates) / sizeof(rates[0]);
int jobscount = sizeof(jobs) / sizeof(jobs [0]);
srand(time(NULL));
for(i=0;i<atoi(argv[1]);i++)
{
sprintf(randName, "%s", names[rand() % namescount]);
sprintf(randRate, "%d", rates[rand() % ratescount]);
sprintf(randJob , "%s", jobs [rand() % jobscount]);
printf("%s, %d, %s\n",randName, randRate, randJob);
}
return 0;
}
------------------------------------------------------------
It compiles with 3 warnings:
26: warning: assignment from incompatible pointer type
27: warning: assignment from incompatible pointer type
28: warning: assignment from incompatible pointer type
The output for names and jobs seems right, but the int variable isn't.
$ getrandoms 10
A, 1310392, architect
B, 1310392, programmer
E, 1310392, DBA
B, 1310392, DBA
E, 1310392, contractor
D, 1310392, programmer
B, 1310392, DBA
B, 1310392, analyst
A, 1310392, analyst
E, 1310392, contractor
[toc] | [prev] | [next] | [standalone]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-05-13 14:15 +0100 |
| Message-ID | <RFDRA.43226$3u2.21524@fx31.am4> |
| In reply to | #109876 |
On 13/05/2017 13:59, DFS wrote:
> If I did want to use sprintf, just for string handling and getting the
> data into variables, why doesn't the below work?
>
> ------------------------------------------------------------
> #include <stdio.h>
> #include <stdlib.h>
> #include <string.h>
> #include <time.h>
>
> int main(int argc, char *argv[])
> {
>
> int i;
> char *randName[2];
> int randRate[8];
> char *randJob[11];
> sprintf(randName, "%s", names[rand() % namescount]);
> sprintf(randRate, "%d", rates[rand() % ratescount]);
> sprintf(randJob , "%s", jobs [rand() % jobscount]);
You're still not calling sprintf properly.
What's the significance of the 2, 8, and 11 in those arrays? sprintf
expects a character array, either char[] or an initialised char*, but
you're passing char*[] and int[]. Some pointer of sorts will be passed,
but the wrong one (hence the warnings), and probably not to what you expect.
Try:
char randName[100];
char randRate[100];
char randJob[100];
The 100 is just some way of ensuring a big enough destination buffer.
> printf("%s, %d, %s\n",randName, randRate, randJob);
And print using all %s.
randRate is now a char buffer, but in yours, you were printing randRate
(which was a int array which becomes an int* in an expression), as a number.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | Gareth Owen <gwowen@gmail.com> |
|---|---|
| Date | 2017-05-13 14:19 +0100 |
| Message-ID | <87o9uwnbcl.fsf@gmail.com> |
| In reply to | #109876 |
DFS <nospam@dfs.com> writes:
> int main(int argc, char *argv[])
> {
>
> int i;
> char *randName[2];
This is an array of 2 unitialised pointers, that never get initialised.
You want
char randname[2]; /* 2 bytes of storage for writing a letter and a NULL-byte */
> int randRate[8];
char randRate[3]; /* you're writing a string representation of an int,
so you need a string / array of chars to write it
to - 3 bytes for two digits and NULL-byte*/
> char *randJob[11];
char randJob[11]; /* 11 bytes of storage */
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 11:06 -0400 |
| Message-ID | <of7774$f78$2@dont-email.me> |
| In reply to | #109878 |
On 5/13/2017 9:19 AM, Gareth Owen wrote:
> DFS <nospam@dfs.com> writes:
>
>> int main(int argc, char *argv[])
>> {
>>
>> int i;
>> char *randName[2];
>
> This is an array of 2 unitialised pointers, that never get initialised.
> You want
>
> char randname[2]; /* 2 bytes of storage for writing a letter and a NULL-byte */
>
>> int randRate[8];
>
> char randRate[3]; /* you're writing a string representation of an int,
> so you need a string / array of chars to write it
> to - 3 bytes for two digits and NULL-byte*/
>> char *randJob[11];
>
> char randJob[11]; /* 11 bytes of storage */
Thanks Bart.
What I intended to do from the start was not just print, but to put
random char data into char variable(s), and random int data into int
variable(s). Then I could use the variables to build SQL strings or for
other uses.
This seems to work:
--------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
char randName[2];
int randRate=0;
char randJob[11];
char *names[] = {"A","B","C","D","E"};
int rates[] = {10,20,30,40,50};
char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
int namescount = sizeof(names) / sizeof(names[0]);
int ratescount = sizeof(rates) / sizeof(rates[0]);
int jobscount = sizeof(jobs) / sizeof(jobs [0]);
srand(time(NULL));
for(i=0;i<atoi(argv[1]);i++)
{
sprintf(randName, "%s", names[rand() % namescount]);
randRate = rates[rand() % ratescount];
sprintf(randJob , "%s", jobs [rand() % jobscount]);
printf("%s, %d, %s\n",randName, randRate, randJob);
}
return 0;
}
--------------------------------------------------------------------
$ tcc getrandoms.c -o getrandoms.exe
(clean compile)
$ getrandoms 10
A, 50, contractor
B, 20, architect
E, 10, programmer
C, 10, programmer
D, 10, architect
D, 50, DBA
A, 40, contractor
E, 40, DBA
B, 30, architect
B, 40, contractor
Do you see ways to improve it? How would you write it?
Thanks
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2017-05-13 17:38 +0200 |
| Message-ID | <of7999$g8p$1@gioia.aioe.org> |
| In reply to | #109884 |
On 05/13/2017 05:06 PM, DFS wrote:
> On 5/13/2017 9:19 AM, Gareth Owen wrote:
>> DFS <nospam@dfs.com> writes:
<snip>
>
> Thanks Bart.
>
> What I intended to do from the start was not just print, but to put
> random char data into char variable(s), and random int data into int
> variable(s). Then I could use the variables to build SQL strings or for
> other uses.
>
> This seems to work:
> --------------------------------------------------------------------
> #include <stdio.h>
> #include <time.h>
>
> int main(int argc, char *argv[])
> {
> int i;
> char randName[2];
> int randRate=0;
> char randJob[11];
The size of these buffers needs to be thoroughly considered:
randName: only if all names are guaranteed to be 1-letter names, and
stay that way, then a 2-char buffer is fine.
randJob: in this example all jobs are max 10-letters long, so an 11-char
buffer works fine, but they are variable length names already now, what
if max length may change in future revisions? bart suggested a 100-char
buffer.
>
> char *names[] = {"A","B","C","D","E"};
> int rates[] = {10,20,30,40,50};
> char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
>
> int namescount = sizeof(names) / sizeof(names[0]);
> int ratescount = sizeof(rates) / sizeof(rates[0]);
> int jobscount = sizeof(jobs) / sizeof(jobs [0]);
>
> srand(time(NULL));
> for(i=0;i<atoi(argv[1]);i++)
> {
> sprintf(randName, "%s", names[rand() % namescount]);
> randRate = rates[rand() % ratescount];
> sprintf(randJob , "%s", jobs [rand() % jobscount]);
>
> printf("%s, %d, %s\n",randName, randRate, randJob);
> }
>
> return 0;
> }
> --------------------------------------------------------------------
>
<snip>
>
>
> Do you see ways to improve it? How would you write it?
>
> Thanks
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 13:38 -0400 |
| Message-ID | <of7g2h$dj9$3@dont-email.me> |
| In reply to | #109888 |
On 5/13/2017 11:38 AM, Manfred wrote:
> On 05/13/2017 05:06 PM, DFS wrote:
>> On 5/13/2017 9:19 AM, Gareth Owen wrote:
>>> DFS <nospam@dfs.com> writes:
> <snip>
>>
>> Thanks Bart.
>>
>> What I intended to do from the start was not just print, but to put
>> random char data into char variable(s), and random int data into int
>> variable(s). Then I could use the variables to build SQL strings or
>> for other uses.
>>
>> This seems to work:
>> --------------------------------------------------------------------
>> #include <stdio.h>
>> #include <time.h>
>>
>> int main(int argc, char *argv[])
>> {
>> int i;
>> char randName[2];
>> int randRate=0;
>> char randJob[11];
>
> The size of these buffers needs to be thoroughly considered:
> randName: only if all names are guaranteed to be 1-letter names, and
> stay that way, then a 2-char buffer is fine.
> randJob: in this example all jobs are max 10-letters long, so an 11-char
> buffer works fine, but they are variable length names already now, what
> if max length may change in future revisions? bart suggested a 100-char
> buffer.
Yeah, but for this example I'm OK.
How about this?
----------------------------------------------------------
char *names[] = {"AA","B","CCCCXCCCC","D","E"};
char randName[sizeof(names[0])+1];
or
char randName[sizeof(names[0])+2];
or
char randName[sizeof(names[0])+5];
----------------------------------------------------------
Then the buffers are automatically sized to the largest value in the
array (+1 or +2 or +5 whatever), and there's no 'waste' like there would
be if I used randName[100]?
Output looks OK.
$ getrandoms 10
D, 50, architect
AA, 20, architect
B, 20, DBA
E, 20, analyst
B, 40, programmer
D, 30, analyst
AA, 30, architect
D, 50, analyst
CCCCXCCCC, 20, analyst
D, 40, contractor
Is there anything wrong with that approach to sizing?
I noticed something:
----------------------------------------------------------
given: char *names[] = {"AA","B","CCCCXCCCC","D","E"};
option
1. char randName[sizeof(names[0])+2];
2. char randName[sizeof(names[0])+1];
3. char randName[sizeof(names[0])];
4. char randName[sizeof(names[0])-1];
5. char randName[sizeof(names[0])-2];
----------------------------------------------------------
All options compile cleanly.
Option 1 always run fine.
Option 2 always run fine.
Option 3 always runs but sometimes outputs gibberish in the 3rd var
(randJob)
Option 4 runs once or twice then crashes.
Option 5 crashes first run.
Are options 3,4,5 resulting in what's known as a buffer overflow?
Also:
given char *names[] = {"AA","B","CCCCXACCCC","D","E"};
Why does sizeof(names[0]) return 8 instead of 9?
Thanks
[toc] | [prev] | [next] | [standalone]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-05-13 19:03 +0100 |
| Message-ID | <gTHRA.74828$wa2.60906@fx36.am4> |
| In reply to | #109899 |
On 13/05/2017 18:38, DFS wrote:
> How about this?
>
> ----------------------------------------------------------
> char *names[] = {"AA","B","CCCCXCCCC","D","E"};
> char randName[sizeof(names[0])+1];
> or
> char randName[sizeof(names[0])+2];
> or
> char randName[sizeof(names[0])+5];
> ----------------------------------------------------------
>
> Then the buffers are automatically sized to the largest value in the
> array (+1 or +2 or +5 whatever),
Automatically? How does that work?
You examples use the size of name[0], which is a pointer, so will be 4
or 8 bytes, then you seem to add an arbitrary number to that. It has
little to do with the size of the largest string in the table, except it
might just be big enough by chance.
and there's no 'waste' like there would
> be if I used randName[100]?
You can choose any number you like that you know will be comfortably
large enough. The space is local storage in a function, and will be
recovered once you're back outside the function. Note that your machine
will be probably have some multiple of 1000,000,000 bytes available.
However, I showed in my other post that you don't need to use sprintf at
all so you don't even need to allocate 2 bytes.
> I noticed something:
> ----------------------------------------------------------
> given: char *names[] = {"AA","B","CCCCXCCCC","D","E"};
>
> option
> 1. char randName[sizeof(names[0])+2];
> 2. char randName[sizeof(names[0])+1];
> 3. char randName[sizeof(names[0])];
> 4. char randName[sizeof(names[0])-1];
> 5. char randName[sizeof(names[0])-2];
> ----------------------------------------------------------
>
> All options compile cleanly.
>
> Option 1 always run fine.
> Option 2 always run fine.
> Option 3 always runs but sometimes outputs gibberish in the 3rd var
> (randJob)
> Option 4 runs once or twice then crashes.
> Option 5 crashes first run.
>
> Are options 3,4,5 resulting in what's known as a buffer overflow?
Probably, as you're effectively using random numbers for the size of the
buffer.
>
>
> Also:
> given char *names[] = {"AA","B","CCCCXACCCC","D","E"};
>
> Why does sizeof(names[0]) return 8 instead of 9?
8 is the number of bytes of a pointer on your machine, as name[0] has a
pointer type (char*).
But why would you expect 9? names[0] points to a string occupying 3
bytes. The longest string (pointed to by names[2]) requires 11 bytes I
think.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | bartc <bc@freeuk.com> |
|---|---|
| Date | 2017-05-13 16:43 +0100 |
| Message-ID | <5QFRA.23773$vv3.16891@fx15.am4> |
| In reply to | #109884 |
On 13/05/2017 16:06, DFS wrote:
> char randName[2];
> sprintf(randName, "%s", names[rand() % namescount]);
> printf("%s, %d, %s\n",randName, randRate, randJob);
> Do you see ways to improve it? How would you write it?
Well, the use of sprintf() doesn't really buy you anything here (other
than learning how to use it). Here, sprintf is effectively just copying
a string from one place to another. So you might as well just use the
original.
For example:
printf ("%s, %d, %s\n", names[rand()%namescount], randRate etc...
If the intention was to simplify the operands to printf, then you can do
it like this (set up a pointer to the original string):
char* randName = names[rand() % namescount];
...
printf("%s, %d, %s\n",randName, randRate, randJob);
With no sprintf.
--
bartc
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2017-05-13 07:44 -0700 |
| Message-ID | <ac6ehc1jasjlrbev11aq7d9jh1e4kav8q0@4ax.com> |
| In reply to | #109876 |
On Sat, 13 May 2017 08:59:40 -0400, DFS <nospam@dfs.com> wrote:
>On 5/13/2017 2:55 AM, Jens Thoms Toerring wrote:
>> DFS <nospam@dfs.com> wrote:
>>> Just trying to get some random chars and ints:
>
>> There doesn't seen to be any good reason here for using
>> sprintf() at all. All you want to do seems to be to out-
>> put the results, so your whole loop can bxse shortened to
>>
>> srand(time(NULL));
>> for (i = 0; i < atoi(argv[1]); i++)
>> printf("%s, %d, %s\n", names[rand() % namescount],
>> rates[rand() % ratescount],
>> jobs[rand() % jobscount]);
>>
>> Regards, Jens
>
>
>Thanks. That's perfect.
>
>If I did want to use sprintf, just for string handling and getting the
>data into variables, why doesn't the below work?
>
>------------------------------------------------------------
>#include <stdio.h>
>#include <stdlib.h>
>#include <string.h>
>#include <time.h>
>
>int main(int argc, char *argv[])
>{
>
> int i;
> char *randName[2];
> int randRate[8];
> char *randJob[11];
>
> char *names[] = {"A","B","C","D","E"};
> int rates[] = {10,20,30,40,50};
> char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
>
> int namescount = sizeof(names) / sizeof(names[0]);
> int ratescount = sizeof(rates) / sizeof(rates[0]);
> int jobscount = sizeof(jobs) / sizeof(jobs [0]);
>
> srand(time(NULL));
> for(i=0;i<atoi(argv[1]);i++)
> {
> sprintf(randName, "%s", names[rand() % namescount]);
> sprintf(randRate, "%d", rates[rand() % ratescount]);
> sprintf(randJob , "%s", jobs [rand() % jobscount]);
> printf("%s, %d, %s\n",randName, randRate, randJob);
> }
>
> return 0;
>}
>------------------------------------------------------------
>
>It compiles with 3 warnings:
>26: warning: assignment from incompatible pointer type
>27: warning: assignment from incompatible pointer type
>28: warning: assignment from incompatible pointer type
Others have explained why you get these diagnostics. Just because
your compiler calls them warnings does not mean they aren't serious.
>The output for names and jobs seems right, but the int variable isn't.
Why are you executing code that does not compile cleanly? You should
never do so unless you *thoroughly* understand what the diagnostics
are trying to tell you.
>$ getrandoms 10
>A, 1310392, architect
Welcome to the world of undefined behavior. The most pernicious form
of undefined behavior is to appear to work as you intended.
Your system has led you astray in 2/3 of you output. The remaining
1/3 that you recognize to be incorrect is a clue that your
understanding of the diagnostics is incomplete.
>B, 1310392, programmer
>E, 1310392, DBA
>B, 1310392, DBA
>E, 1310392, contractor
>D, 1310392, programmer
>B, 1310392, DBA
>B, 1310392, analyst
>A, 1310392, analyst
>E, 1310392, contractor
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-13 11:25 -0400 |
| Message-ID | <of789u$j0n$3@dont-email.me> |
| In reply to | #109882 |
On 5/13/2017 10:44 AM, Barry Schwarz wrote:
> On Sat, 13 May 2017 08:59:40 -0400, DFS <nospam@dfs.com> wrote:
>> It compiles with 3 warnings:
>> 26: warning: assignment from incompatible pointer type
>> 27: warning: assignment from incompatible pointer type
>> 28: warning: assignment from incompatible pointer type
>
> Others have explained why you get these diagnostics. Just because
> your compiler calls them warnings does not mean they aren't serious.
>> Why are you executing code that does not compile cleanly? You should
> never do so unless you *thoroughly* understand what the diagnostics
> are trying to tell you.
>
> Welcome to the world of undefined behavior. The most pernicious form
> of undefined behavior is to appear to work as you intended.
>
> Your system has led you astray in 2/3 of you output. The remaining
> 1/3 that you recognize to be incorrect is a clue that your
> understanding of the diagnostics is incomplete.
Thanks for the stern lesson, Professor.
Below is my 'final working version', which compiles cleanly and runs
just fine. See any issues?
--------------------------------------------------------------------
#include <stdio.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
char randName[2];
int randRate=0;
char randJob[11];
char *names[] = {"A","B","C","D","E"};
int rates[] = {10,20,30,40,50};
char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
int namescount = sizeof(names) / sizeof(names[0]);
int ratescount = sizeof(rates) / sizeof(rates[0]);
int jobscount = sizeof(jobs) / sizeof(jobs [0]);
srand(time(NULL));
for(i=0;i<atoi(argv[1]);i++)
{
sprintf(randName, "%s", names[rand() % namescount]);
randRate = rates[rand() % ratescount];
sprintf(randJob , "%s", jobs [rand() % jobscount]);
printf("%s, %d, %s\n",randName, randRate, randJob);
}
return 0;
}
--------------------------------------------------------------------
Thanks
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-05-13 19:23 +0100 |
| Message-ID | <87vap4ehtu.fsf@bsb.me.uk> |
| In reply to | #109887 |
DFS <nospam@dfs.com> writes:
> On 5/13/2017 10:44 AM, Barry Schwarz wrote:
>> On Sat, 13 May 2017 08:59:40 -0400, DFS <nospam@dfs.com> wrote:
>>> It compiles with 3 warnings:
>>> 26: warning: assignment from incompatible pointer type
>>> 27: warning: assignment from incompatible pointer type
>>> 28: warning: assignment from incompatible pointer type
>>
>> Others have explained why you get these diagnostics. Just because
>> your compiler calls them warnings does not mean they aren't serious.
>>> Why are you executing code that does not compile cleanly? You should
>> never do so unless you *thoroughly* understand what the diagnostics
>> are trying to tell you.
>>
>> Welcome to the world of undefined behavior. The most pernicious form
>> of undefined behavior is to appear to work as you intended.
>>
>> Your system has led you astray in 2/3 of you output. The remaining
>> 1/3 that you recognize to be incorrect is a clue that your
>> understanding of the diagnostics is incomplete.
>
>
> Thanks for the stern lesson, Professor.
>
> Below is my 'final working version', which compiles cleanly and runs
> just fine. See any issues?
I would prefer it not to compile clean since it has a small
compiler-delectable problem. You've forgotten to include stdlib so
rand, srand and atoi are all being called without a prototype and you
are relying on the (now very old) rule that an function undeclared
function f is assume to be declared int f(). That's not even allowed in
modern C (i.e. you must get a diagnostic if you compile as C99 or C11).
> --------------------------------------------------------------------
> #include <stdio.h>
> #include <time.h>
>
> int main(int argc, char *argv[])
> {
> int i;
> char randName[2];
> int randRate=0;
> char randJob[11];
>
> char *names[] = {"A","B","C","D","E"};
> int rates[] = {10,20,30,40,50};
> char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
>
> int namescount = sizeof(names) / sizeof(names[0]);
> int ratescount = sizeof(rates) / sizeof(rates[0]);
> int jobscount = sizeof(jobs) / sizeof(jobs [0]);
>
> srand(time(NULL));
> for(i=0;i<atoi(argv[1]);i++)
> {
> sprintf(randName, "%s", names[rand() % namescount]);
> randRate = rates[rand() % ratescount];
> sprintf(randJob , "%s", jobs [rand() % jobscount]);
>
> printf("%s, %d, %s\n",randName, randRate, randJob);
> }
>
> return 0;
> }
> --------------------------------------------------------------------
This has the look of working too hard, though maybe you plan some future
changes that make this work pay off. Is there anything wrong with just
printing the chosen values:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
char *names[] = {"A", "B", "C", "D", "E"};
int rates[] = {10, 20, 30, 40, 50};
char *jobs[] = {"programmer", "DBA", "analyst", "architect", "contractor"};
int namescount = sizeof(names) / sizeof(names[0]);
int ratescount = sizeof(rates) / sizeof(rates[0]);
int jobscount = sizeof(jobs) / sizeof(jobs [0]);
if (argc > 1) {
srand(time(NULL));
for(int i = 0; i < atoi(argv[1]); i++)
printf("%s, %d, %s\n",
names[rand() % namescount],
rates[rand() % ratescount],
jobs[rand() % jobscount]);
}
return 0;
}
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-05-13 13:58 -0700 |
| Message-ID | <lninl45v90.fsf@kst-u.example.com> |
| In reply to | #109871 |
jt@toerring.de (Jens Thoms Toerring) writes:
[...]
> There doesn't seen to be any good reason here for using
> sprintf() at all. All you want to do seems to be to out-
> put the results, so your whole loop can bxse shortened to
>
> srand(time(NULL));
> for (i = 0; i < atoi(argv[1]); i++)
> printf("%s, %d, %s\n", names[rand() % namescount],
> rates[rand() % ratescount],
> jobs[rand() % jobscount]);
Note that the order of evaluation of the three rand() calls is
unspecified, though it is guaranteed to be called three times.
In the particular case of rand(), that probably doesn't matter,
but it's something to keep in mind. (And it could be significant
if you call srand() with a fixed seed to get a consistent sequence
of pseudo-random numbers, though it won't be consistent across
implementations.)
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for JetHead Development, Inc.
"We must do something. This is something. Therefore, we must do this."
-- Antony Jay and Jonathan Lynn, "Yes Minister"
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2017-05-13 23:43 +0000 |
| Message-ID | <enpk14F68sdU1@mid.uni-berlin.de> |
| In reply to | #109908 |
Keith Thompson <kst-u@mib.org> wrote:
> jt@toerring.de (Jens Thoms Toerring) writes:
> [...]
> > There doesn't seen to be any good reason here for using
> > sprintf() at all. All you want to do seems to be to out-
> > put the results, so your whole loop can bxse shortened to
> >
> > srand(time(NULL));
> > for (i = 0; i < atoi(argv[1]); i++)
> > printf("%s, %d, %s\n", names[rand() % namescount],
> > rates[rand() % ratescount],
> > jobs[rand() % jobscount]);
> Note that the order of evaluation of the three rand() calls is
> unspecified, though it is guaranteed to be called three times.
> In the particular case of rand(), that probably doesn't matter,
> but it's something to keep in mind. (And it could be significant
> if you call srand() with a fixed seed to get a consistent sequence
> of pseudo-random numbers, though it won't be consistent across
> implementations.)
There are other issues as well, like using only the lower
bits of what rand() returns (that are known to usually be
less "random" than the upper ones). But I guess that's, at
least at the moment, not what the OP will care about a lot;-)
Best regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-05-14 13:43 -0700 |
| Message-ID | <kfn60h3qied.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #109921 |
jt@toerring.de (Jens Thoms Toerring) writes:
> Keith Thompson <kst-u@mib.org> wrote:
>> jt@toerring.de (Jens Thoms Toerring) writes:
>> [...]
>>> There doesn't seen to be any good reason here for using
>>> sprintf() at all. All you want to do seems to be to out-
>>> put the results, so your whole loop can bxse shortened to
>>>
>>> srand(time(NULL));
>>> for (i = 0; i < atoi(argv[1]); i++)
>>> printf("%s, %d, %s\n", names[rand() % namescount],
>>> rates[rand() % ratescount],
>>> jobs[rand() % jobscount]);
>>
>> Note that the order of evaluation of the three rand() calls is
>> unspecified, though it is guaranteed to be called three times.
>>
>> In the particular case of rand(), that probably doesn't matter,
>> but it's something to keep in mind. (And it could be significant
>> if you call srand() with a fixed seed to get a consistent sequence
>> of pseudo-random numbers, though it won't be consistent across
>> implementations.)
>
> There are other issues as well, like using only the lower
> bits of what rand() returns (that are known to usually be
> less "random" than the upper ones). [...]
The program given earlier does not in fact have that
property. A slightly different program could have it,
but the one actually given does not.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2017-05-15 20:18 -0400 |
| Message-ID | <ofdga6$s8b$3@dont-email.me> |
| In reply to | #109866 |
On 5/13/2017 12:39 AM, DFS wrote:
> Just trying to get some random chars and ints:
Thanks for your help guys.
That question about sprintf() was related to this program I wrote
yesterday, which does performance tests on the PostgreSQL dbms.
usage: progname baserows exponent
ex: bigdata 1000 10
It will add baserows of random data, then copy it exponent times
Ex: 1000 10 means you end up with 1000*(2^10) = 1024000 rows
------------------------------------------------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <C:\Program Files\PostgreSQL\9.6\include\libpq-fe.h>
#include <Windows.h>
// compile on Windows:
// copy libpq.dll to source directory
// tcc bigdata.c libpq.dll -o bigdata.exe
LARGE_INTEGER
frequency,startMaster,startDrop,startRows,startDistinct,start,end;
double elapsedtime(LARGE_INTEGER startingtimer)
{
QueryPerformanceCounter(&end);
return (end.QuadPart - startingtimer.QuadPart) /
(double)frequency.QuadPart;
}
int main(int argc, char *argv[])
{
QueryPerformanceFrequency(&frequency);
QueryPerformanceCounter(&startMaster);
//vars
int i=0,cnt1=0,cnt2=0;
PGresult *rs;
char cSQL[200];
int colcount = 4;
char *columns[] = {"HIREDATE","REG","SALARY","JOB"};
char *display[] = {"Hire Dates","Regs","Salaries","Jobs"};
//random data sources
char *regs[] = {"Al","Bill","Chris","Diana","Evan"};
int salary[] = {100,150,200,250,300};
char *jobs[] = {"programmer","DBA","analyst","architect","contractor"};
//char *regs[] = {"Al","Bill","Chris","Diana","Evan"};
//int salary[] = {100,150,200,250,300};
//char *jobs[] =
{"programmer","DBA","analyst","architect","contractor"};
//db connect, drop table, recreate table
QueryPerformanceCounter(&startDrop);
char *conninfo = "host='localhost' dbname='COLATEST' user='COLA'
password='evermore'";
PGconn *conn = PQconnectdb(conninfo);
PQexec(conn, "BEGIN TRANSACTION;");
PQexec(conn, "DROP TABLE IF EXISTS BIGDATA;");
PQexec(conn, "CREATE TABLE BIGDATA (ROWSID SERIAL PRIMARY KEY,
HIREDATE DATE NOT NULL, REG VARCHAR(15) NOT NULL,SALARY INTEGER NOT
NULL,JOB VARCHAR(20) NOT NULL);");
PQexec(conn, "COMMIT;");
printf("%.2fs to drop and recreate table\n",elapsedtime(startDrop));
//show counts of random source data
int regcount = sizeof(regs) / sizeof(regs[0]);
int salarycount = sizeof(salary) / sizeof(salary[0]);
int jobcount = sizeof(jobs) / sizeof(jobs[0]);
printf("Random Data: 365 Hire Dates, %d Regs, %d Salaries, %d
Jobs\n",regcount,salarycount,jobcount);
//inputs
int baserows = strtol(argv[1], NULL, 10);
int exponent = strtol(argv[2], NULL, 10);
QueryPerformanceCounter(&startRows);
//add base rows
QueryPerformanceCounter(&start);
struct tm sdt = {0,0,0,1,0,(2017-1900)}; // starting date of 1/1/2017
time_t sdts = mktime(&sdt); //convert start date/time to seconds
since epoch
PQexec(conn, "BEGIN TRANSACTION;");
srand(time(NULL));
for(i=0; i<baserows; i++)
{
time_t randSecs = sdts + (86400 * (rand() % 365));
char* randDate = asctime(gmtime(&randSecs));
char* randReg = regs [rand() % regcount];
int randSalary = salary[rand() % salarycount];
char* randJob = jobs [rand() % jobcount];
sprintf(cSQL,"INSERT INTO BIGDATA (HIREDATE,REG,SALARY,JOB)
VALUES('%s','%s',%d,'%s');",randDate,randReg,randSalary,randJob);
PQexec(conn, cSQL);
}
PQexec(conn, "COMMIT;");
rs = PQexec(conn, "SELECT COUNT(ROWSID) FROM BIGDATA;");
cnt1 = strtol(PQgetvalue(rs,0,0),NULL,10);
printf("added %d rows in %.2fs (total = %d rows)\n",cnt1,
elapsedtime(start),cnt1);
//copy all existing rows: row count doubles each loop
PQexec(conn, "BEGIN TRANSACTION;");
for(i=0; i < exponent; i++)
{
QueryPerformanceCounter(&start);
PQexec(conn, "INSERT INTO BIGDATA (HIREDATE,REG,SALARY,JOB) SELECT
HIREDATE,REG,SALARY,JOB FROM BIGDATA;");
rs = PQexec(conn, "SELECT COUNT(ROWSID) FROM BIGDATA;");
cnt2 = strtol(PQgetvalue(rs,0,0),NULL,10);
printf("%d. added %d rows in %.2fs (total = %d rows)\n",i+1,cnt2-cnt1,
elapsedtime(start),cnt2);
cnt1 = cnt2;
}
PQexec(conn, "COMMIT;");
printf("%.2fs to add all data\n",elapsedtime(startRows));
//create indexes
QueryPerformanceCounter(&start);
PQexec(conn,"CREATE INDEX IDXHIREDATE ON BIGDATA (HIREDATE);");
PQexec(conn,"CREATE INDEX IDXREG ON BIGDATA (REG) ;");
PQexec(conn,"CREATE INDEX IDXSALARY ON BIGDATA (SALARY) ;");
PQexec(conn,"CREATE INDEX IDXJOB ON BIGDATA (JOB) ;");
printf("%.2fs to create indexes\n",elapsedtime(start));
//count distinct values in each column
QueryPerformanceCounter(&start);
printf("Random data contains:");
for(i = 0; i < colcount; i++)
{
sprintf(cSQL,"SELECT COUNT(%s) FROM (SELECT DISTINCT %s FROM BIGDATA)
AS CNT;",columns[i],columns[i]);
rs = PQexec(conn,cSQL);
printf(" %s %s",PQgetvalue(rs,0,0),display[i]);
}
printf("\n%.2fs to count distinct\n",elapsedtime(start));
//get db size
rs = PQexec(conn, "SELECT
pg_size_pretty(pg_database_size(current_database())) AS dbsize");
printf("db size is %s\n",PQgetvalue(rs,0,0));
//close
PQclear(rs);
PQfinish(conn);
double elapsed = elapsedtime(startMaster);
printf("Finished: %.2fs total (%.2fm)",elapsed,elapsed/60);
return 0;
}
------------------------------------------------------------------------------
If you use a small exponent, sometimes the dbsize doesn't register - I
guess the OS hasn't caught up to the code/dbms.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web