Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c > #109866 > unrolled thread

What am I doing wrong here?

Started byDFS <nospam@dfs.com>
First post2017-05-13 00:39 -0400
Last post2017-05-15 20:18 -0400
Articles 18 — 9 participants

Back to article view | Back to comp.lang.c


Contents

  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

#109866 — What am I doing wrong here?

FromDFS <nospam@dfs.com>
Date2017-05-13 00:39 -0400
SubjectWhat 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]


#109868

FromDFS <nospam@dfs.com>
Date2017-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]


#109871

Fromjt@toerring.de (Jens Thoms Toerring)
Date2017-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]


#109876

FromDFS <nospam@dfs.com>
Date2017-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]


#109877

Frombartc <bc@freeuk.com>
Date2017-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]


#109878

FromGareth Owen <gwowen@gmail.com>
Date2017-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]


#109884

FromDFS <nospam@dfs.com>
Date2017-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]


#109888

FromManfred <noname@invalid.add>
Date2017-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]


#109899

FromDFS <nospam@dfs.com>
Date2017-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]


#109900

Frombartc <bc@freeuk.com>
Date2017-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]


#109889

Frombartc <bc@freeuk.com>
Date2017-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]


#109882

FromBarry Schwarz <schwarzb@dqel.com>
Date2017-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]


#109887

FromDFS <nospam@dfs.com>
Date2017-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]


#109901

FromBen Bacarisse <ben.usenet@bsb.me.uk>
Date2017-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]


#109908

FromKeith Thompson <kst-u@mib.org>
Date2017-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]


#109921

Fromjt@toerring.de (Jens Thoms Toerring)
Date2017-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]


#109978

FromTim Rentsch <txr@alumni.caltech.edu>
Date2017-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]


#110111

FromDFS <nospam@dfs.com>
Date2017-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