Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #69828 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2015-09-07 10:47 -0700 |
| Last post | 2015-09-08 02:39 -0700 |
| Articles | 20 — 12 participants |
Back to article view | Back to comp.lang.c
Issues with array, strlen, etc Alla _ <modelling.data@gmail.com> - 2015-09-07 10:47 -0700
Re: Issues with array, strlen, etc James Kuyper <jameskuyper@verizon.net> - 2015-09-07 14:47 -0400
Re: Issues with array, strlen, etc bartekltg <bartekltg@gmail.com> - 2015-09-07 22:03 +0200
Re: Issues with array, strlen, etc Paul N <gw7rib@aol.com> - 2015-09-07 13:08 -0700
Re: Issues with array, strlen, etc Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-07 22:55 +0100
Re: Issues with array, strlen, etc Rosario19 <Ros@invalid.invalid> - 2015-09-08 07:59 +0200
Re: Issues with array, strlen, etc Rosario19 <Ros@invalid.invalid> - 2015-09-08 08:05 +0200
Re: Issues with array, strlen, etc Barry Schwarz <schwarzb@dqel.com> - 2015-09-07 20:35 -0700
Re: Issues with array, strlen, etc Alla _ <modelling.data@gmail.com> - 2015-09-08 01:08 -0700
Re: Issues with array, strlen, etc Keith Thompson <kst-u@mib.org> - 2015-09-08 09:04 -0700
Re: Issues with array, strlen, etc Alla _ <modelling.data@gmail.com> - 2015-09-10 01:22 -0700
Re: Issues with array, strlen, etc Richard Heathfield <rjh@cpax.org.uk> - 2015-09-10 09:38 +0100
Re: Issues with array, strlen, etc Eric Sosman <esosman@comcast-dot-net.invalid> - 2015-09-10 07:34 -0400
Re: Issues with array, strlen, etc David Brown <david.brown@hesbynett.no> - 2015-09-10 13:47 +0200
Re: Issues with array, strlen, etc Richard Heathfield <rjh@cpax.org.uk> - 2015-09-10 13:11 +0100
Re: Issues with array, strlen, etc Keith Thompson <kst-u@mib.org> - 2015-09-10 10:21 -0700
Re: Issues with array, strlen, etc Geoff <geoff@invalid.invalid> - 2015-09-10 10:42 -0700
Re: Issues with array, strlen, etc Alla _ <modelling.data@gmail.com> - 2015-09-08 01:11 -0700
Re: Issues with array, strlen, etc Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-08 09:51 +0100
Re: Issues with array, strlen, etc Alla _ <modelling.data@gmail.com> - 2015-09-08 02:39 -0700
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-07 10:47 -0700 |
| Subject | Issues with array, strlen, etc |
| Message-ID | <1866812f-e415-44b4-8127-8e21c4a13653@googlegroups.com> |
Hello!
I have started working on a new task.
I decided to break the program into
parts and then combine them.
First part should prompt the user for
a card number; then multiply every other
digit by 2, starting from the number's
second-to-last digit. (please, bear with
me until I will be able to get rid of
scanf; for now, please, allow me to
use it).
I plan to try a few approaches. I think
I am facing not only C programming issues
here, but also issues connected with math.
First approach involves arrays. The program
doesn't do what I thought it should. I post
my thoughts within comments.
#include <stdio.h>
#include <string.h>
int main(void)
{
char card_number[16];
/** limiting the number of possible inputs by
16, because it represents the longest card
number
**/
int i, digit;
printf ("Please, enter your card number: \n");
if (scanf ("%16s", card_number) == 1)
{
for (i = (strlen(card_number)-1); i >= 0; i -= 1)
{
digit = card_number[i] * 2;
printf ("%i", digit);
}
}
/** I have tried to achieve the following:
take the last i-th character of the array
and subtract 1 character; this will be
a starting point, i.e. i = (strlen(card_number)-1);
multiply that character by 2 and store the number
in variable 'digit'; print that number; start the next
loop with the array that has 2 digits less comparing to
the initial array; do until i = 0.
for example:
4 5 6 7
strlen = 4, card_number[4] = 7
i = (strlen(card_number)-1) will be 6, i.e.
card_number[3] = 6
6 * 2 = 12
print 12
next iteration of the loop starts from
digit 5 (because the first loop ended by
i = i - 1, hence at 5, which is on the 3d
position of the array); subtracts 1, and
multiplies 4 by 2.
This intention isn't realized. I don't see why.
**/
printf ("\n");
return 0;
}
Thank you!
[toc] | [next] | [standalone]
| From | James Kuyper <jameskuyper@verizon.net> |
|---|---|
| Date | 2015-09-07 14:47 -0400 |
| Message-ID | <55EDDBBF.9020804@verizon.net> |
| In reply to | #69828 |
On 09/07/2015 01:47 PM, Alla _ wrote:
> Hello!
>
> I have started working on a new task.
> I decided to break the program into
> parts and then combine them.
>
> First part should prompt the user for
> a card number; then multiply every other
> digit by 2, starting from the number's
> second-to-last digit. (please, bear with
> me until I will be able to get rid of
> scanf; for now, please, allow me to
> use it).
>
> I plan to try a few approaches. I think
> I am facing not only C programming issues
> here, but also issues connected with math.
>
> First approach involves arrays. The program
> doesn't do what I thought it should. I post
> my thoughts within comments.
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[16];
>
> /** limiting the number of possible inputs by
> 16, because it represents the longest card
> number
> **/
> int i, digit;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%16s", card_number) == 1)
> {
> for (i = (strlen(card_number)-1); i >= 0; i -= 1)
> {
> digit = card_number[i] * 2;
Note: if the card number is "9876543210", then filling in the array by
calling scanf() this way is roughly is equivalent to
char card_number[16] = {'9', '8', '7', '6', '5', '4', '3', '2', '1',
'0', '\0'};
The main difference is that, with your code, card_number[11],
card_number[12], card_number[13], card_number[14], card_number[15] all
remain uninitialized. With my replacement code, they would all have
values of 0.
On a typical system that uses ASCII encoding, this will also be
equivalent to
char card_number[16] = {57, 56, 55, 54, 53, 52, 51, 50, 49, 48, 0};
If that's not what you expected, that's probably where your problem is.
The reason is that '9' == 57; ASCII uses a value of 57 to encode the
character '9'. So do most of the other encodings currently in
wide-spread use, but there are exceptions, the most prominent being EBCDIC.
If you read in one digit at a time using scanf("%1.1d",
&card_number[i]), then scanf() will perform the conversion from the
character '5' to integer value 5 for you, so you don't have to worry
about it. It will use the appropriate encoding for your platform,
regardless of whether that is ASCII, UTF-8, EBCDIC, UCS2, Shift-JIS,
UTF-16, or anything else.
[toc] | [prev] | [next] | [standalone]
| From | bartekltg <bartekltg@gmail.com> |
|---|---|
| Date | 2015-09-07 22:03 +0200 |
| Message-ID | <mskqii$4d1$1@node1.news.atman.pl> |
| In reply to | #69828 |
On 07.09.2015 19:47, Alla _ wrote:
> Hello!
>
> I have started working on a new task.
> I decided to break the program into
> parts and then combine them.
>
> First part should prompt the user for
> a card number; then multiply every other
> digit by 2, starting from the number's
> second-to-last digit. (please, bear with
> me until I will be able to get rid of
> scanf; for now, please, allow me to
> use it).
>
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[16];
>
> /** limiting the number of possible inputs by
> 16, because it represents the longest card
> number
> **/
> int i, digit;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%16s", card_number) == 1)
> {
> for (i = (strlen(card_number)-1); i >= 0; i -= 1)
> {
> digit = card_number[i] * 2;
card_number[i] is an ASCII code for a character.
https://en.wikipedia.org/wiki/ASCII#ASCII_printable_code_chart
character '0' is represented as _48_.
You have to decode ascii first.
One way is to subtract a code for zero
digit = (card_number[i]-'0') * 2;
Do you know why this works?
> printf ("%i", digit);
6 times 2 is 12, this is not a digit;-)
The output still looks like gibberish, add space
printf ("%i ", digit);
bartekltg
[toc] | [prev] | [next] | [standalone]
| From | Paul N <gw7rib@aol.com> |
|---|---|
| Date | 2015-09-07 13:08 -0700 |
| Message-ID | <2c7e0d58-1527-47be-9c40-c2817a0a455f@googlegroups.com> |
| In reply to | #69828 |
On Monday, 7 September 2015 18:47:30 UTC+1, Alla _ wrote:
> Hello!
>
> I have started working on a new task.
> I decided to break the program into
> parts and then combine them.
>
> First part should prompt the user for
> a card number; then multiply every other
> digit by 2, starting from the number's
> second-to-last digit. (please, bear with
> me until I will be able to get rid of
> scanf; for now, please, allow me to
> use it).
>
> I plan to try a few approaches. I think
> I am facing not only C programming issues
> here, but also issues connected with math.
>
> First approach involves arrays. The program
> doesn't do what I thought it should. I post
> my thoughts within comments.
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[16];
>
> /** limiting the number of possible inputs by
> 16, because it represents the longest card
> number
> **/
> int i, digit;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%16s", card_number) == 1)
> {
> for (i = (strlen(card_number)-1); i >= 0; i -= 1)
Two problems with this line. Firstly, you said you wanted to start with the last but one digit, so your "-1" should be "-2" - see below. And secondly, you said you only wanted to do each alternate digit, so " i -= 1" should be "i -= 2".
> {
> digit = card_number[i] * 2;
As James has said, card_number[i] is a char so it contains a value representing a character. You can change it to the actual number by subtracting the value for the character 0, ie (card_number[i] - '0').
> printf ("%i", digit);
> }
> }
> /** I have tried to achieve the following:
> take the last i-th character of the array
> and subtract 1 character; this will be
> a starting point, i.e. i = (strlen(card_number)-1);
>
> multiply that character by 2 and store the number
> in variable 'digit'; print that number; start the next
> loop with the array that has 2 digits less comparing to
> the initial array; do until i = 0.
> for example:
> 4 5 6 7
> strlen = 4, card_number[4] = 7
No, arrays in C are zero-based. card_number[0] is '4'. card_number[3] is '7'. card_number[4] is zero, marking the end of the string.
> i = (strlen(card_number)-1) will be 6, i.e.
> card_number[3] = 6
> 6 * 2 = 12
> print 12
>
> next iteration of the loop starts from
> digit 5 (because the first loop ended by
> i = i - 1, hence at 5, which is on the 3d
> position of the array); subtracts 1, and
> multiplies 4 by 2.
>
> This intention isn't realized. I don't see why.
> **/
>
> printf ("\n");
> return 0;
> }
> Thank you!
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-07 22:55 +0100 |
| Message-ID | <87lhchq4h8.fsf@bsb.me.uk> |
| In reply to | #69828 |
Alla _ <modelling.data@gmail.com> writes:
> Hello!
>
> I have started working on a new task.
> I decided to break the program into
> parts and then combine them.
>
> First part should prompt the user for
> a card number; then multiply every other
> digit by 2, starting from the number's
> second-to-last digit. (please, bear with
> me until I will be able to get rid of
> scanf; for now, please, allow me to
> use it).
>
> I plan to try a few approaches. I think
> I am facing not only C programming issues
> here, but also issues connected with math.
>
> First approach involves arrays. The program
> doesn't do what I thought it should. I post
> my thoughts within comments.
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[16];
>
> /** limiting the number of possible inputs by
> 16, because it represents the longest card
> number
> **/
> int i, digit;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%16s", card_number) == 1)
You need 15 there. scanf must put a null (zero) byte at the end of the
input, and that means reading no more than 15 characters. You can, of
course, choose to change the array size to 17 instead.
> {
> for (i = (strlen(card_number)-1); i >= 0; i -= 1)
You said "every other digit". Setting i to i-1 will print the next one.
> {
> digit = card_number[i] * 2;
> printf ("%i", digit);
> }
You are likely to get confused by this output because it will be run
together. If is see 710 as the output is that one number, or the result
of printing 7 then 1 then 0, or 7 and then 10? You can't tell.
For now, do something like printf("[%i]", digit); so you can see where
one starts and another ends. You can remove the []s later.
Also, first, just print the digits without any multiplication and in the
normal order and see if you understand the output. Post again if you
don't!
for (i = 0; i < strlen(card_number); ++i) {
digit = card_number[1];
printf("[%i]", digit);
}
<snip>
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Rosario19 <Ros@invalid.invalid> |
|---|---|
| Date | 2015-09-08 07:59 +0200 |
| Message-ID | <k4usuaptmnii8v9bs9v4mvlnfgn5dria5k@4ax.com> |
| In reply to | #69853 |
On Mon, 07 Sep 2015 22:55:31 +0100, Ben Bacarisse wrote:
> for (i = 0; i < strlen(card_number); ++i) {
> digit = card_number[1];
> printf("[%i]", digit);
> }
yes the compiler can optimize etc but i'm more confident on my own
for(i=0, cardLen=strlen(card_number); i<cardLen; ++i)
{digit =card_number[1];
printf("[%i]", digit);
}
or something as above
[toc] | [prev] | [next] | [standalone]
| From | Rosario19 <Ros@invalid.invalid> |
|---|---|
| Date | 2015-09-08 08:05 +0200 |
| Message-ID | <5lusuah399e795pndnlptm2omrovqo9jvo@4ax.com> |
| In reply to | #69864 |
On Tue, 08 Sep 2015 07:59:37 +0200, Rosario19 <Ros@invalid.invalid>
wrote:
>On Mon, 07 Sep 2015 22:55:31 +0100, Ben Bacarisse wrote:
>
>> for (i = 0; i < strlen(card_number); ++i) {
>> digit = card_number[1];
>> printf("[%i]", digit);
>> }
>
>yes the compiler can optimize etc but i'm more confident on my own
> for(i=0, cardLen=strlen(card_number); i<cardLen; ++i)
> {digit =card_number[1];
> printf("[%i]", digit);
> }
>or something as above
yes the compiler can optimize etc but i'm more confident on my own
for(i=0, cardLen=strlen(card_number); i<cardLen; ++i)
{digit =card_number[i];
printf("[%i]", digit);
}
or something as above
[toc] | [prev] | [next] | [standalone]
| From | Barry Schwarz <schwarzb@dqel.com> |
|---|---|
| Date | 2015-09-07 20:35 -0700 |
| Message-ID | <mfqrua9nqer025bvd2lfjcv4rpatuhkoh3@4ax.com> |
| In reply to | #69828 |
On Mon, 7 Sep 2015 10:47:05 -0700 (PDT), Alla _
<modelling.data@gmail.com> wrote:
>Hello!
>
>I have started working on a new task.
>I decided to break the program into
>parts and then combine them.
>
>First part should prompt the user for
>a card number; then multiply every other
>digit by 2, starting from the number's
>second-to-last digit. (please, bear with
>me until I will be able to get rid of
>scanf; for now, please, allow me to
>use it).
>
>I plan to try a few approaches. I think
>I am facing not only C programming issues
>here, but also issues connected with math.
>
>First approach involves arrays. The program
>doesn't do what I thought it should. I post
>my thoughts within comments.
>
>#include <stdio.h>
>#include <string.h>
>
>int main(void)
>{
> char card_number[16];
>
>/** limiting the number of possible inputs by
> 16, because it represents the longest card
> number
>**/
> int i, digit;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%16s", card_number) == 1)
This allows too many characters. Since scanf will always add a
terminating '\0', width specification must be at least one less than
the size of the target.
> {
> for (i = (strlen(card_number)-1); i >= 0; i -= 1)
> {
> digit = card_number[i] * 2;
You have lost sight of the difference between a character digit and an
integer digit. If card_number[i] is '2' (the character), then the
result of this arithmetic is not 4 (the integer) and not '4' (the
character) but 'd' which is not an integer or character digit.
> printf ("%i", digit);
> }
> }
>/** I have tried to achieve the following:
> take the last i-th character of the array
> and subtract 1 character; this will be
> a starting point, i.e. i = (strlen(card_number)-1);
>
> multiply that character by 2 and store the number
> in variable 'digit'; print that number; start the next
> loop with the array that has 2 digits less comparing to
> the initial array; do until i = 0.
> for example:
> 4 5 6 7
> strlen = 4, card_number[4] = 7
>
> i = (strlen(card_number)-1) will be 6, i.e.
> card_number[3] = 6
NO! card_number[3] = '6' which is a completely different value.
> 6 * 2 = 12
> print 12
>
> next iteration of the loop starts from
> digit 5 (because the first loop ended by
> i = i - 1, hence at 5, which is on the 3d
> position of the array); subtracts 1, and
> multiplies 4 by 2.
>
> This intention isn't realized. I don't see why.
>**/
>
> printf ("\n");
> return 0;
>}
>Thank you!
--
Remove del for email
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 01:08 -0700 |
| Message-ID | <1e5f8717-847a-451c-8e50-7e87115ead51@googlegroups.com> |
| In reply to | #69828 |
Thank you very much for these explanations.
I have revised the program based on your
explanations and suggestions.
Bartekltg, yes, I understand (now) what
happens when '0' is being subtracted :)
Given '0' equals 48, by subtracting '0'
from any given character I get the correct
digit (integer, not an ascii character).
#include <stdio.h>
#include <string.h>
int main(void)
{
char card_number[17];
int i, number;
printf ("Please, enter your card number: \n");
if (scanf ("%s", card_number) == 1)
{
for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
{
number = (card_number[i]-'0') * 2;
printf (" [%i] ", number);
}
}
printf ("\n");
return 0;
}
[toc] | [prev] | [next] | [standalone]
| From | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-09-08 09:04 -0700 |
| Message-ID | <lnlhcgsxs9.fsf@kst-u.example.com> |
| In reply to | #69876 |
Alla _ <modelling.data@gmail.com> writes:
> Thank you very much for these explanations.
>
> I have revised the program based on your explanations and suggestions.
>
> Bartekltg, yes, I understand (now) what happens when '0' is being
> subtracted :) Given '0' equals 48, by subtracting '0' from any given
> character I get the correct digit (integer, not an ascii character).
'0' is equal to 48 only if you're using an ASCII-based character
set, which the standard doesn't guarantee. For example, EBCDIC
assigns the value 240 to the character '0'.
*However* the C standard guarantees that the character codes for
the digits '0' through '9' have consecutive codes, so subtracting
'0' from a digit *is* give you the value ('9' - '0' == 9 for any
conforming implementation, even if '0' != 48).
Keep in mind that there's no such guarantee for letters; 'z' -
'a' == 25 in ASCII but not in EBCDIC.
[...]
> for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> {
> number = (card_number[i]-'0') * 2;
> printf (" [%i] ", number);
> }
[...]
This evaluates strlen(card_number) each time through the loop, which is
inefficient. The strlen() function has to scan the entire string to
find the terminating '\0', which can turn an O(N) loop into an O(N**2)
loop. You probably won't notice the difference for reasonably short
strings, and micro-optimization is *usually* less important than
clarity, but for something like this, it's worth it to save the length
in a variable:
size_t len = strlen(card_number);
for (i = len - 2, ...)
--
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 | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-10 01:22 -0700 |
| Message-ID | <061a430f-e33f-4661-a8c5-506bf106c590@googlegroups.com> |
| In reply to | #69922 |
> This evaluates strlen(card_number) each time through the loop, which is > inefficient. The strlen() function has to scan the entire string to > find the terminating '\0', which can turn an O(N) loop into an O(N**2) > loop. You probably won't notice the difference for reasonably short > strings, and micro-optimization is *usually* less important than > clarity, but for something like this, it's worth it to save the length > in a variable: > > size_t len = strlen(card_number); > for (i = len - 2, ...) > Keith, thank you very much. I have revised parts with strlen. I guess I see the difference; please, correct me if I am wrong: if I declare the length outside the loop, the program will only once scan through the whole card number to find '\0' and will compute the length of the card number only once, then will store that length in the variable 'len'; hence when further with each iteration of the loop the program will have to deal only with that defined number, and will not have to scan through the entire card_number again and again. > -- > 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 | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-09-10 09:38 +0100 |
| Message-ID | <MjbIx.485700$8E7.431470@fx29.am4> |
| In reply to | #70133 |
On 10/09/2015 09:22, Alla _ wrote:
>
>> This evaluates strlen(card_number) each time through the loop,
No, it doesn't. Keith is wrong. That doesn't happen very often, but it
happened this time.
>> which is
>> inefficient. The strlen() function has to scan the entire string to
>> find the terminating '\0',
True.
>> which can turn an O(N) loop into an O(N**2)
>> loop.
Not if the strlen is in the x part of for(x;y;z) which, on this
occasion, it was.
> Keith, thank you very much. I have revised
> parts with strlen. I guess I see the difference;
That's interesting, because he's wrong. Here's why:
In this loop:
for(x; y; z)
{
the_loop_body;
}
x is only executed once, at the beginning. y, z, and the_loop_body are
executed once *per loop iteration*. If your strlen call had been in any
of those places, Keith would have been perfectly correct. So the lesson
is still worth learning, even if on this occasion Keith very slightly
mis-read your code.
> please, correct me if I am wrong: if I declare
> the length outside the loop, the program will only
> once scan through the whole card number to find '\0'
> and will compute the length of the card number only once,
> then will store that length in the variable 'len'; hence
> when further with each iteration of the loop the program
> will have to deal only with that defined number, and will
> not have to scan through the entire card_number again and
> again.
That's the basic idea, yes, and that would have been true with your code
if you'd written something like:
for(i = 0; i < strlen(s) - 2; i += 2)
<-x-> <----y----------> <--z-->
strlen(s) is in the 'y' part. That's the kind of thing Keith was talking
about. Note the difference between it and your own code, which was
roughly this:
for (i = (strlen(s) - 2); i >= 0; i -= 2)
<----- x --------> <--y--> <--z-->
In your code, strlen() is in the 'x' part, so moving it above the loop
has no effect on performance.
--
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 | Eric Sosman <esosman@comcast-dot-net.invalid> |
|---|---|
| Date | 2015-09-10 07:34 -0400 |
| Message-ID | <msrpot$1rm$1@dont-email.me> |
| In reply to | #70137 |
On 9/10/2015 4:38 AM, Richard Heathfield wrote:
> [...]
> In this loop:
>
> for(x; y; z)
> {
> the_loop_body;
> }
>
> x is only executed once, at the beginning. y, z, and the_loop_body are
> executed once *per loop iteration*. [...]
Richard isn't wrong very often, but he's wrong this time.
x is executed once; Richard is right.
y is executed either (1) the same number of times as
the_loop_body or (2) one more time than the_loop_body.
z is executed either (2) the same number of times as
the_loop_body or (1) one fewer time than the_loop_body.
Case (2) might be considered the "normal" case, when
the loop terminates by the action of the `for' part alone.
In this case, y precedes and z follows each the_loop_body
execution, and y executes one additional time (when it
evaluates to false and stops the loop).
Case (1) holds when the_loop_body itself terminates the
loop, by executing a `break' or `return' or `goto' or the
like. In this case, y precedes each the_loop_body execution
and z follows each one except the last.
Caveat: All the above presumes that none of x,y,z, or
the_loop_body invokes undefined behavior, in which case
there's no telling what might happen.
--
esosman@comcast-dot-net.invalid
"Don't be afraid of work. Make work afraid of you." -- TLM
[toc] | [prev] | [next] | [standalone]
| From | David Brown <david.brown@hesbynett.no> |
|---|---|
| Date | 2015-09-10 13:47 +0200 |
| Message-ID | <msrqha$4kq$1@dont-email.me> |
| In reply to | #70150 |
On 10/09/15 13:34, Eric Sosman wrote:
> On 9/10/2015 4:38 AM, Richard Heathfield wrote:
>> [...]
>> In this loop:
>>
>> for(x; y; z)
>> {
>> the_loop_body;
>> }
>>
>> x is only executed once, at the beginning. y, z, and the_loop_body are
>> executed once *per loop iteration*. [...]
>
> Richard isn't wrong very often, but he's wrong this time.
>
> x is executed once; Richard is right.
>
> y is executed either (1) the same number of times as
> the_loop_body or (2) one more time than the_loop_body.
>
> z is executed either (2) the same number of times as
> the_loop_body or (1) one fewer time than the_loop_body.
>
> Case (2) might be considered the "normal" case, when
> the loop terminates by the action of the `for' part alone.
> In this case, y precedes and z follows each the_loop_body
> execution, and y executes one additional time (when it
> evaluates to false and stops the loop).
>
> Case (1) holds when the_loop_body itself terminates the
> loop, by executing a `break' or `return' or `goto' or the
> like. In this case, y precedes each the_loop_body execution
> and z follows each one except the last.
>
> Caveat: All the above presumes that none of x,y,z, or
> the_loop_body invokes undefined behavior, in which case
> there's no telling what might happen.
>
You're all wrong! For a compiler with reasonable optimisation, the
compiler will see that the strlen() call is invariant in the loop, and
lift it outside - it will be executed only once no matter where in the
x, y, z it is given.
/Logically/ you are correct - but if you are trying to measure the
generated behaviour, write fast code, or examine the assembly code, it's
worth remembering the compiler's ability to shuffle things around and
give you fast, efficient object code even though you wrote slow,
inefficient source code.
Richard's approximation (x is done once, while y and z are done once per
iteration) is probably good enough for most purposes. And moving the
strlen() call outside the loop makes sense even if the compiler is smart
enough to do so automatically - compilers don't always manage such
optimisations.
[toc] | [prev] | [next] | [standalone]
| From | Richard Heathfield <rjh@cpax.org.uk> |
|---|---|
| Date | 2015-09-10 13:11 +0100 |
| Message-ID | <OreIx.33502$xw.15873@fx22.am4> |
| In reply to | #70151 |
On 10/09/2015 12:47, David Brown wrote:
> On 10/09/15 13:34, Eric Sosman wrote:
>> On 9/10/2015 4:38 AM, Richard Heathfield wrote:
>>> [...]
>>> In this loop:
>>>
>>> for(x; y; z)
>>> {
>>> the_loop_body;
>>> }
>>>
>>> x is only executed once, at the beginning. y, z, and the_loop_body are
>>> executed once *per loop iteration*. [...]
>>
>> Richard isn't wrong very often,
You'd be surprised.
>> but he's wrong this time.
>>
<snip>
>
> You're all wrong! For a compiler with reasonable optimisation, the
> compiler will see that the strlen() call is invariant in the loop, and
> lift it outside - it will be executed only once no matter where in the
> x, y, z it is given.
You are, of course, wrong. If the loop body contains f(s), this could
stop the strlen call from being invariant. And the compiler may not even
be able to see the code of f() to determine whether or not that is the
case. And in any case, from the OP's point of view, the whole shooting
match is irrelevant because the strlen is in x, not y, z, or loop_body.
(Eric is also wrong because nobody in their right mind would put a goto,
a break (except as part of an inner switch), or a return into a loop body.)
> /Logically/ you are correct - but if you are trying to measure the
> generated behaviour, write fast code, or examine the assembly code, it's
> worth remembering the compiler's ability to shuffle things around and
> give you fast, efficient object code even though you wrote slow,
> inefficient source code.
>
> Richard's approximation (x is done once, while y and z are done once per
> iteration) is probably good enough for most purposes. And moving the
> strlen() call outside the loop makes sense even if the compiler is smart
> enough to do so automatically - compilers don't always manage such
> optimisations.
All good stuff, but you're not going to win any friends telling people
they're right. :-)
Anyway, I think Keith should have the last word on this little fracas -
if there is any justice, he'll find a way of telling us we're *all* wrong.
--
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 | Keith Thompson <kst-u@mib.org> |
|---|---|
| Date | 2015-09-10 10:21 -0700 |
| Message-ID | <lnmvwunqah.fsf@kst-u.example.com> |
| In reply to | #70137 |
Richard Heathfield <rjh@cpax.org.uk> writes:
> On 10/09/2015 09:22, Alla _ wrote:
>>
>>> This evaluates strlen(card_number) each time through the loop,
>
> No, it doesn't. Keith is wrong. That doesn't happen very often, but it
> happened this time.
[...]
>> Keith, thank you very much. I have revised
>> parts with strlen. I guess I see the difference;
>
> That's interesting, because he's wrong. Here's why:
>
> In this loop:
>
> for(x; y; z)
> {
> the_loop_body;
> }
>
> x is only executed once, at the beginning. y, z, and the_loop_body are
> executed once *per loop iteration*. If your strlen call had been in any
> of those places, Keith would have been perfectly correct. So the lesson
> is still worth learning, even if on this occasion Keith very slightly
> mis-read your code.
Oh, crud. Richard, you are of course absolutely correct. Alla, sorry
about the confusion.
--
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 | Geoff <geoff@invalid.invalid> |
|---|---|
| Date | 2015-09-10 10:42 -0700 |
| Message-ID | <1qd3vat1tdajkber6imo67ilb2q7e0u8h2@4ax.com> |
| In reply to | #70133 |
On Thu, 10 Sep 2015 01:22:29 -0700 (PDT), Alla _
<modelling.data@gmail.com> wrote:
>Keith, thank you very much. I have revised
>parts with strlen. I guess I see the difference;
>please, correct me if I am wrong: if I declare
>the length outside the loop, the program will only
>once scan through the whole card number to find '\0'
>and will compute the length of the card number only once,
>then will store that length in the variable 'len'; hence
>when further with each iteration of the loop the program
>will have to deal only with that defined number, and will
>not have to scan through the entire card_number again and
>again.
Alla _,
There is absolutely no difference in the performance of this loop
whether it's written
for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
{
number = (card_number[i]-'0') * 2;
printf (" [%i] ", number);
}
or as
size_t len = strlen(card_number);
for (i = len - 2, ; i >= 0; i -= 2)
{
number = (card_number[i]-'0') * 2;
printf (" [%i] ", number);
}
The only variables that will be modified as the loop executes will be
i and number.
In both cases, strlen(card_number) - 2 is evaluated EXACTLY ONCE at
the beginning of the loop to initialize i, then i, and only i, is
modified to index through the card_number array.
Your original version is preferable. It's shorter, clearer, cleaner
and is written in the fashion of 99% of for() loops of this nature
because it saves the declaration of another variable that is only used
once and ignored thereafter.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 01:11 -0700 |
| Message-ID | <326d1e2b-aeca-4e1b-8843-76bbb46d7466@googlegroups.com> |
| In reply to | #69828 |
May I continue asking questions about other parts of this program as I include them? Or shall I start a new thread? I do not know if there are any restrictions and rules regarding such issues. Thank you!
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-08 09:51 +0100 |
| Message-ID | <8737yppa3s.fsf@bsb.me.uk> |
| In reply to | #69877 |
Alla _ <modelling.data@gmail.com> writes: > May I continue asking questions about > other parts of this program as I include > them? Or shall I start a new thread? I do > not know if there are any restrictions > and rules regarding such issues. > Thank you! I don't think it makes very much difference. Posting in the same thread makes it easier to find other versions of the program but that probably won't matter in this case as the program is short and you can post is all when asking new questions. Basically, take your pick. No one will mind. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 02:39 -0700 |
| Message-ID | <1c74da61-5dfb-4342-ac6a-eb9675e61c33@googlegroups.com> |
| In reply to | #69879 |
On Tuesday, September 8, 2015 at 12:51:43 PM UTC+4, Ben Bacarisse wrote: > Alla _ <modelling.data@gmail.com> writes: > > > May I continue asking questions about > > other parts of this program as I include > > them? Or shall I start a new thread? I do > > not know if there are any restrictions > > and rules regarding such issues. > > Thank you! > > I don't think it makes very much difference. Posting in the same thread > makes it easier to find other versions of the program but that probably > won't matter in this case as the program is short and you can post is > all when asking new questions. > > Basically, take your pick. No one will mind. > > -- > Ben. Thank you!
[toc] | [prev] | [standalone]
Back to top | Article view | comp.lang.c
csiph-web