Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #147683 > unrolled thread
| Started by | Barry Schwarz <schwarzb@delq.com> |
|---|---|
| First post | 2019-11-06 14:23 -0800 |
| Last post | 2019-11-07 11:57 +0000 |
| Articles | 10 — 8 participants |
Back to article view | Back to comp.lang.c
This discussion starts older than the indexed window; earlier articles aren't shown. The article labeled Started by
below is the oldest one visible, not the original post.
Re: What are the odds? (a continuation of One works ...) Barry Schwarz <schwarzb@delq.com> - 2019-11-06 14:23 -0800
Re: What are the odds? (a continuation of One works ...) Bart <bc@freeuk.com> - 2019-11-06 22:35 +0000
Re: What are the odds? (a continuation of One works ...) luser droog <luser.droog@gmail.com> - 2019-11-06 17:09 -0800
Re: What are the odds? (a continuation of One works ...) Keith Thompson <kst-u@mib.org> - 2019-11-06 19:19 -0800
Re: What are the odds? (a continuation of One works ...) Ian Collins <ian-news@hotmail.com> - 2019-11-07 16:30 +1300
Re: What are the odds? (a continuation of One works ...) Bart <bc@freeuk.com> - 2019-11-07 10:59 +0000
Re: What are the odds? (a continuation of One works ...) David Brown <david.brown@hesbynett.no> - 2019-11-07 14:27 +0100
Re: What are the odds? (a continuation of One works ...) DFS <nospam@dfs.com> - 2019-11-06 18:09 -0500
Re: What are the odds? (a continuation of One works ...) Keith Thompson <kst-u@mib.org> - 2019-11-06 19:26 -0800
Re: What are the odds? (a continuation of One works ...) Ben Bacarisse <ben.usenet@bsb.me.uk> - 2019-11-07 11:57 +0000
| From | Barry Schwarz <schwarzb@delq.com> |
|---|---|
| Date | 2019-11-06 14:23 -0800 |
| Subject | Re: What are the odds? (a continuation of One works ...) |
| Message-ID | <g4g6se5u1ggsmecioggck2k7ve59pfdbbp@4ax.com> |
On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote:
>On 11/6/2019 1:08 PM, Barry Schwarz wrote:
<snip>
>> One of the simplest things you can do that make programming
>> exponentially easier is use a consistent indenting scheme. This will
>> help you avoid nesting level errors.
>
>
>The indenting is fine in my editor, but a mix of tabs and spaces comes
>out bad when the code is pasted to Thunderbird.
When asking for help, it behooves one to make things as easy as
possible for the reader. Experienced people in this newsgroup have
recommended spaces instead of tabs so that the resulting display is
not dependent on how the reader's tabs are set.
>>> Maybe you can show me how to fix the //letter distribution part of the
>>> code. I can't get it to compile.
>>
>> The error message for the statement that calls strcmp should have been
>> crystal clear. What part of it did you not understand?
>
>
>I got it:
You got that part of it but then decided to break another part.
<snip>
>=========================================================================
>final code
>=========================================================================
>#include <stdlib.h>
>#include <stdio.h>
>#include <time.h>
>#include <math.h>
>#include <string.h>
>
>int randNbr(int low, int high) {
> return (low + rand() / (RAND_MAX / (high - low + 1) + 1));
>}
>
>int main(void) {
<snip>
> //letter distribution
> char charset[62] =
>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
> int charsetLen = strlen(charset);
After numerous examples in your comp.lang.c posts (where I have
redirected this response since we are not discussing the odds any
more) of calculating charsetLen correctly, you have chosen to use a
different method. You have tried to pass charset to strlen in
complete violation of the requirements that function imposes.
It is not sufficient to simply pass a pointer to char to strlen.
strlen requires that the pointer actually point to a string. In order
for an array of char to contain a string, the array must contain at
least one '\0' to properly terminate the string. charset does not. As
a result, this code exhibits undefined behavior.
When you tested the code, did you not notice extraneous lines of
output after the line for "9"?
> cnt=0;
> printf("n = 1000000\n");
> for(i=0;i<charsetLen;i++) {
> for(j=0;j<1000000;j++) {
> k = randNbr(0,charsetLen-1);
> if(charset[i] == charset[k]) {cnt++;}
> }
> printf("%c = %d\n",charset[i],cnt);
> cnt=0;
> }
>
>exit(0);
>}
>=========================================================================
--
Remove del for email
[toc] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-11-06 22:35 +0000 |
| Message-ID | <2VHwF.97943$_i.39059@fx25.am4> |
| In reply to | #147683 |
On 06/11/2019 22:23, Barry Schwarz wrote: > On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote: >> char charset[62] = >> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; > After numerous examples in your comp.lang.c posts (where I have > redirected this response since we are not discussing the odds any > more) of calculating charsetLen correctly, you have chosen to use a > different method. You have tried to pass charset to strlen in > complete violation of the requirements that function imposes. > > It is not sufficient to simply pass a pointer to char to strlen. > strlen requires that the pointer actually point to a string. In order > for an array of char to contain a string, the array must contain at > least one '\0' to properly terminate the string. charset does not. A simple fix is to get rid of the '62': char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; Then the trailing 0 that is part of every string constant is included (otherwise the 63 chars including \0 are truncated to 62).
[toc] | [prev] | [next] | [standalone]
| From | luser droog <luser.droog@gmail.com> |
|---|---|
| Date | 2019-11-06 17:09 -0800 |
| Message-ID | <33b3c4ce-2f41-4bb1-bbc1-76a768125681@googlegroups.com> |
| In reply to | #147684 |
On Wednesday, November 6, 2019 at 4:35:51 PM UTC-6, Bart wrote:
> On 06/11/2019 22:23, Barry Schwarz wrote:
> > On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote:
>
> >> char charset[62] =
> >> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>
> > After numerous examples in your comp.lang.c posts (where I have
> > redirected this response since we are not discussing the odds any
> > more) of calculating charsetLen correctly, you have chosen to use a
> > different method. You have tried to pass charset to strlen in
> > complete violation of the requirements that function imposes.
> >
> > It is not sufficient to simply pass a pointer to char to strlen.
> > strlen requires that the pointer actually point to a string. In order
> > for an array of char to contain a string, the array must contain at
> > least one '\0' to properly terminate the string. charset does not.
>
> A simple fix is to get rid of the '62':
>
> char charset[] =
> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>
> Then the trailing 0 that is part of every string constant is included
> (otherwise the 63 chars including \0 are truncated to 62).
Another small improvement would be to use the compiler's ability to
concatenate string literals. I'd make the three sequences separate
string literals so they can be lined up.
char charset[] =
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ"
"0123456789";
If you happen to miss a letter while typing one of the two alphabets,
the error would immediately be apparent to the eye.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-11-06 19:19 -0800 |
| Message-ID | <ln36f05q6t.fsf@kst-u.example.com> |
| In reply to | #147684 |
Bart <bc@freeuk.com> writes:
> On 06/11/2019 22:23, Barry Schwarz wrote:
>> On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote:
>>> char charset[62] =
>>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>> After numerous examples in your comp.lang.c posts (where I have
>> redirected this response since we are not discussing the odds any
>> more) of calculating charsetLen correctly, you have chosen to use a
>> different method. You have tried to pass charset to strlen in
>> complete violation of the requirements that function imposes.
>>
>> It is not sufficient to simply pass a pointer to char to strlen.
>> strlen requires that the pointer actually point to a string. In order
>> for an array of char to contain a string, the array must contain at
>> least one '\0' to properly terminate the string. charset does not.
>
> A simple fix is to get rid of the '62':
>
> char charset[] =
> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
The only thing the code does that depends on charset containing a
valid string is the single (incorrect) call to strlen(). If you
replace `strlen(charset)` by `sizeof charset` then there's no need
to nul-terminate it.
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Ian Collins <ian-news@hotmail.com> |
|---|---|
| Date | 2019-11-07 16:30 +1300 |
| Message-ID | <h2hhf7Fq967U11@mid.individual.net> |
| In reply to | #147696 |
On 07/11/2019 16:19, Keith Thompson wrote: > Bart <bc@freeuk.com> writes: >> On 06/11/2019 22:23, Barry Schwarz wrote: >>> On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote: >>>> char charset[62] = >>>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; >>> After numerous examples in your comp.lang.c posts (where I have >>> redirected this response since we are not discussing the odds any >>> more) of calculating charsetLen correctly, you have chosen to use a >>> different method. You have tried to pass charset to strlen in >>> complete violation of the requirements that function imposes. >>> >>> It is not sufficient to simply pass a pointer to char to strlen. >>> strlen requires that the pointer actually point to a string. In order >>> for an array of char to contain a string, the array must contain at >>> least one '\0' to properly terminate the string. charset does not. >> >> A simple fix is to get rid of the '62': >> >> char charset[] = >> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; > > The only thing the code does that depends on charset containing a > valid string is the single (incorrect) call to strlen(). If you > replace `strlen(charset)` by `sizeof charset` then there's no need > to nul-terminate it. Or do what I did in my C++ version and use a compile time constant for the size. That way the compile will break if you miss out a character. -- Ian.
[toc] | [prev] | [next] | [standalone]
| From | Bart <bc@freeuk.com> |
|---|---|
| Date | 2019-11-07 10:59 +0000 |
| Message-ID | <0OSwF.55314$_d3.10705@fx38.am4> |
| In reply to | #147698 |
On 07/11/2019 03:30, Ian Collins wrote: > On 07/11/2019 16:19, Keith Thompson wrote: >> The only thing the code does that depends on charset containing a >> valid string is the single (incorrect) call to strlen(). If you >> replace `strlen(charset)` by `sizeof charset` then there's no need >> to nul-terminate it. > Or do what I did in my C++ version and use a compile time constant for > the size. That way the compile will break if you miss out a character. What does that look like? With a specified bound, C is only interested if you have too many characters, not too few.
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2019-11-07 14:27 +0100 |
| Message-ID | <qq1649$vvi$1@dont-email.me> |
| In reply to | #147698 |
On 07/11/2019 04:30, Ian Collins wrote: > On 07/11/2019 16:19, Keith Thompson wrote: >> Bart <bc@freeuk.com> writes: >>> On 06/11/2019 22:23, Barry Schwarz wrote: >>>> On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote: >>>>> char charset[62] = >>>>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; >>>> After numerous examples in your comp.lang.c posts (where I have >>>> redirected this response since we are not discussing the odds any >>>> more) of calculating charsetLen correctly, you have chosen to use a >>>> different method. You have tried to pass charset to strlen in >>>> complete violation of the requirements that function imposes. >>>> >>>> It is not sufficient to simply pass a pointer to char to strlen. >>>> strlen requires that the pointer actually point to a string. In order >>>> for an array of char to contain a string, the array must contain at >>>> least one '\0' to properly terminate the string. charset does not. >>> >>> A simple fix is to get rid of the '62': >>> >>> char charset[] = >>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; >> >> The only thing the code does that depends on charset containing a >> valid string is the single (incorrect) call to strlen(). If you >> replace `strlen(charset)` by `sizeof charset` then there's no need >> to nul-terminate it. > Or do what I did in my C++ version and use a compile time constant for > the size. That way the compile will break if you miss out a character. > C++ will complain if the initialiser is too long (as it is in this case, but not if it is too short. (A compiler may provide a warning, of course.) I think the best way to ensure such arrays are the size you expect are to omit the size in the definition, then use a static assertion to check it: const char charset[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; _Static_assert(sizeof(charset) == 63, "Charset should be 62 chars plus terminating zero"); If you have got your alphabet wrong, you'll get a compile-time error.
[toc] | [prev] | [next] | [standalone]
| From | DFS <nospam@dfs.com> |
|---|---|
| Date | 2019-11-06 18:09 -0500 |
| Message-ID | <joIwF.86203$FF4.79851@fx40.iad> |
| In reply to | #147683 |
On 11/6/2019 5:23 PM, Barry Schwarz wrote:
> On Wed, 6 Nov 2019 15:52:28 -0500, DFS <nospam@dfs.com> wrote:
>
>> On 11/6/2019 1:08 PM, Barry Schwarz wrote:
>
> <snip>
>
>>> One of the simplest things you can do that make programming
>>> exponentially easier is use a consistent indenting scheme. This
>>> will help you avoid nesting level errors.
>>
>>
>> The indenting is fine in my editor, but a mix of tabs and spaces
>> comes out bad when the code is pasted to Thunderbird.
>
> When asking for help, it behooves one to make things as easy as
> possible for the reader. Experienced people in this newsgroup have
> recommended spaces instead of tabs so that the resulting display is
> not dependent on how the reader's tabs are set.
I'll do that.
>>>> Maybe you can show me how to fix the //letter distribution part
>>>> of the code. I can't get it to compile.
>>>
>>> The error message for the statement that calls strcmp should have
>>> been crystal clear. What part of it did you not understand?
>>
>>
>> I got it:
>
> You got that part of it but then decided to break another part.
> <snip>
>
>> //letter distribution char charset[62] =
>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>> int charsetLen = strlen(charset);
>
> After numerous examples in your comp.lang.c posts (where I have
> redirected this response since we are not discussing the odds any
> more) of calculating charsetLen correctly,
Actually, I never calculated it before. I hard-coded it.
short charsetLen = 62;
> you have chosen to use a
> different method. You have tried to pass charset to strlen in
> complete violation of the requirements that function imposes.
>
> It is not sufficient to simply pass a pointer to char to strlen.
> strlen requires that the pointer actually point to a string. In
> order for an array of char to contain a string, the array must
> contain at least one '\0' to properly terminate the string. charset
> does not. As a result, this code exhibits undefined behavior.
char charset[62]
="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int charsetLen = strlen(charset);
printf("%d \n",charsetLen);
62
char charset[63] =
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
int charsetLen = strlen(charset);
printf("%d \n",charsetLen);
62
> When you tested the code, did you not notice extraneous lines of
> output after the line for "9"?
Not seeing that. Compiled and ran on tcc/Windows and gcc (MSYS2) and
there are no extraneous lines of output after the output for 9.
I do notice on tcc/Windows the count for 9 is always significantly lower
than the count of any other character in the set. Low 15Ks vs high
15Ks/low 16Ks for all the other characters.
That doesn't happen on gcc/MSYS2.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2019-11-06 19:26 -0800 |
| Message-ID | <lny2ws4ba3.fsf@kst-u.example.com> |
| In reply to | #147686 |
DFS <nospam@dfs.com> writes:
[...]
> char charset[62]
> ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
> int charsetLen = strlen(charset);
> printf("%d \n",charsetLen);
> 62
That still has undefined behavior. It appears to "work" only because,
most likely, there just happens to be a null byte in memory immediately
after charset.
I just compiled and ran your on my system. I got 62 with gcc and clang,
and 65 with tcc. There is not necessarily any particular reason for
this, and it could just as easily produce different results tomorrow.
> char charset[63] =
> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
> int charsetLen = strlen(charset);
> printf("%d \n",charsetLen);
> 62
That's well defined, but as I mentioned elsethread your (incorrect)
strlen call is the only thing that relies on charset containing a valid
string.
If you define charset using [] you can get its size using sizeof.
>> When you tested the code, did you not notice extraneous lines of
>> output after the line for "9"?
>
> Not seeing that. Compiled and ran on tcc/Windows and gcc (MSYS2) and
> there are no extraneous lines of output after the output for 9.
That's one of thep problems with undefined behavior: it can evade
testing.
[...]
--
Keith Thompson (The_Other_Keith) kst-u@mib.org <http://www.ghoti.net/~kst>
Working, but not speaking, for Philips Healthcare
void Void(void) { Void(); } /* The recursive call of the void */
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2019-11-07 11:57 +0000 |
| Message-ID | <87o8xnj3vs.fsf@bsb.me.uk> |
| In reply to | #147697 |
Keith Thompson <kst-u@mib.org> writes:
> DFS <nospam@dfs.com> writes:
> [...]
>> char charset[62]
>> ="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>> int charsetLen = strlen(charset);
>> printf("%d \n",charsetLen);
>> 62
>
> That still has undefined behavior. It appears to "work" only because,
> most likely, there just happens to be a null byte in memory immediately
> after charset.
>
> I just compiled and ran your on my system. I got 62 with gcc and clang,
> and 65 with tcc. There is not necessarily any particular reason for
> this, and it could just as easily produce different results tomorrow.
>
>> char charset[63] =
>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
>> int charsetLen = strlen(charset);
>> printf("%d \n",charsetLen);
>> 62
>
> That's well defined, but as I mentioned elsethread your (incorrect)
> strlen call is the only thing that relies on charset containing a valid
> string.
>
> If you define charset using [] you can get its size using sizeof.
(This is to the OP...) You will get 63 using sizeof because the size
includes the null that will be put there if you [] in the array
declaration. You have to write sizeof charset - 1. Keith's previous
remark about using sizeof refereed to the case what you gave an explicit
size in the array declaration.
Just in case things have got confused, here are your options:
char s[] = "abc";
s will be a null terminated string and you can get the number of
non-null characters using either strlen(s) or sizeof s - 1.
char s[3] = "abc";
s will not be a string. There is no guarantee that there will be a null
at the end (though there might be one by accident). You can't use
strlen but sizeof s will give you 3.
char *s = "abc";
s points to the start of a null-terminated string. You can get the
number of non-null characters in it using strlen(s) but you can't size
sizeof s because that will report only the size of the pointer s.
(And you can put const in front of all of these to tell the reader the
that this is read-only data. Indeed, in the last case you can write
const char *const s = "abc";
to show that the pointer s itself is read-only as well as the string it
points to.)
--
Ben.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web