Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #102211 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2017-01-20 01:24 -0800 |
| Last post | 2017-01-21 05:36 -0800 |
| Articles | 20 on this page of 42 — 10 participants |
Back to article view | Back to comp.lang.c
while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 01:24 -0800
Re: while loop condition doesn't work mark.bluemel@gmail.com - 2017-01-20 03:29 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-20 12:19 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 05:12 -0800
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-20 13:17 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 05:20 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-20 15:07 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 05:31 -0800
Re: while loop condition doesn't work Manfred <noname@invalid.add> - 2017-01-20 15:23 +0100
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-20 15:16 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 07:45 -0800
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-20 16:06 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 08:37 -0800
Re: while loop condition doesn't work David Brown <david.brown@hesbynett.no> - 2017-01-20 17:54 +0100
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-20 17:04 +0000
Re: while loop condition doesn't work David Brown <david.brown@hesbynett.no> - 2017-01-20 19:08 +0100
Re: while loop condition doesn't work Tim Rentsch <txr@alumni.caltech.edu> - 2017-01-30 12:51 -0800
Re: while loop condition doesn't work Keith Thompson <kst-u@mib.org> - 2017-01-30 14:09 -0800
Re: while loop condition doesn't work supercat@casperkitty.com - 2017-01-30 14:57 -0800
Re: while loop condition doesn't work Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-01 21:31 -0800
Re: while loop condition doesn't work Keith Thompson <kst-u@mib.org> - 2017-02-02 10:01 -0800
Re: while loop condition doesn't work Tim Rentsch <txr@alumni.caltech.edu> - 2017-02-04 00:22 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-20 19:12 +0000
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-23 10:54 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 23:22 -0800
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-23 11:02 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-21 01:22 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-21 11:00 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-21 08:35 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-21 17:17 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-21 09:32 -0800
Re: while loop condition doesn't work Ben Bacarisse <ben.usenet@bsb.me.uk> - 2017-01-20 19:16 +0000
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-23 11:03 +0000
Re: while loop condition doesn't work David Brown <david.brown@hesbynett.no> - 2017-01-20 14:34 +0100
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 07:40 -0800
Re: while loop condition doesn't work Richard Heathfield <rjh@cpax.org.uk> - 2017-01-20 15:47 +0000
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 08:26 -0800
Re: while loop condition doesn't work David Brown <david.brown@hesbynett.no> - 2017-01-20 18:01 +0100
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 09:26 -0800
Re: while loop condition doesn't work David Brown <david.brown@hesbynett.no> - 2017-01-20 19:02 +0100
Re: while loop condition doesn't work Alla _ <modelling.data@gmail.com> - 2017-01-20 10:13 -0800
Re: while loop condition doesn't work Malcolm McLean <malcolm.mclean5@btinternet.com> - 2017-01-21 05:36 -0800
Page 1 of 3 [1] 2 3 Next page →
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 01:24 -0800 |
| Subject | while loop condition doesn't work |
| Message-ID | <750784a4-22dc-44ef-8972-34d4fb048b00@googlegroups.com> |
Hello!
Please, help me to understand why a very simple while loop
condition doesn't work - it doesn't stop the loop when I
expect it to stop.
Please, take a look at the piece of code, and my explanation
of how I intended it to perform:
Input:
1062,1252,1587,1934,2519
Count starts at 5.
double number_1 = strtod(ptr, ¬_converted);
if (not_converted > ptr)
{
double number_2 = 0;
while(not_converted > ptr && (!isspace(*not_converted)
|| *not_converted != '\0'))
{
ptr = not_converted + 1;
number_2 = strtod(ptr, ¬_converted);
count--;
}
if(count != 1)
return false;
}
Explanation:
(1) before the loop number_1 = 1062, and
not_converted is ",1252,1587,1934,2519"
(2) not_converted is bigger than ptr, and not_converted
doesn't point to any space character or '\0';
so the loop starts;
(3) ptr at the beginning of the loop is set to "1252,1587,1934,2519";
number_2 = 1252
not_converted points to ",1587,1934,2519"
count = 4
(4) ptr at the beginning of the loop is set to "1587,1934,2519";
number_2 = 1587
not_converted points to ",1934,2519"
count = 3
(5) ptr at the beginning of the loop is set to "1934,2519";
number_2 = 1934
not_converted points to ",2519"
count = 2
(6) ptr at the beginning of the loop is set to "2519";
number_2 = 2519
not_converted points to "space character"
count = 1
As not_converted points to space, the loop should terminate,
hence the number_2 should be 2519 and count should also
stay 1. But the loop doesn't terminate, and makes one more
iteration.
The hex dump of the full line (it also contains the name
before numbers; but the name is left behind when the program
starts executing the code above) reveals two newline characters,
which should be detected by isspace():
53 61 6C 65 73 2C 31 30 36 32 2C 31 32 35 32 2C
31 35 38 37 2C 31 39 33 34 2C 32 35 31 39 0D 0A
Thank you!
[toc] | [next] | [standalone]
| From | mark.bluemel@gmail.com |
|---|---|
| Date | 2017-01-20 03:29 -0800 |
| Message-ID | <b63925af-2cec-465f-b3b9-701c9bf1e28b@googlegroups.com> |
| In reply to | #102211 |
On Friday, 20 January 2017 09:24:10 UTC, Alla _ wrote:
> Hello!
>
> Please, help me to understand why a very simple while loop
> condition doesn't work - it doesn't stop the loop when I
> expect it to stop.
> Please, take a look at the piece of code, and my explanation
> of how I intended it to perform:
>
> Input:
> 1062,1252,1587,1934,2519
>
> Count starts at 5.
>
> double number_1 = strtod(ptr, ¬_converted);
> if (not_converted > ptr)
> {
> double number_2 = 0;
>
> while(not_converted > ptr && (!isspace(*not_converted)
> || *not_converted != '\0'))
> {
> ptr = not_converted + 1;
> number_2 = strtod(ptr, ¬_converted);
> count--;
> }
> if(count != 1)
> return false;
> }
Consider this part of your test (which is, IMHO, pretty loathesome) :-
(!isspace(*not_converted) || *not_converted != '\0')
If not_converted points to (say) newline, then
"isspace(*not_coverted)" is true
so
"!isspace(*not_coverted)" is false
So the second part of the test is evaluated :-
"*not_converted != '\0'" is true
so the whole of the bracketed expression is true, so we continue.
You probably want && in place of ||, but I'd be looking for a clearer way to express my intent.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-20 12:19 +0000 |
| Message-ID | <871svxdiu9.fsf@bsb.me.uk> |
| In reply to | #102211 |
Alla _ <modelling.data@gmail.com> writes:
> Please, help me to understand why a very simple while loop
> condition doesn't work - it doesn't stop the loop when I
> expect it to stop.
> Please, take a look at the piece of code, and my explanation
> of how I intended it to perform:
>
> Input:
> 1062,1252,1587,1934,2519
>
> Count starts at 5.
>
> double number_1 = strtod(ptr, ¬_converted);
> if (not_converted > ptr)
> {
> double number_2 = 0;
>
> while(not_converted > ptr && (!isspace(*not_converted)
> || *not_converted != '\0'))
> {
> ptr = not_converted + 1;
> number_2 = strtod(ptr, ¬_converted);
> count--;
> }
> if(count != 1)
> return false;
> }
> Explanation:
> (1) before the loop number_1 = 1062, and
> not_converted is ",1252,1587,1934,2519"
> (2) not_converted is bigger than ptr, and not_converted
> doesn't point to any space character or '\0';
That's not what your test does. Please, please, please, if you take
nothing else from my coaching, always negate a while condition to see
what it is you are trying to establish:
while(nc > ptr && (!isspace(*nc) || *nc != '\0')) ...
is trying to make the condition false. It stops when
!(nc > ptr && (!isspace(*nc) || *nc != '\0'))
== !(nc > ptr) || !(!isspace(*nc) || *nc != '\0')
== nc <= ptr || (!!isspace(*nc) && !(*nc != '\0'))
== nc <= ptr || (isspace(*nc) && *nc == '\0')
== nc <= ptr || 0
== nc <= ptr
I've urged you to do this on several occasions. Do it every time you
write a loop until you can do it without thinking. (It's complicated by
break, but you should be avoiding break.)
The main logic rules involved are called De Morgan's laws:
!(A && B) => !A || !B
!(A || B) => !A && !B
<snip>
On another issue, a well-structured program to read numbers and checking
how many there are will have a call to strtod in only one place.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 05:12 -0800 |
| Message-ID | <fc3ad7a9-282a-4831-85e6-fcec02b2d821@googlegroups.com> |
| In reply to | #102217 |
On Friday, January 20, 2017 at 3:19:58 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
>
> > Please, help me to understand why a very simple while loop
> > condition doesn't work - it doesn't stop the loop when I
> > expect it to stop.
> > Please, take a look at the piece of code, and my explanation
> > of how I intended it to perform:
> >
> > Input:
> > 1062,1252,1587,1934,2519
> >
> > Count starts at 5.
> >
> > double number_1 = strtod(ptr, ¬_converted);
> > if (not_converted > ptr)
> > {
> > double number_2 = 0;
> >
> > while(not_converted > ptr && (!isspace(*not_converted)
> > || *not_converted != '\0'))
> > {
> > ptr = not_converted + 1;
> > number_2 = strtod(ptr, ¬_converted);
> > count--;
> > }
> > if(count != 1)
> > return false;
> > }
> > Explanation:
> > (1) before the loop number_1 = 1062, and
> > not_converted is ",1252,1587,1934,2519"
> > (2) not_converted is bigger than ptr, and not_converted
> > doesn't point to any space character or '\0';
>
> That's not what your test does. Please, please, please, if you take
> nothing else from my coaching, always negate a while condition to see
> what it is you are trying to establish:
>
> while(nc > ptr && (!isspace(*nc) || *nc != '\0')) ...
>
> is trying to make the condition false. It stops when
>
> !(nc > ptr && (!isspace(*nc) || *nc != '\0'))
> == !(nc > ptr) || !(!isspace(*nc) || *nc != '\0')
> == nc <= ptr || (!!isspace(*nc) && !(*nc != '\0'))
> == nc <= ptr || (isspace(*nc) && *nc == '\0')
> == nc <= ptr || 0
> == nc <= ptr
>
> I've urged you to do this on several occasions. Do it every time you
> write a loop until you can do it without thinking. (It's complicated by
> break, but you should be avoiding break.)
>
> The main logic rules involved are called De Morgan's laws:
>
> !(A && B) => !A || !B
> !(A || B) => !A && !B
>
Yes. I have experienced a mental block.
Sad, though, to read "if you take nothing else
from my coaching". Is everything that bad?
Well, I can answer this myself: I know
it is, but we have only started, and it was not enough
for good habits to develop and establish themselves.
> <snip>
>
> On another issue, a well-structured program to read numbers and checking
> how many there are will have a call to strtod in only one place.
Ok... Going back to rethink that piece. But. I am not checking how many
there, I am finding and storing the last one - I need only the first and
the last one in the line.
>
> --
> Ben.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2017-01-20 13:17 +0000 |
| Message-ID | <o5t2i9$44d$4@dont-email.me> |
| In reply to | #102221 |
On 20/01/17 13:12, Alla _ wrote: > Sad, though, to read "if you take nothing else > from my coaching". Is everything that bad? I don't think he means that. I think he means that the advice he gave you about negating every condition to verify that it's doing what you think it's doing is the most important advice he has ever given you. Therefore, whatever else you might learn from him, be sure to learn THAT. -- Richard Heathfield Email: rjh at cpax dot org dot uk "Usenet is a strange place" - dmr 29 July 1999 Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 05:20 -0800 |
| Message-ID | <78c2de2d-1438-4cac-9fe1-ef39c0d10fd1@googlegroups.com> |
| In reply to | #102223 |
On Friday, January 20, 2017 at 4:17:37 PM UTC+3, Richard Heathfield wrote: > On 20/01/17 13:12, Alla _ wrote: > > > Sad, though, to read "if you take nothing else > > from my coaching". Is everything that bad? > > I don't think he means that. I think he means that the advice he gave > you about negating every condition to verify that it's doing what you > think it's doing is the most important advice he has ever given you. > Therefore, whatever else you might learn from him, be sure to learn THAT. > Understood. Thank you!
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-20 15:07 +0000 |
| Message-ID | <87vat9bwia.fsf@bsb.me.uk> |
| In reply to | #102223 |
Richard Heathfield <rjh@cpax.org.uk> writes: > On 20/01/17 13:12, Alla _ wrote: > >> Sad, though, to read "if you take nothing else >> from my coaching". Is everything that bad? > > I don't think he means that. I think he means that the advice he gave > you about negating every condition to verify that it's doing what you > think it's doing is the most important advice he has ever given > you. Therefore, whatever else you might learn from him, be sure to > learn THAT. Yes, exactly. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 05:31 -0800 |
| Message-ID | <e9b02777-9542-4e5b-bbf7-885c9bbcb5da@googlegroups.com> |
| In reply to | #102217 |
On Friday, January 20, 2017 at 3:19:58 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
>
<snip>
>
> On another issue, a well-structured program to read numbers and checking
> how many there are will have a call to strtod in only one place.
>
Here how it looks now - I have to think how to eliminate the call to strtod:
/** Function to compute CAGR **/
bool gr_rate(char *line, struct assumptions *rates)
{
char *ptr = line;
char *not_converted = NULL;
int count = DATA_SIZE;
double number_1 = strtod(ptr, ¬_converted);
double number_2 = 0;
if (not_converted > ptr)
{
while(not_converted > ptr && !isspace(*not_converted))
{
if(*not_converted != '\0')
{
ptr = not_converted + 1;
number_2 = strtod(ptr, ¬_converted);
count--;
}
}
if(count != 1)
return false;
rates->gr_sales = pow((number_2/number_1), (1.0/DATA_SIZE));
return true;
}
return false;
}
[toc] | [prev] | [next] | [standalone]
| From | Manfred <noname@invalid.add> |
|---|---|
| Date | 2017-01-20 15:23 +0100 |
| Message-ID | <o5t6gc$lrs$1@gioia.aioe.org> |
| In reply to | #102226 |
On 1/20/2017 2:31 PM, Alla _ wrote: > On Friday, January 20, 2017 at 3:19:58 PM UTC+3, Ben Bacarisse wrote: > <snip> >> On another issue, a well-structured program to read numbers and checking >> how many there are will have a call to strtod in only one place. Excellent advice. >> > Here how it looks now - I have to think how to eliminate the call to strtod: A hint about this (hope this helps): usage of strtod requires checking that the scan termination (*endptr) is larger than the start of the string; which can be checked only after executing strtod itself. Therefore I would think of one of the following: - use a do-while loop - use a comma operator (less obvious, more compact)
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2017-01-20 15:16 +0000 |
| Message-ID | <87pojhbw2h.fsf@bsb.me.uk> |
| In reply to | #102226 |
Alla _ <modelling.data@gmail.com> writes:
> On Friday, January 20, 2017 at 3:19:58 PM UTC+3, Ben Bacarisse wrote:
>> Alla _ <modelling.data@gmail.com> writes:
>>
> <snip>
>>
>> On another issue, a well-structured program to read numbers and checking
>> how many there are will have a call to strtod in only one place.
>>
> Here how it looks now - I have to think how to eliminate the call to strtod:
>
> /** Function to compute CAGR **/
> bool gr_rate(char *line, struct assumptions *rates)
This looks odd. Why is it computing something so specific? You will
want to read 5 numbers on every line so surely there will be a function
to read 5 numbers. The various calculations will then be separate
functions that are passed the numbers in an array.
> {
> char *ptr = line;
> char *not_converted = NULL;
> int count = DATA_SIZE;
> double number_1 = strtod(ptr, ¬_converted);
> double number_2 = 0;
> if (not_converted > ptr)
> {
> while(not_converted > ptr && !isspace(*not_converted))
Why are you interested in non-spaces? Nothing in your specification
seems to need non-spaces. Can you write out what the input should look
like in general? I.e. what will you permit and what won't you permit?
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 07:45 -0800 |
| Message-ID | <d4616907-128c-442d-b29e-82bf47b4e83d@googlegroups.com> |
| In reply to | #102234 |
On Friday, January 20, 2017 at 6:17:01 PM UTC+3, Ben Bacarisse wrote:
> Alla _ <modelling.data@gmail.com> writes:
>
> > On Friday, January 20, 2017 at 3:19:58 PM UTC+3, Ben Bacarisse wrote:
> >> Alla _ <modelling.data@gmail.com> writes:
> >>
> > <snip>
> >>
> >> On another issue, a well-structured program to read numbers and checking
> >> how many there are will have a call to strtod in only one place.
> >>
> > Here how it looks now - I have to think how to eliminate the call to strtod:
> >
> > /** Function to compute CAGR **/
> > bool gr_rate(char *line, struct assumptions *rates)
>
> This looks odd. Why is it computing something so specific? You will
> want to read 5 numbers on every line so surely there will be a function
> to read 5 numbers. The various calculations will then be separate
> functions that are passed the numbers in an array.
>
> > {
> > char *ptr = line;
> > char *not_converted = NULL;
> > int count = DATA_SIZE;
> > double number_1 = strtod(ptr, ¬_converted);
> > double number_2 = 0;
> > if (not_converted > ptr)
> > {
> > while(not_converted > ptr && !isspace(*not_converted))
>
> Why are you interested in non-spaces? Nothing in your specification
> seems to need non-spaces. Can you write out what the input should look
> like in general? I.e. what will you permit and what won't you permit?
With this function I just need two numbers out of 5 - the first and the last
one. At the moment the function is called the input
contains numbers, separated by commas (csv format), as in
1062,1252,1587,1934,2519
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2017-01-20 16:06 +0000 |
| Message-ID | <o5tcfb$ap3$1@dont-email.me> |
| In reply to | #102236 |
On 20/01/17 15:45, Alla _ wrote:
> On Friday, January 20, 2017 at 6:17:01 PM UTC+3, Ben Bacarisse wrote:
>> Alla _ <modelling.data@gmail.com> writes:
<snip>
>>> while(not_converted > ptr && !isspace(*not_converted))
>>
>> Why are you interested in non-spaces? [...]
> With this function I just need two numbers out of 5 - the first and the last
> one. At the moment the function is called the input
> contains numbers, separated by commas (csv format), as in
> 1062,1252,1587,1934,2519
In which case you have no need to call isspace at all, and the whole
thing can be done in less than a dozen lines of very simple code.
n = 0; /* this is how many numbers you've successfully parsed */
do
{
/* try to convert a number */
num[n] = strtod(ptr, ¬_converted, 10);
/* if that worked... */
if(not_converted > ptr)
{
/* record the success */
++n;
/* if we're just at a field boundary, we
want to move to just past that boundary.
If we're at the end of the string,
then two things happen: (1) we can't be
sure that it's legal to move past the '\0'
AND (2) there is in any case nothing more
to convert.
So if we're not at '\0', we want ptr to
point to not_converted + 1. Otherwise, we
want ptr to point to not_converted (which will
terminate the loop).
In C, the result of a condition is either 0
(false), or 1 (true), and this happens to map
precisely onto what we want. So we can do this:
*/
ptr = not_converted + (*not_converted != '\0');
}
} while(not_converted > ptr && n < expected_count);
expected_count would appear to be 5 in this case. If it's always 5, use
a constant e.g. #define NUMBERS_PER_LINE 5
if(n == expected_count) you have all the numbers you need. If it isn't,
you don't, and presumably that's an error.
Note the complete absence of isspace.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2017-01-20 08:37 -0800 |
| Message-ID | <2f5efea6-4d06-42bf-a6f9-976e1faf51e4@googlegroups.com> |
| In reply to | #102238 |
On Friday, January 20, 2017 at 7:06:52 PM UTC+3, Richard Heathfield wrote:
> On 20/01/17 15:45, Alla _ wrote:
> > On Friday, January 20, 2017 at 6:17:01 PM UTC+3, Ben Bacarisse wrote:
> >> Alla _ <modelling.data@gmail.com> writes:
> <snip>
> >>> while(not_converted > ptr && !isspace(*not_converted))
> >>
> >> Why are you interested in non-spaces? [...]
> > With this function I just need two numbers out of 5 - the first and the last
> > one. At the moment the function is called the input
> > contains numbers, separated by commas (csv format), as in
> > 1062,1252,1587,1934,2519
>
> In which case you have no need to call isspace at all, and the whole
> thing can be done in less than a dozen lines of very simple code.
>
> n = 0; /* this is how many numbers you've successfully parsed */
> do
> {
> /* try to convert a number */
> num[n] = strtod(ptr, ¬_converted, 10);
>
> /* if that worked... */
> if(not_converted > ptr)
> {
> /* record the success */
> ++n;
>
> /* if we're just at a field boundary, we
> want to move to just past that boundary.
> If we're at the end of the string,
> then two things happen: (1) we can't be
> sure that it's legal to move past the '\0'
> AND (2) there is in any case nothing more
> to convert.
>
> So if we're not at '\0', we want ptr to
> point to not_converted + 1. Otherwise, we
> want ptr to point to not_converted (which will
> terminate the loop).
>
> In C, the result of a condition is either 0
> (false), or 1 (true), and this happens to map
> precisely onto what we want. So we can do this:
> */
>
> ptr = not_converted + (*not_converted != '\0');
Yet another amazing trick! ) Thank you. I didn't know
about it. Not surprising though )
> }
> } while(not_converted > ptr && n < expected_count);
>
> expected_count would appear to be 5 in this case. If it's always 5, use
> a constant e.g. #define NUMBERS_PER_LINE 5
Yes, I have this in the program. This was a tiny piece I have created
out of few pieces to ask for help.
Your approach is great for storing all numbers in the array, which
was not my intent in this piece; but it is great for the program itself,
there I do store numbers in the array of structs.
>
> if(n == expected_count) you have all the numbers you need. If it isn't,
> you don't, and presumably that's an error.
>
> Note the complete absence of isspace.
>
> --
> Richard Heathfield
> Email: rjh at cpax dot org dot uk
> "Usenet is a strange place" - dmr 29 July 1999
> Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-01-20 17:54 +0100 |
| Message-ID | <o5tf8a$lpn$1@dont-email.me> |
| In reply to | #102238 |
On 20/01/17 17:06, Richard Heathfield wrote:
>
> /* if we're just at a field boundary, we
> want to move to just past that boundary.
> If we're at the end of the string,
> then two things happen: (1) we can't be
> sure that it's legal to move past the '\0'
> AND (2) there is in any case nothing more
> to convert.
>
> So if we're not at '\0', we want ptr to
> point to not_converted + 1. Otherwise, we
> want ptr to point to not_converted (which will
> terminate the loop).
>
> In C, the result of a condition is either 0
> (false), or 1 (true), and this happens to map
> precisely onto what we want. So we can do this:
> */
>
> ptr = not_converted + (*not_converted != '\0');
>
And how is that better than:
if (*not_converted != '\0') {
ptr = not_converted + 1;
} else {
ptr = not_converted;
}
Rather than writing a nice, clear explanation in comments followed by
code with a completely different structure, why not simply write the
code that follows the nice, clear explanation? Then you can also skip
that part of the comment.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2017-01-20 17:04 +0000 |
| Message-ID | <o5tfrf$o7q$1@dont-email.me> |
| In reply to | #102243 |
On 20/01/17 16:54, David Brown wrote:
> On 20/01/17 17:06, Richard Heathfield wrote:
>>
>> /* if we're just at a field boundary, we
>> want to move to just past that boundary.
>> If we're at the end of the string,
>> then two things happen: (1) we can't be
>> sure that it's legal to move past the '\0'
>> AND (2) there is in any case nothing more
>> to convert.
>>
>> So if we're not at '\0', we want ptr to
>> point to not_converted + 1. Otherwise, we
>> want ptr to point to not_converted (which will
>> terminate the loop).
>>
>> In C, the result of a condition is either 0
>> (false), or 1 (true), and this happens to map
>> precisely onto what we want. So we can do this:
>> */
>>
>> ptr = not_converted + (*not_converted != '\0');
>>
>
> And how is that better than:
>
> if (*not_converted != '\0') {
> ptr = not_converted + 1;
> } else {
> ptr = not_converted;
> }
That was in fact my first version (apart from the cuddled 'else'). But
the duplication of code offended my sense of elegance, so I changed it
and added the comment to explain exactly how I'd arrived at it.
Normally, I wouldn't bother with the comment, because to me the code is
obvious. But I (correctly) guessed that Alla wouldn't be familiar with
that idiom, so I took the time to explain it.
--
Richard Heathfield
Email: rjh at cpax dot org dot uk
"Usenet is a strange place" - dmr 29 July 1999
Sig line 4 vacant - apply within
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2017-01-20 19:08 +0100 |
| Message-ID | <o5tjj4$6pg$1@dont-email.me> |
| In reply to | #102245 |
On 20/01/17 18:04, Richard Heathfield wrote:
> On 20/01/17 16:54, David Brown wrote:
>> On 20/01/17 17:06, Richard Heathfield wrote:
>>>
>>> /* if we're just at a field boundary, we
>>> want to move to just past that boundary.
>>> If we're at the end of the string,
>>> then two things happen: (1) we can't be
>>> sure that it's legal to move past the '\0'
>>> AND (2) there is in any case nothing more
>>> to convert.
>>>
>>> So if we're not at '\0', we want ptr to
>>> point to not_converted + 1. Otherwise, we
>>> want ptr to point to not_converted (which will
>>> terminate the loop).
>>>
>>> In C, the result of a condition is either 0
>>> (false), or 1 (true), and this happens to map
>>> precisely onto what we want. So we can do this:
>>> */
>>>
>>> ptr = not_converted + (*not_converted != '\0');
>>>
>>
>> And how is that better than:
>>
>> if (*not_converted != '\0') {
>> ptr = not_converted + 1;
>> } else {
>> ptr = not_converted;
>> }
>
> That was in fact my first version (apart from the cuddled 'else'). But
> the duplication of code offended my sense of elegance, so I changed it
> and added the comment to explain exactly how I'd arrived at it.
>
I'm okay with a bit of code duplication, as long as it is short and
clear. If it were more than a simple assignment that were duplicated,
I'd probably hoist the common part to before the conditional.
> Normally, I wouldn't bother with the comment, because to me the code is
> obvious. But I (correctly) guessed that Alla wouldn't be familiar with
> that idiom, so I took the time to explain it.
>
I guess this has the benefit of teaching a new idiom. While I would not
use it in this piece of code, I might use it elsewhere - it's a useful
idea to know.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-01-30 12:51 -0800 |
| Message-ID | <kfnbmuoff0p.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #102245 |
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 20/01/17 16:54, David Brown wrote:
>> On 20/01/17 17:06, Richard Heathfield wrote:
>>
>>> /* if we're just at a field boundary, we
>>> want to move to just past that boundary.
>>> If we're at the end of the string,
>>> then two things happen: (1) we can't be
>>> sure that it's legal to move past the '\0'
>>> AND (2) there is in any case nothing more
>>> to convert.
>>>
>>> So if we're not at '\0', we want ptr to
>>> point to not_converted + 1. Otherwise, we
>>> want ptr to point to not_converted (which will
>>> terminate the loop).
>>>
>>> In C, the result of a condition is either 0
>>> (false), or 1 (true), and this happens to map
>>> precisely onto what we want. So we can do this:
>>> */
>>>
>>> ptr = not_converted + (*not_converted != '\0');
>>
>> And how is that better than:
>>
>> if (*not_converted != '\0') {
>> ptr = not_converted + 1;
>> } else {
>> ptr = not_converted;
>> }
>
> That was in fact my first version (apart from the cuddled 'else'). But
> the duplication of code offended my sense of elegance, so I changed it
> and added the comment to explain exactly how I'd arrived at it.
I share the opinion that the single statement form is better
here.
> Normally, I wouldn't bother with the comment, because to me the code
> is obvious. But I (correctly) guessed that Alla wouldn't be familiar
> with that idiom, so I took the time to explain it.
This brings up what I think is a more interesting point. In
writing programs for students, it's fairly common to use comments
not because the author thinks the program needs it, but because
it is throught the students need it. Unfortunately this habit
frequently leads to students thinking that sort of commenting
style is how programs should normally be written. That's bad and
even worse self-perpetuating. To fix it we should stop writing
such "educational" comments in any example code, including
(especially) code written with an educational purpose in mind.
Please consider putting any educational commentary outside the
actual code, rather that giving it as comments inside the code.
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2017-01-30 14:09 -0800 |
| Message-ID | <ln37g09p3k.fsf@kst-u.example.com> |
| In reply to | #102798 |
Tim Rentsch <txr@alumni.caltech.edu> writes:
[...]
> This brings up what I think is a more interesting point. In
> writing programs for students, it's fairly common to use comments
> not because the author thinks the program needs it, but because
> it is throught the students need it. Unfortunately this habit
> frequently leads to students thinking that sort of commenting
> style is how programs should normally be written. That's bad and
> even worse self-perpetuating. To fix it we should stop writing
> such "educational" comments in any example code, including
> (especially) code written with an educational purpose in mind.
>
> Please consider putting any educational commentary outside the
> actual code, rather that giving it as comments inside the code.
I agree that there's a problem. I'm not sure eliminating such comments
or moving them elsewhere is the best solution.
For a student just beginning to learn the language, comments like these:
int i; /* Create an object named "i" of type int */
i = 42; /* Assign the value 42 to i */
i ++; /* Increment i by 1 */
as annoying as they might be, can actually be useful. For example
the meaning of "++" is not obvious to a non-programmer, and
having a reminder close to where it's used can be a good reminder.
Putting them outside the code is going to make it more difficult
for the reader to associate the comments with the relevant code.
Perhaps one could use some special marker, with a comment at the
top (and an explanation by the instructor) saying that any marked
comments are intended to explain the language features and should
not be included in real code.
int i; /* TUT: Create an object named "i" of type int */
i = 42; /* TUT: Assign the value 42 to i */
i ++; /* TUT: Increment i by 1 */
(It's been a long time since I was a beginning programmer, so it's hard
for me to tell what would work best.)
--
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 | supercat@casperkitty.com |
|---|---|
| Date | 2017-01-30 14:57 -0800 |
| Message-ID | <8f148b3d-948e-4f48-8bd9-88ba99b345c0@googlegroups.com> |
| In reply to | #102808 |
On Monday, January 30, 2017 at 4:09:28 PM UTC-6, Keith Thompson wrote: > Perhaps one could use some special marker, with a comment at the > top (and an explanation by the instructor) saying that any marked > comments are intended to explain the language features and should > not be included in real code. > > int i; /* TUT: Create an object named "i" of type int */ > i = 42; /* TUT: Assign the value 42 to i */ > i ++; /* TUT: Increment i by 1 */ > > (It's been a long time since I was a beginning programmer, so it's hard > for me to tell what would work best.) An alternative for purposes of printed, PDF, or HTML documents, would be to say that only text which is in a particular distinctive font should be treated as part of a program, and text which is not in that font is intended for human explanation only and is not part of the program. I don't think such an approach would be particularly useful here, however, nor in situations where explanations need to "travel" with the associated code. Perhaps those could best be handled by observing that programs whose purpose is to test or illustrate the behavior of a particular construct should be designed quite differently from programs which are supposed to do real work, and should--as part of that--be commented differently.
[toc] | [prev] | [next] | [standalone]
| From | Tim Rentsch <txr@alumni.caltech.edu> |
|---|---|
| Date | 2017-02-01 21:31 -0800 |
| Message-ID | <kfnwpd9b1kq.fsf@x-alumni2.alumni.caltech.edu> |
| In reply to | #102808 |
Keith Thompson <kst-u@mib.org> writes:
> Tim Rentsch <txr@alumni.caltech.edu> writes:
> [...]
>> This brings up what I think is a more interesting point. In
>> writing programs for students, it's fairly common to use comments
>> not because the author thinks the program needs it, but because
>> it is thought the students need it. Unfortunately this habit
>> frequently leads to students thinking that sort of commenting
>> style is how programs should normally be written. That's bad and
>> even worse self-perpetuating. To fix it we should stop writing
>> such "educational" comments in any example code, including
>> (especially) code written with an educational purpose in mind.
>>
>> Please consider putting any educational commentary outside the
>> actual code, rather that giving it as comments inside the code.
>
> I agree that there's a problem. I'm not sure eliminating such
> comments or moving them elsewhere is the best solution.
How you phrase the statement shows how deep the problem is. My
suggestion is not to move /comments/ but to put /commentary/
outside the program. Any program examples that have /comments/
should have only those comments that one would write as part
of a real (as opposed to example or tutorial) program. The
question of what is the best solution is misplaced: it assumes
we know exactly what problem we're trying to solve, that it is
well-defined, that there is a "best" solution (by what metric?),
and that we could tell whether a proposed solution is a best
solution. My goal is to avoid a behavior fairly well known to
have negative effects. It may be that in the process of doing
that there will be other unexpected effects, but the only way
to know what those might be is to try the suggestion and see
what happens.
> For a student just beginning to learn the language, comments like
> these:
>
> int i; /* Create an object named "i" of type int */
> i = 42; /* Assign the value 42 to i */
> i ++; /* Increment i by 1 */
>
> as annoying as they might be, can actually be useful.
The problem isn't that the comments are annoying. The problem is
that they subconsciously reinforce bad habits. Any usefulness
is temporary; the cost of the bad habits endures much longer.
> For example
> the meaning of "++" is not obvious to a non-programmer, and
> having a reminder close to where it's used can be a good reminder.
It's hard for me to see any useful content in this statement. It
looks like a tautology.
> Putting them outside the code is going to make it more difficult
> for the reader to associate the comments with the relevant code.
Here is an easy way to do that: just repeat the line of code in
question, as an inline block within the commentary. So for
example:
The ++ operator adds one to its operand. The program line
i ++;
has the effect of incrementing the variable 'i' by one. ...
> Perhaps one could use some special marker, with a comment at the
> top (and an explanation by the instructor) saying that any marked
> comments are intended to explain the language features and should
> not be included in real code.
>
> int i; /* TUT: Create an object named "i" of type int */
> i = 42; /* TUT: Assign the value 42 to i */
> i ++; /* TUT: Increment i by 1 */
I've seen this done in other ways (eg, using a different font
for the non-code material). It suffers from many of the same
problems that regular comments do. Most importantly, it too
promotes or reinforces a way of thinking that is damaging to
less experienced programmers. In that respect it isn't really
an improvement over using regular "comments".
> (It's been a long time since I was a beginning programmer, so
> it's hard for me to tell what would work best.)
The "what would work best" phrase tacitly implies that you
know what problem is being addressed. Can you say what problem
it is you're trying to solve here?
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web