Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.lang.c > #69887 > unrolled thread
| Started by | Alla _ <modelling.data@gmail.com> |
|---|---|
| First post | 2015-09-08 04:13 -0700 |
| Last post | 2015-09-11 14:19 +0100 |
| Articles | 20 on this page of 51 — 11 participants |
Back to article view | Back to comp.lang.c
A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-08 04:13 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-08 04:19 -0700
Re: A finalized program fir <profesor.fir@gmail.com> - 2015-09-08 04:30 -0700
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-08 14:45 +0100
Re: A finalized program Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-09-08 08:29 -0700
Re: A finalized program Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-09-08 08:52 -0700
Re: A finalized program Martin Shobe <martin.shobe@yahoo.com> - 2015-09-08 13:01 -0500
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-08 21:00 +0100
Re: A finalized program Malcolm McLean <malcolm.mclean5@btinternet.com> - 2015-09-08 13:33 -0700
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-09 00:28 +0100
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-08 14:26 +0100
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-08 06:42 -0700
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-08 20:50 +0100
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 01:47 -0700
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-08 13:41 +0000
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-10 01:31 -0700
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-10 10:39 +0000
Re: A finalized program David Thompson <dave.thompson2@verizon.net> - 2015-09-20 18:35 -0400
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-10 01:33 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-10 10:16 -0700
Re: A finalized program bartekltg <bartekltg@gmail.com> - 2015-09-10 20:08 +0200
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:05 -0700
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-11 10:17 +0100
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-11 10:19 +0100
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:28 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:29 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:19 -0700
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-11 10:23 +0100
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:33 -0700
Re: A finalized program Keith Thompson <kst-u@mib.org> - 2015-09-11 14:11 -0700
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-11 21:39 +0000
Re: A finalized program bartekltg <bartekltg@gmail.com> - 2015-09-11 12:49 +0200
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-10 23:31 +0100
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:15 -0700
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-10 22:37 +0000
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-10 23:47 +0100
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-11 10:18 +0000
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 01:07 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 02:14 -0700
Re: A finalized program jt@toerring.de (Jens Thoms Toerring) - 2015-09-11 10:10 +0000
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 04:19 -0700
Re: A finalized program Barry Schwarz <schwarzb@dqel.com> - 2015-09-08 15:53 -0700
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 04:27 -0700
Re: A finalized program bartekltg <bartekltg@gmail.com> - 2015-09-11 14:05 +0200
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 04:42 -0700
Re: A finalized program bartekltg <bartekltg@gmail.com> - 2015-09-11 14:15 +0200
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 05:50 -0700
Re: A finalized program bartekltg <bartekltg@gmail.com> - 2015-09-11 15:00 +0200
Re: A finalized program Alla _ <modelling.data@gmail.com> - 2015-09-11 05:50 -0700
Re: A finalized program Ben Bacarisse <ben.usenet@bsb.me.uk> - 2015-09-11 13:46 +0100
Re: A finalized program Richard Heathfield <rjh@cpax.org.uk> - 2015-09-11 14:19 +0100
Page 1 of 3 [1] 2 3 Next page →
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 04:13 -0700 |
| Subject | A finalized program |
| Message-ID | <d93ca264-e41a-4f82-8c09-cd87731b2eed@googlegroups.com> |
Hello!
First of all, I want to say that I can't
believe that I did "cobbled together" a
program, which I consider to be a difficult
one for someone like me. I am very thankful
for everyone who has helped me with all previous
programs and with the beginning part of this
program: if not your help, I wouldn't make such
progress, seriously.
Here is the program. Of course, I would love
to see your comments and suggestions, as well
as any nitpicking; any would be of a great
help. But, please, remember that I am at the
initial stage, hence I can understand only
basics for now :)
Also, of course, I have to revise this
program to add functions, but this topic
is still nebulous to me.
The task was to:
1) Get the card number from the user.
2) Multiply every other digit by 2,
starting with the number's second-to-last digit,
and then add those products' digits together.
3) Add the sum to the sum of the digits that
weren't multiplied by 2.
4) If the total's last digit is 0 (or, put more
formally, if the total modulo 10 is congruent to
0), the number is valid.
5) If the card is valid, print that it's a valid
card and the name of the issuer.
I version:
#include <stdio.h>
#include <string.h>
int main(void)
{
char card_number[17];
int i, number, digit, sum;
int sum1 = 0, sum2 = 0, sum3 = 0;
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;
if (number >= 0 && number <= 9)
{
sum1 += number;
}
if (number > 9)
{
while (number > 0)
{
digit = number % 10;
sum2 += digit;
number /= 10;
}
}
}
for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
{
sum3 += (card_number[i] - '0');
}
sum = sum1 + sum2 + sum3;
if (sum % 10 == 0)
{
if (strlen(card_number) == 15)
printf ("It's a valid AMEX\n");
else if (strlen(card_number) == 16)
printf ("It's a valid MASTERCARD or VISA\n");
else if (strlen(card_number) == 13)
printf ("It's a valid VISA\n");
else
printf ("Card of an unknown card issuer\n");
}
else
printf ("Sorry, the card number failed the test\n");
}
printf ("\n");
return 0;
}
II version with switch statement at the end (though
switch statement doesn't completely serve the purpose):
#include <stdio.h>
#include <string.h>
int main(void)
{
char card_number[17];
int i, number, digit, sum;
int sum1 = 0, sum2 = 0, sum3 = 0;
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;
if (number >= 0 && number <= 9)
{
sum1 += number;
}
if (number > 9)
{
while (number > 0)
{
digit = number % 10;
sum2 += digit;
number /= 10;
}
}
}
for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
{
sum3 += (card_number[i] - '0');
}
sum = sum1 + sum2 + sum3;
if (sum % 10 == 0)
{
switch (strlen(card_number))
{
case 15:
printf ("It's a valid AMEX\n");
break;
case 16:
printf ("It's a valid MASTERCARD or VISA\n");
break;
case 13:
printf ("It's a valid VISA\n");
break;
default:
break;
}
}
else
printf ("Sorry, the card number failed the test\n");
}
printf ("\n");
return 0;
}
[toc] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 04:19 -0700 |
| Message-ID | <0b40a48e-3d88-46dd-adf2-275a33a87f65@googlegroups.com> |
| In reply to | #69887 |
On Tuesday, September 8, 2015 at 3:13:57 PM UTC+4, Alla _ wrote:
> Hello!
>
> First of all, I want to say that I can't
> believe that I did "cobbled together" a
> program, which I consider to be a difficult
> one for someone like me. I am very thankful
> for everyone who has helped me with all previous
> programs and with the beginning part of this
> program: if not your help, I wouldn't make such
> progress, seriously.
>
> Here is the program. Of course, I would love
> to see your comments and suggestions, as well
> as any nitpicking; any would be of a great
> help. But, please, remember that I am at the
> initial stage, hence I can understand only
> basics for now :)
>
> Also, of course, I have to revise this
> program to add functions, but this topic
> is still nebulous to me.
>
> The task was to:
> 1) Get the card number from the user.
>
> 2) Multiply every other digit by 2,
> starting with the number's second-to-last digit,
> and then add those products' digits together.
>
> 3) Add the sum to the sum of the digits that
> weren't multiplied by 2.
>
> 4) If the total's last digit is 0 (or, put more
> formally, if the total modulo 10 is congruent to
> 0), the number is valid.
>
> 5) If the card is valid, print that it's a valid
> card and the name of the issuer.
>
> I version:
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[17];
> int i, number, digit, sum;
> int sum1 = 0, sum2 = 0, sum3 = 0;
>
> 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;
>
> if (number >= 0 && number <= 9)
> {
> sum1 += number;
> }
>
> if (number > 9)
> {
> while (number > 0)
> {
> digit = number % 10;
> sum2 += digit;
> number /= 10;
> }
> }
> }
>
> for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> {
> sum3 += (card_number[i] - '0');
> }
>
> sum = sum1 + sum2 + sum3;
>
> if (sum % 10 == 0)
> {
> if (strlen(card_number) == 15)
> printf ("It's a valid AMEX\n");
>
> else if (strlen(card_number) == 16)
> printf ("It's a valid MASTERCARD or VISA\n");
>
> else if (strlen(card_number) == 13)
> printf ("It's a valid VISA\n");
>
> else
> printf ("Card of an unknown card issuer\n");
> }
>
> else
> printf ("Sorry, the card number failed the test\n");
> }
>
> printf ("\n");
> return 0;
> }
>
> II version with switch statement at the end (though
> switch statement doesn't completely serve the purpose):
>
> #include <stdio.h>
> #include <string.h>
>
> int main(void)
> {
> char card_number[17];
> int i, number, digit, sum;
> int sum1 = 0, sum2 = 0, sum3 = 0;
>
> 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;
>
> if (number >= 0 && number <= 9)
> {
> sum1 += number;
> }
>
> if (number > 9)
> {
> while (number > 0)
> {
> digit = number % 10;
> sum2 += digit;
> number /= 10;
> }
> }
> }
>
> for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> {
> sum3 += (card_number[i] - '0');
> }
>
> sum = sum1 + sum2 + sum3;
>
> if (sum % 10 == 0)
> {
> switch (strlen(card_number))
> {
> case 15:
> printf ("It's a valid AMEX\n");
> break;
> case 16:
> printf ("It's a valid MASTERCARD or VISA\n");
> break;
> case 13:
> printf ("It's a valid VISA\n");
> break;
> default:
> break;
> }
> }
>
> else
> printf ("Sorry, the card number failed the test\n");
> }
>
> printf ("\n");
> return 0;
> }
Although I've written this, I still think the
function strlen is not totally clear to me.
In for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
I subtract 2 from strlen(card_number) to start the loop
for the second digit from the end. I come up with this
minus 2 after a few tests, and this tells me that
strlen computes the number of characters from 0 to n, including;
therefore strlen should give the length that is 1 more than
the actual length of the string.
But both in switch and if statements, I use the exact
length of the string (not 17, if the actual length is 16)
to get the right answer. When I tested with strlen which
is n + 1, I got wrong answers.
What is the math behind strlen?
Thank you!
[toc] | [prev] | [next] | [standalone]
| From | fir <profesor.fir@gmail.com> |
|---|---|
| Date | 2015-09-08 04:30 -0700 |
| Message-ID | <8fa87e1d-ad37-4e22-9d64-f2209eefea8c@googlegroups.com> |
| In reply to | #69890 |
W dniu wtorek, 8 września 2015 13:19:42 UTC+2 użytkownik Alla _ napisał:
> On Tuesday, September 8, 2015 at 3:13:57 PM UTC+4, Alla _ wrote:
> > Hello!
> >
> > First of all, I want to say that I can't
> > believe that I did "cobbled together" a
> > program, which I consider to be a difficult
> > one for someone like me. I am very thankful
> > for everyone who has helped me with all previous
> > programs and with the beginning part of this
> > program: if not your help, I wouldn't make such
> > progress, seriously.
> >
> > Here is the program. Of course, I would love
> > to see your comments and suggestions, as well
> > as any nitpicking; any would be of a great
> > help. But, please, remember that I am at the
> > initial stage, hence I can understand only
> > basics for now :)
> >
> > Also, of course, I have to revise this
> > program to add functions, but this topic
> > is still nebulous to me.
> >
> > The task was to:
> > 1) Get the card number from the user.
> >
> > 2) Multiply every other digit by 2,
> > starting with the number's second-to-last digit,
> > and then add those products' digits together.
> >
> > 3) Add the sum to the sum of the digits that
> > weren't multiplied by 2.
> >
> > 4) If the total's last digit is 0 (or, put more
> > formally, if the total modulo 10 is congruent to
> > 0), the number is valid.
> >
> > 5) If the card is valid, print that it's a valid
> > card and the name of the issuer.
> >
> > I version:
> >
> > #include <stdio.h>
> > #include <string.h>
> >
> > int main(void)
> > {
> > char card_number[17];
> > int i, number, digit, sum;
> > int sum1 = 0, sum2 = 0, sum3 = 0;
> >
> > 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;
> >
> > if (number >= 0 && number <= 9)
> > {
> > sum1 += number;
> > }
> >
> > if (number > 9)
> > {
> > while (number > 0)
> > {
> > digit = number % 10;
> > sum2 += digit;
> > number /= 10;
> > }
> > }
> > }
> >
> > for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> > {
> > sum3 += (card_number[i] - '0');
> > }
> >
> > sum = sum1 + sum2 + sum3;
> >
> > if (sum % 10 == 0)
> > {
> > if (strlen(card_number) == 15)
> > printf ("It's a valid AMEX\n");
> >
> > else if (strlen(card_number) == 16)
> > printf ("It's a valid MASTERCARD or VISA\n");
> >
> > else if (strlen(card_number) == 13)
> > printf ("It's a valid VISA\n");
> >
> > else
> > printf ("Card of an unknown card issuer\n");
> > }
> >
> > else
> > printf ("Sorry, the card number failed the test\n");
> > }
> >
> > printf ("\n");
> > return 0;
> > }
> >
> > II version with switch statement at the end (though
> > switch statement doesn't completely serve the purpose):
> >
> > #include <stdio.h>
> > #include <string.h>
> >
> > int main(void)
> > {
> > char card_number[17];
> > int i, number, digit, sum;
> > int sum1 = 0, sum2 = 0, sum3 = 0;
> >
> > 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;
> >
> > if (number >= 0 && number <= 9)
> > {
> > sum1 += number;
> > }
> >
> > if (number > 9)
> > {
> > while (number > 0)
> > {
> > digit = number % 10;
> > sum2 += digit;
> > number /= 10;
> > }
> > }
> > }
> >
> > for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> > {
> > sum3 += (card_number[i] - '0');
> > }
> >
> > sum = sum1 + sum2 + sum3;
> >
> > if (sum % 10 == 0)
> > {
> > switch (strlen(card_number))
> > {
> > case 15:
> > printf ("It's a valid AMEX\n");
> > break;
> > case 16:
> > printf ("It's a valid MASTERCARD or VISA\n");
> > break;
> > case 13:
> > printf ("It's a valid VISA\n");
> > break;
> > default:
> > break;
> > }
> > }
> >
> > else
> > printf ("Sorry, the card number failed the test\n");
> > }
> >
> > printf ("\n");
> > return 0;
> > }
>
> Although I've written this, I still think the
> function strlen is not totally clear to me.
>
> In for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> I subtract 2 from strlen(card_number) to start the loop
> for the second digit from the end. I come up with this
> minus 2 after a few tests, and this tells me that
> strlen computes the number of characters from 0 to n, including;
> therefore strlen should give the length that is 1 more than
> the actual length of the string.
>
> But both in switch and if statements, I use the exact
> length of the string (not 17, if the actual length is 16)
> to get the right answer. When I tested with strlen which
> is n + 1, I got wrong answers.
>
> What is the math behind strlen?
> Thank you!
strlen gives you a number of letters in a string for example strlen("fir") gives 3
so if this loop goes on some string like
"loop goes" it will go thru 'e' 'g' p' 'o' (as strings indexing starts form zero)
(i was not lookin the code answering only on loop and strlen)
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-08 14:45 +0100 |
| Message-ID | <87r3m9nhwp.fsf@bsb.me.uk> |
| In reply to | #69890 |
Alla _ <modelling.data@gmail.com> writes:
> On Tuesday, September 8, 2015 at 3:13:57 PM UTC+4, Alla _ wrote:
>> Hello!
>>
>> First of all, I want to say that I can't
>> believe that I did "cobbled together" a
>> program, which I consider to be a difficult
>> one for someone like me. I am very thankful
>> for everyone who has helped me with all previous
>> programs and with the beginning part of this
>> program: if not your help, I wouldn't make such
>> progress, seriously.
>>
>> Here is the program. Of course, I would love
>> to see your comments and suggestions, as well
>> as any nitpicking; any would be of a great
>> help. But, please, remember that I am at the
>> initial stage, hence I can understand only
>> basics for now :)
>>
>> Also, of course, I have to revise this
>> program to add functions, but this topic
>> is still nebulous to me.
>>
>> The task was to:
>> 1) Get the card number from the user.
>>
>> 2) Multiply every other digit by 2,
>> starting with the number's second-to-last digit,
>> and then add those products' digits together.
>>
>> 3) Add the sum to the sum of the digits that
>> weren't multiplied by 2.
>>
>> 4) If the total's last digit is 0 (or, put more
>> formally, if the total modulo 10 is congruent to
>> 0), the number is valid.
>>
>> 5) If the card is valid, print that it's a valid
>> card and the name of the issuer.
>>
>> I version:
>>
>> #include <stdio.h>
>> #include <string.h>
>>
>> int main(void)
>> {
>> char card_number[17];
>> int i, number, digit, sum;
>> int sum1 = 0, sum2 = 0, sum3 = 0;
>>
>> 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;
>>
>> if (number >= 0 && number <= 9)
>> {
>> sum1 += number;
>> }
>>
>> if (number > 9)
>> {
>> while (number > 0)
>> {
>> digit = number % 10;
>> sum2 += digit;
>> number /= 10;
>> }
>> }
>> }
>>
>> for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
>> {
>> sum3 += (card_number[i] - '0');
>> }
>>
>> sum = sum1 + sum2 + sum3;
>>
>> if (sum % 10 == 0)
>> {
>> if (strlen(card_number) == 15)
>> printf ("It's a valid AMEX\n");
>>
>> else if (strlen(card_number) == 16)
>> printf ("It's a valid MASTERCARD or VISA\n");
>>
>> else if (strlen(card_number) == 13)
>> printf ("It's a valid VISA\n");
>>
>> else
>> printf ("Card of an unknown card issuer\n");
>> }
>>
>> else
>> printf ("Sorry, the card number failed the test\n");
>> }
>>
>> printf ("\n");
>> return 0;
>> }
>>
>> II version with switch statement at the end (though
>> switch statement doesn't completely serve the purpose):
>>
>> #include <stdio.h>
>> #include <string.h>
>>
>> int main(void)
>> {
>> char card_number[17];
>> int i, number, digit, sum;
>> int sum1 = 0, sum2 = 0, sum3 = 0;
>>
>> 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;
>>
>> if (number >= 0 && number <= 9)
>> {
>> sum1 += number;
>> }
>>
>> if (number > 9)
>> {
>> while (number > 0)
>> {
>> digit = number % 10;
>> sum2 += digit;
>> number /= 10;
>> }
>> }
>> }
>>
>> for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
>> {
>> sum3 += (card_number[i] - '0');
>> }
>>
>> sum = sum1 + sum2 + sum3;
>>
>> if (sum % 10 == 0)
>> {
>> switch (strlen(card_number))
>> {
>> case 15:
>> printf ("It's a valid AMEX\n");
>> break;
>> case 16:
>> printf ("It's a valid MASTERCARD or VISA\n");
>> break;
>> case 13:
>> printf ("It's a valid VISA\n");
>> break;
>> default:
>> break;
>> }
>> }
>>
>> else
>> printf ("Sorry, the card number failed the test\n");
>> }
>>
>> printf ("\n");
>> return 0;
>> }
>
> Although I've written this, I still think the
> function strlen is not totally clear to me.
That's not surprising because it brings up oe the most surprising things
about C (though not directly related to your question below).
> In for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> I subtract 2 from strlen(card_number) to start the loop
> for the second digit from the end. I come up with this
> minus 2 after a few tests, and this tells me that
> strlen computes the number of characters from 0 to n, including;
> therefore strlen should give the length that is 1 more than
> the actual length of the string.
The user enters 16 digits: 0123456789012345. strlen will report 16 --
the actual length. These 16 characters are indexed from 0 to 15
inclusive so to get the first you use card_number[0] and to get the last
card_number[15]. The last-but-one is card_number[14] -- that's
strlen(card_number) - 2.
> But both in switch and if statements, I use the exact
> length of the string (not 17, if the actual length is 16)
> to get the right answer. When I tested with strlen which
> is n + 1, I got wrong answers.
>
> What is the math behind strlen?
I think you just forgot that arrays start at 0 so the characters in a
string run from s[0] to s[len - 1].
But there is a problem with the way you use strlen. It's a function
that returns an unsigned value -- not an int (specifically a value of
type size_t used in C to represent sizes of things). When you do
arithmetic on unsigned types you can't get a signed result[1]. What
happens is that the value wraps round modulo one more than the largest
value that can be stored. (If you know how machines represent numbers
you'll see that this is the "natural" thing to do.) As a result, if
strlen returns a number less than 2, your subtraction will produce a
very large number indeed. Now you may wonder why you program does not
then go haywire trying to get at millions of non-existent elements of
the card_number array? Well, it's because you put the number back into
an int variable (i). On most systems that converts the very large
number back into a small negative one (exactly the one you expect in
most cases).
You may ask why is the a problem then? Well the C language allows
implementations to raise an error when that conversion back to int is
done. You probably wont find such a machine where this actually happens
but its better to write code that will work everywhere.
[1] That's not always strictly true, but you really don't care about the
details.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-09-08 08:29 -0700 |
| Message-ID | <31527bc2-2d86-4636-bff3-c497d0f6b2f0@googlegroups.com> |
| In reply to | #69903 |
On Tuesday, September 8, 2015 at 2:46:10 PM UTC+1, Ben Bacarisse wrote: > > But there is a problem with the way you use strlen. It's a function > that returns an unsigned value -- not an int (specifically a value of > type size_t used in C to represent sizes of things). When you do > arithmetic on unsigned types you can't get a signed result[1]. What > happens is that the value wraps round modulo one more than the largest > value that can be stored. (If you know how machines represent numbers > you'll see that this is the "natural" thing to do.) As a result, if > strlen returns a number less than 2, your subtraction will produce a > very large number indeed. Now you may wonder why you program does not > then go haywire trying to get at millions of non-existent elements of > the card_number array? Well, it's because you put the number back into > an int variable (i). On most systems that converts the very large > number back into a small negative one (exactly the one you expect in > most cases). > > You may ask why is the a problem then? Well the C language allows > implementations to raise an error when that conversion back to int is > done. You probably wont find such a machine where this actually happens > but its better to write code that will work everywhere. > And I get criticised for disapproving of size_t.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-09-08 08:52 -0700 |
| Message-ID | <4371016b-309f-4f89-9b94-91088121f113@googlegroups.com> |
| In reply to | #69903 |
On Tuesday, September 8, 2015 at 2:46:10 PM UTC+1, Ben Bacarisse wrote:
>
> But there is a problem with the way you use strlen. It's a function
> that returns an unsigned value -- not an int (specifically a value of
> type size_t used in C to represent sizes of things).
>
If you want another demonstration of the evils of size_t, here's some code I'm
working on literally this minute.
it's an undo / redo buffer with a "track" from the root, which was the document
as created, to the current tip. There's also a "head" which shows where the
next change will be inserted.
So it's very simple boilerplate code, unfortunately C++.
std::vector <Node *> getCurrentTrack(int *aHeadIndex) const
{
Node *node = mRoot;
std::vector <Node *> answer;
*aHeadIndex = -1;
while(node)
{
answer.push_back(node);
if(node == mHead)
*aHeadIndex = (int) answer.size() -1;
node = node->next;
}
return answer;
}
But if the index is a size_t, and the track is empty, what are we supposed to set
aHeadIndex to? Or if the head isn't on the track (shouldn't happen, but maybe
if the system is extended, you'll have "detached heads" as in git).
[toc] | [prev] | [next] | [standalone]
| From | Martin Shobe <martin.shobe@yahoo.com> |
|---|---|
| Date | 2015-09-08 13:01 -0500 |
| Message-ID | <msn7m2$cga$1@dont-email.me> |
| In reply to | #69920 |
On 9/8/2015 10:52 AM, Malcolm McLean wrote:
> On Tuesday, September 8, 2015 at 2:46:10 PM UTC+1, Ben Bacarisse wrote:
>>
>> But there is a problem with the way you use strlen. It's a function
>> that returns an unsigned value -- not an int (specifically a value of
>> type size_t used in C to represent sizes of things).
>>
> If you want another demonstration of the evils of size_t, here's some code I'm
> working on literally this minute.
>
> it's an undo / redo buffer with a "track" from the root, which was the document
> as created, to the current tip. There's also a "head" which shows where the
> next change will be inserted.
> So it's very simple boilerplate code, unfortunately C++.
>
> std::vector <Node *> getCurrentTrack(int *aHeadIndex) const
> {
> Node *node = mRoot;
> std::vector <Node *> answer;
> *aHeadIndex = -1;
> while(node)
> {
> answer.push_back(node);
> if(node == mHead)
> *aHeadIndex = (int) answer.size() -1;
> node = node->next;
> }
> return answer;
> }
>
> But if the index is a size_t, and the track is empty, what are we supposed to set
> aHeadIndex to? Or if the head isn't on the track (shouldn't happen, but maybe
> if the system is extended, you'll have "detached heads" as in git).
>
It's a common enough practice to reserve the largest value that a
variable of size_t can store for such purposes. Another possibility is
one past the end (similar to how C++ already uses iterators to signal
not found in the library). Signed types have a similar (though less
common) issue for offsets from the middle.
From what little I can see, I'd be tempted to encapsulate the index and
the vector into a single class so the users don't need to worry about
how that information was encoded.
Martin Shobe
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-08 21:00 +0100 |
| Message-ID | <874mj4of4e.fsf@bsb.me.uk> |
| In reply to | #69920 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes:
> On Tuesday, September 8, 2015 at 2:46:10 PM UTC+1, Ben Bacarisse wrote:
>>
>> But there is a problem with the way you use strlen. It's a function
>> that returns an unsigned value -- not an int (specifically a value of
>> type size_t used in C to represent sizes of things).
>>
> If you want another demonstration of the evils of size_t, here's some
> code I'm working on literally this minute.
>
> it's an undo / redo buffer with a "track" from the root, which was the
> document as created, to the current tip. There's also a "head" which
> shows where the next change will be inserted. So it's very simple
> boilerplate code, unfortunately C++.
>
> std::vector <Node *> getCurrentTrack(int *aHeadIndex) const
> {
> Node *node = mRoot;
> std::vector <Node *> answer;
> *aHeadIndex = -1;
> while(node)
> {
> answer.push_back(node);
> if(node == mHead)
> *aHeadIndex = (int) answer.size() -1;
> node = node->next;
> }
> return answer;
> }
>
> But if the index is a size_t, and the track is empty, what are we
> supposed to set aHeadIndex to?
But the index isn't a size_t -- someone (you?) chose int because you
want to use -1 as a special value. If you want the index to be a size_t
the design has to change. Set it to the final answer.size() (which is
guaranteed to be invalid) or, indeed, set it to (size_t)-1. What value
denotes "no head index" is part of the contract with the caller so the
designer chooses. You could even use the style of the standard
containers ans use an iterator.
> Or if the head isn't on the track
> (shouldn't happen, but maybe if the system is extended, you'll have
> "detached heads" as in git).
I don't follow this.
--
Ben.
[toc] | [prev] | [next] | [standalone]
| From | Malcolm McLean <malcolm.mclean5@btinternet.com> |
|---|---|
| Date | 2015-09-08 13:33 -0700 |
| Message-ID | <58f9484c-29fd-4f88-991b-2539f56fe9ca@googlegroups.com> |
| In reply to | #69968 |
On Tuesday, September 8, 2015 at 9:00:56 PM UTC+1, Ben Bacarisse wrote: > Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > > > Or if the head isn't on the track > > (shouldn't happen, but maybe if the system is extended, you'll have > > "detached heads" as in git). > > I don't follow this. > As you undo and redo you create a branching tree of versions. But there's a concept of the "active tip", which is what the track is about - it's a list of versions from the root to the active tip. The "head" is the insertion point, which is usually at the active tip, unless the user has just executed an "undo". Then it's a step back. It follows that the head must always be on the "track", unless there is no data in the system at all. But that might not always hold, at some future date we may extend the system in a way that allows for heads that aren't on the current track.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-09 00:28 +0100 |
| Message-ID | <87r3m8mqy4.fsf@bsb.me.uk> |
| In reply to | #69972 |
Malcolm McLean <malcolm.mclean5@btinternet.com> writes: > On Tuesday, September 8, 2015 at 9:00:56 PM UTC+1, Ben Bacarisse wrote: >> Malcolm McLean <malcolm.mclean5@btinternet.com> writes: >> >> > Or if the head isn't on the track >> > (shouldn't happen, but maybe if the system is extended, you'll have >> > "detached heads" as in git). >> >> I don't follow this. >> > As you undo and redo you create a branching tree of versions. But > there's a concept of the "active tip", which is what the track is > about - it's a list of versions from the root to the active tip. > The "head" is the insertion point, which is usually at the active > tip, unless the user has just executed an "undo". Then it's a step > back. > It follows that the head must always be on the "track", unless there > is no data in the system at all. But that might not always hold, > at some future date we may extend the system in a way that allows > for heads that aren't on the current track. The bit I don't follow is what effect that has on what I said before. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-08 14:26 +0100 |
| Message-ID | <87wpw1nitg.fsf@bsb.me.uk> |
| In reply to | #69887 |
Alla _ <modelling.data@gmail.com> writes: <snip> > Here is the program. Of course, I would love > to see your comments and suggestions, as well > as any nitpicking; any would be of a great > help. But, please, remember that I am at the > initial stage, hence I can understand only > basics for now :) It's very good. You've got an easy to understand program there. There are some things I'd do differently but I don't want to make you write programs just like I do. Instead, I'll just make a few remarks. 1) Try the input ;111111111112 2) The order in which things get added together does not matter. Does that let you make any simplifications? 3) How big can 'number' be? Does the lead to any simplifications? <snip> -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-08 06:42 -0700 |
| Message-ID | <4bde6ccc-2c98-4d8f-82df-22a19f55a0bb@googlegroups.com> |
| In reply to | #69900 |
On Tuesday, September 8, 2015 at 5:26:38 PM UTC+4, Ben Bacarisse wrote: > Alla _ <modelling.data@gmail.com> writes: > <snip> > > Here is the program. Of course, I would love > > to see your comments and suggestions, as well > > as any nitpicking; any would be of a great > > help. But, please, remember that I am at the > > initial stage, hence I can understand only > > basics for now :) > > It's very good. You've got an easy to understand program there. There > are some things I'd do differently but I don't want to make you write > programs just like I do. Instead, I'll just make a few remarks. > > 1) Try the input ;111111111112 > > 2) The order in which things get added together does not matter. Does > that let you make any simplifications? > > 3) How big can 'number' be? Does the lead to any simplifications? > > <snip> > -- > Ben. Ben, thank you. yes, indeed, you name very important issues that I don't know how to solve yet. For example, check user's input for letters, special characters, negative numbers, and prompt for the input until the user cooperates; Same with the size of the 'number'. I didn't understand your second question: 2) The order in which things get added together does not matter. Does that let you make any simplifications?
[toc] | [prev] | [next] | [standalone]
| From | Ben Bacarisse <ben.usenet@bsb.me.uk> |
|---|---|
| Date | 2015-09-08 20:50 +0100 |
| Message-ID | <87a8swofl7.fsf@bsb.me.uk> |
| In reply to | #69902 |
Alla _ <modelling.data@gmail.com> writes: <snip> > I didn't understand your second question: > |> 2) The order in which things get added together does not matter. Does |> that let you make any simplifications? You don't need to do multiple loops. You can add up the sum in one pass over the number. As a programmer, one of the things that is both fun and irritating is trying to get code that is clear and simple. There is always an irritating voice in my head asking of this or that could be done simpler or the purpose made clearer, but then there are lots of nice "ah!" moments as you find way to do things better. I am not 100% sure what is the neatest and simplest way to write this program of yours which it one reason I simple brought up some questions. -- Ben.
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-11 01:47 -0700 |
| Message-ID | <f9e7d119-ffca-47d1-9220-f6aaef6608df@googlegroups.com> |
| In reply to | #69966 |
On Tuesday, September 8, 2015 at 11:50:51 PM UTC+4, Ben Bacarisse wrote: > Alla _ <modelling.data@gmail.com> writes: > <snip> > > I didn't understand your second question: > > > |> 2) The order in which things get added together does not matter. Does > |> that let you make any simplifications? > > You don't need to do multiple loops. You can add up the sum in one pass > over the number. As a programmer, one of the things that is both fun > and irritating is trying to get code that is clear and simple. There is > always an irritating voice in my head asking of this or that could be > done simpler or the purpose made clearer, but then there are lots of > nice "ah!" moments as you find way to do things better. I am not 100% > sure what is the neatest and simplest way to write this program of yours > which it one reason I simple brought up some questions. > > -- > Ben. I understand and agree with you; and my intention is to learn to find clear, simple and beautiful solutions for code. I hope to find the way to do so with this program; you know that I am yet at such a low level of knowledge and understanding.
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2015-09-08 13:41 +0000 |
| Message-ID | <d586scFdva0U1@mid.uni-berlin.de> |
| In reply to | #69887 |
Alla _ <modelling.data@gmail.com> wrote:
> The task was to:
> 1) Get the card number from the user.
> 2) Multiply every other digit by 2,
> starting with the number's second-to-last digit,
> and then add those products' digits together.
> 3) Add the sum to the sum of the digits that
> weren't multiplied by 2.
> 4) If the total's last digit is 0 (or, put more
> formally, if the total modulo 10 is congruent to
> 0), the number is valid.
> 5) If the card is valid, print that it's a valid
> card and the name of the issuer.
> I version:
> #include <stdio.h>
> #include <string.h>
> int main(void)
> {
> char card_number[17];
> int i, number, digit, sum;
> int sum1 = 0, sum2 = 0, sum3 = 0;
>
> printf ("Please, enter your card number: \n");
>
> if (scanf ("%s", card_number) == 1)
Here's a potential problem: what happens if the user enters
a number that's longer than 16 digits? In that case scanf()
will try to write all of them into the 'card_number' buffer
and in the process write past the end of it. And that, of
course, is a rather evil thing to do - it's now completely
unclear what the program will do. It might even seem to work
correctly.
So you must find some way to stop scanf() from reading more
than 16 characters. The simplest way to do that is to pass
the maximum length with the "%s" format specifier, i.e.
if ( scanf( "16%s", card_number ) == 1 )
With this is will never attempt to read more than a 16
characters.
> {
> for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> {
> number = (card_number[i] - '0') * 2;
>
> if (number >= 0 && number <= 9)
I guess, since you multiplied by two, this should be
if ( number >= 0 && number <= 18 )
> {
> sum1 += number;
> }
>
What now follows doesn't seem to make too much sense.
Obviously, the user must have entered something that
wasn't a digit. But you now try to make something out
of it, but I guess it should be treated as an invalid
card number. And here you then also handle those cha-
racters that had a higher number representation than
'9' but not those with one less than '0'.
> if (number > 9)
> {
> while (number > 0)
> {
> digit = number % 10;
> sum2 += digit;
> number /= 10;
> }
> }
> }
>
> for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> {
> sum3 += (card_number[i] - '0');
And here you don't even attempt to test if what the user
entered was a digit...
> }
Here's an idea how it could done a bit differently:
char card_number[ 17 ];
printf( "Enter card number: " );
while ( ! ( scanf( "%16[0-9]", card_number ) == 1
&& getchar( ) == '\n' ) )
{
printf( "Not a card number, please re-ennter it: " );
while ( getchar( ) != '\n' )
/* empty */ ;
}
The "%16[0-9]" format specifier tells scanf() to read in only
digits (and 16 at most). The additional test for '\n' makes
sure that this was all the user entered and scanf() didn't
stop because it found something that was not a digit (or
more than 16 digits). In the loop there's a second while
loop to remove everything from the input buffer the user
typed (which obviously wasn't something that could appear
in a card number).
The summing up could also simplified a bit:
int sum = 0;
size_t i = strlen( card_number );
while ( i > 0 )
{
sum += card_number[ --i ] - '0';
if ( i > 0 )
sum += 2 * card_number[ --i ] - '0';
}
You actually don't need two loops, a single one will do.
Here no tests if what the user typed was all digits, that
has all been done by scanf().
> if (sum % 10 == 0)
> {
> switch (strlen(card_number))
> {
> case 15:
> printf ("It's a valid AMEX\n");
> break;
> case 16:
> printf ("It's a valid MASTERCARD or VISA\n");
> break;
> case 13:
> printf ("It's a valid VISA\n");
> break;
> default:
Here you should also have (as in your other version) some-
thing like
printf( "Vaild card from unknown card issuer\n" );
> break;
> }
> }
>
> else
> printf ("Sorry, the card number failed the test\n");
> }
>
> printf ("\n");
> return 0;
> }
There's one more snag though: if the user just enters '0'
this will be seen as a valid card number, but which it
probably isn't. I guess the specifications are a bit
incomplete, there rather likely is a lower bound for
the length of a card number.
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-10 01:31 -0700 |
| Message-ID | <e714d908-b358-471c-bf66-03f1be205cd9@googlegroups.com> |
| In reply to | #69901 |
On Tuesday, September 8, 2015 at 5:41:49 PM UTC+4, Jens Thoms Toerring wrote:
> Alla _ <modelling.data@gmail.com> wrote:
> > The task was to:
> > 1) Get the card number from the user.
>
> > 2) Multiply every other digit by 2,
> > starting with the number's second-to-last digit,
> > and then add those products' digits together.
>
> > 3) Add the sum to the sum of the digits that
> > weren't multiplied by 2.
>
> > 4) If the total's last digit is 0 (or, put more
> > formally, if the total modulo 10 is congruent to
> > 0), the number is valid.
>
> > 5) If the card is valid, print that it's a valid
> > card and the name of the issuer.
>
> > I version:
>
> > #include <stdio.h>
> > #include <string.h>
>
> > int main(void)
> > {
> > char card_number[17];
> > int i, number, digit, sum;
> > int sum1 = 0, sum2 = 0, sum3 = 0;
> >
> > printf ("Please, enter your card number: \n");
> >
> > if (scanf ("%s", card_number) == 1)
>
> Here's a potential problem: what happens if the user enters
> a number that's longer than 16 digits? In that case scanf()
> will try to write all of them into the 'card_number' buffer
> and in the process write past the end of it. And that, of
> course, is a rather evil thing to do - it's now completely
> unclear what the program will do. It might even seem to work
> correctly.
>
> So you must find some way to stop scanf() from reading more
> than 16 characters. The simplest way to do that is to pass
> the maximum length with the "%s" format specifier, i.e.
>
> if ( scanf( "16%s", card_number ) == 1 )
>
> With this is will never attempt to read more than a 16
> characters.
>
> > {
> > for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> > {
> > number = (card_number[i] - '0') * 2;
>
> >
> > if (number >= 0 && number <= 9)
>
> I guess, since you multiplied by two, this should be
Sorry, I should have entered comments, but I
hoped that the description of the task would be
suffice.
The card_number can contain numbers, some of which
when multiplied by two will give only one digit, and others
will have two digits. If the result has only one digit, then
I just sum up these digits; but if the result has 2 digits,
I need to sum these two digits (products' digits), as
specified in the task. This is how it's done:
for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
{
number = (card_number[i] - '0') * 2;
if (number >= 0 && number <= 9)
{
sum1 += number;
}
if (number > 9)
{
while (number > 0)
{
digit = number % 10;
sum2 += digit;
number /= 10;
}
}
}
for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
{
sum3 += (card_number[i] - '0');
}
sum = sum1 + sum2 + sum3;
This is part of the Luhn's algorithm
>
> if ( number >= 0 && number <= 18 )
>
>
> > {
> > sum1 += number;
> > }
> >
>
> What now follows doesn't seem to make too much sense.
> Obviously, the user must have entered something that
> wasn't a digit. But you now try to make something out
> of it, but I guess it should be treated as an invalid
> card number. And here you then also handle those cha-
> racters that had a higher number representation than
> '9' but not those with one less than '0'.
>
> > if (number > 9)
> > {
> > while (number > 0)
> > {
> > digit = number % 10;
> > sum2 += digit;
> > number /= 10;
> > }
> > }
> > }
> >
> > for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> > {
> > sum3 += (card_number[i] - '0');
>
> And here you don't even attempt to test if what the user
> entered was a digit...
>
> > }
>
> Here's an idea how it could done a bit differently:
>
> char card_number[ 17 ];
> printf( "Enter card number: " );
> while ( ! ( scanf( "%16[0-9]", card_number ) == 1
> && getchar( ) == '\n' ) )
> {
> printf( "Not a card number, please re-ennter it: " );
> while ( getchar( ) != '\n' )
> /* empty */ ;
> }
>
> The "%16[0-9]" format specifier tells scanf() to read in only
> digits (and 16 at most). The additional test for '\n' makes
> sure that this was all the user entered and scanf() didn't
> stop because it found something that was not a digit (or
> more than 16 digits). In the loop there's a second while
> loop to remove everything from the input buffer the user
> typed (which obviously wasn't something that could appear
> in a card number).
>
> The summing up could also simplified a bit:
>
> int sum = 0;
> size_t i = strlen( card_number );
> while ( i > 0 )
> {
> sum += card_number[ --i ] - '0';
> if ( i > 0 )
> sum += 2 * card_number[ --i ] - '0';
> }
>
> You actually don't need two loops, a single one will do.
> Here no tests if what the user typed was all digits, that
> has all been done by scanf().
>
> > if (sum % 10 == 0)
> > {
> > switch (strlen(card_number))
> > {
> > case 15:
> > printf ("It's a valid AMEX\n");
> > break;
> > case 16:
> > printf ("It's a valid MASTERCARD or VISA\n");
> > break;
> > case 13:
> > printf ("It's a valid VISA\n");
> > break;
> > default:
>
> Here you should also have (as in your other version) some-
> thing like
>
> printf( "Vaild card from unknown card issuer\n" );
>
> > break;
> > }
> > }
> >
> > else
> > printf ("Sorry, the card number failed the test\n");
> > }
> >
> > printf ("\n");
> > return 0;
> > }
>
> There's one more snag though: if the user just enters '0'
> this will be seen as a valid card number, but which it
> probably isn't. I guess the specifications are a bit
> incomplete, there rather likely is a lower bound for
> the length of a card number.
>
> Regards, Jens
> --
> \ Jens Thoms Toerring ___ jt@toerring.de
> \__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | jt@toerring.de (Jens Thoms Toerring) |
|---|---|
| Date | 2015-09-10 10:39 +0000 |
| Message-ID | <d5d4vrFlpkpU1@mid.uni-berlin.de> |
| In reply to | #70134 |
Alla _ <modelling.data@gmail.com> wrote:
> On Tuesday, September 8, 2015 at 5:41:49 PM UTC+4, Jens Thoms Toerring wrote:
> > Alla _ <modelling.data@gmail.com> wrote:
1> Sorry, I should have entered comments, but I
> hoped that the description of the task would be
> suffice.
> The card_number can contain numbers, some of which
> when multiplied by two will give only one digit, and others
> will have two digits. If the result has only one digit, then
> I just sum up these digits; but if the result has 2 digits,
> I need to sum these two digits (products' digits), as
> specified in the task. This is how it's done:
Thanks, didn't understand that. But then you still need to
check for non-digits the user may have entered.
With the Luhn algorithm (and if it's clear the input only
contains digits) the summation could be done in a single
loop with e.g.
int sum = 0;
size_t i = strlen( card_number );
while ( i > 0 )
{
sum += card_number[ --i ] - '0';
if ( i > 0 )
{
int n = 2 * card_number[ --i ] - '0';
if ( n <= 9 )
sum += n;
else
sum += 1 + n % 10;
}
Note that, if there are only digits, twice the value can't
be larger than 18, so if the doubled value is larger than
9 you just have to add 1 to the second digit of the resulting
number (i.e. to the modulo 10 of that number).
Regards, Jens
--
\ Jens Thoms Toerring ___ jt@toerring.de
\__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | David Thompson <dave.thompson2@verizon.net> |
|---|---|
| Date | 2015-09-20 18:35 -0400 |
| Message-ID | <iucuva1jd08hej5eotslp94tbhqhu4ctes@4ax.com> |
| In reply to | #70147 |
On 10 Sep 2015 10:39:57 GMT, jt@toerring.de (Jens Thoms Toerring)
wrote:
<snip>
> With the Luhn algorithm (and if it's clear the input only
> contains digits) the summation could be done in a single
> loop with e.g.
>
> int sum = 0;
> size_t i = strlen( card_number );
> while ( i > 0 )
> {
> sum += card_number[ --i ] - '0';
> if ( i > 0 )
> {
> int n = 2 * card_number[ --i ] - '0';
> if ( n <= 9 )
> sum += n;
> else
> sum += 1 + n % 10;
> }
>
> Note that, if there are only digits, twice the value can't
> be larger than 18, so if the doubled value is larger than
> 9 you just have to add 1 to the second digit of the resulting
> number (i.e. to the modulo 10 of that number).
>
The 2*digit > 9 case can be even simpler, just
sum += n - 9; // 10-9=1, 12-9=3, ... 18-9=9
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-10 01:33 -0700 |
| Message-ID | <8b071560-ed21-44c9-b7a0-e00fab7550e4@googlegroups.com> |
| In reply to | #69901 |
On Tuesday, September 8, 2015 at 5:41:49 PM UTC+4, Jens Thoms Toerring wrote:
> Alla _ <modelling.data@gmail.com> wrote:
> > The task was to:
> > 1) Get the card number from the user.
>
> > 2) Multiply every other digit by 2,
> > starting with the number's second-to-last digit,
> > and then add those products' digits together.
>
> > 3) Add the sum to the sum of the digits that
> > weren't multiplied by 2.
>
> > 4) If the total's last digit is 0 (or, put more
> > formally, if the total modulo 10 is congruent to
> > 0), the number is valid.
>
> > 5) If the card is valid, print that it's a valid
> > card and the name of the issuer.
>
> > I version:
>
> > #include <stdio.h>
> > #include <string.h>
>
> > int main(void)
> > {
> > char card_number[17];
> > int i, number, digit, sum;
> > int sum1 = 0, sum2 = 0, sum3 = 0;
> >
> > printf ("Please, enter your card number: \n");
> >
> > if (scanf ("%s", card_number) == 1)
>
> Here's a potential problem: what happens if the user enters
> a number that's longer than 16 digits? In that case scanf()
> will try to write all of them into the 'card_number' buffer
> and in the process write past the end of it. And that, of
> course, is a rather evil thing to do - it's now completely
> unclear what the program will do. It might even seem to work
> correctly.
>
> So you must find some way to stop scanf() from reading more
> than 16 characters. The simplest way to do that is to pass
> the maximum length with the "%s" format specifier, i.e.
>
> if ( scanf( "16%s", card_number ) == 1 )
>
> With this is will never attempt to read more than a 16
> characters.
>
> > {
> > for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> > {
> > number = (card_number[i] - '0') * 2;
>
> >
> > if (number >= 0 && number <= 9)
>
> I guess, since you multiplied by two, this should be
>
> if ( number >= 0 && number <= 18 )
>
>
> > {
> > sum1 += number;
> > }
> >
>
> What now follows doesn't seem to make too much sense.
> Obviously, the user must have entered something that
> wasn't a digit. But you now try to make something out
> of it, but I guess it should be treated as an invalid
> card number. And here you then also handle those cha-
> racters that had a higher number representation than
> '9' but not those with one less than '0'.
>
> > if (number > 9)
> > {
> > while (number > 0)
> > {
> > digit = number % 10;
> > sum2 += digit;
> > number /= 10;
> > }
> > }
> > }
> >
> > for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> > {
> > sum3 += (card_number[i] - '0');
>
> And here you don't even attempt to test if what the user
> entered was a digit...
>
> > }
>
> Here's an idea how it could done a bit differently:
>
> char card_number[ 17 ];
> printf( "Enter card number: " );
> while ( ! ( scanf( "%16[0-9]", card_number ) == 1
> && getchar( ) == '\n' ) )
> {
> printf( "Not a card number, please re-ennter it: " );
> while ( getchar( ) != '\n' )
> /* empty */ ;
> }
>
Thank you! I haven't yet learned how to solve this issue,
I will look into your helpful suggestion.
> The "%16[0-9]" format specifier tells scanf() to read in only
> digits (and 16 at most). The additional test for '\n' makes
> sure that this was all the user entered and scanf() didn't
> stop because it found something that was not a digit (or
> more than 16 digits). In the loop there's a second while
> loop to remove everything from the input buffer the user
> typed (which obviously wasn't something that could appear
> in a card number).
>
> The summing up could also simplified a bit:
>
> int sum = 0;
> size_t i = strlen( card_number );
> while ( i > 0 )
> {
> sum += card_number[ --i ] - '0';
> if ( i > 0 )
> sum += 2 * card_number[ --i ] - '0';
> }
>
> You actually don't need two loops, a single one will do.
> Here no tests if what the user typed was all digits, that
> has all been done by scanf().
>
> > if (sum % 10 == 0)
> > {
> > switch (strlen(card_number))
> > {
> > case 15:
> > printf ("It's a valid AMEX\n");
> > break;
> > case 16:
> > printf ("It's a valid MASTERCARD or VISA\n");
> > break;
> > case 13:
> > printf ("It's a valid VISA\n");
> > break;
> > default:
>
> Here you should also have (as in your other version) some-
> thing like
>
> printf( "Vaild card from unknown card issuer\n" );
>
> > break;
> > }
> > }
> >
> > else
> > printf ("Sorry, the card number failed the test\n");
> > }
> >
> > printf ("\n");
> > return 0;
> > }
>
> There's one more snag though: if the user just enters '0'
> this will be seen as a valid card number, but which it
> probably isn't. I guess the specifications are a bit
> incomplete, there rather likely is a lower bound for
> the length of a card number.
>
> Regards, Jens
> --
> \ Jens Thoms Toerring ___ jt@toerring.de
> \__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
| From | Alla _ <modelling.data@gmail.com> |
|---|---|
| Date | 2015-09-10 10:16 -0700 |
| Message-ID | <2e6deec0-c080-41f5-8f1c-18d27e46621f@googlegroups.com> |
| In reply to | #69901 |
On Tuesday, September 8, 2015 at 5:41:49 PM UTC+4, Jens Thoms Toerring wrote:
> Alla _ <modelling.data@gmail.com> wrote:
> > The task was to:
> > 1) Get the card number from the user.
>
> > 2) Multiply every other digit by 2,
> > starting with the number's second-to-last digit,
> > and then add those products' digits together.
>
> > 3) Add the sum to the sum of the digits that
> > weren't multiplied by 2.
>
> > 4) If the total's last digit is 0 (or, put more
> > formally, if the total modulo 10 is congruent to
> > 0), the number is valid.
>
> > 5) If the card is valid, print that it's a valid
> > card and the name of the issuer.
>
> > I version:
>
> > #include <stdio.h>
> > #include <string.h>
>
> > int main(void)
> > {
> > char card_number[17];
> > int i, number, digit, sum;
> > int sum1 = 0, sum2 = 0, sum3 = 0;
> >
> > printf ("Please, enter your card number: \n");
> >
> > if (scanf ("%s", card_number) == 1)
>
> Here's a potential problem: what happens if the user enters
> a number that's longer than 16 digits? In that case scanf()
> will try to write all of them into the 'card_number' buffer
> and in the process write past the end of it. And that, of
> course, is a rather evil thing to do - it's now completely
> unclear what the program will do. It might even seem to work
> correctly.
>
> So you must find some way to stop scanf() from reading more
> than 16 characters. The simplest way to do that is to pass
> the maximum length with the "%s" format specifier, i.e.
>
> if ( scanf( "16%s", card_number ) == 1 )
>
> With this is will never attempt to read more than a 16
> characters.
>
> > {
> > for (i = (strlen(card_number) - 2); i >= 0; i -= 2)
> > {
> > number = (card_number[i] - '0') * 2;
>
> >
> > if (number >= 0 && number <= 9)
>
> I guess, since you multiplied by two, this should be
>
> if ( number >= 0 && number <= 18 )
>
>
> > {
> > sum1 += number;
> > }
> >
>
> What now follows doesn't seem to make too much sense.
> Obviously, the user must have entered something that
> wasn't a digit. But you now try to make something out
> of it, but I guess it should be treated as an invalid
> card number. And here you then also handle those cha-
> racters that had a higher number representation than
> '9' but not those with one less than '0'.
>
> > if (number > 9)
> > {
> > while (number > 0)
> > {
> > digit = number % 10;
> > sum2 += digit;
> > number /= 10;
> > }
> > }
> > }
> >
> > for (i = (strlen(card_number) - 1); i >= 0; i -= 2)
> > {
> > sum3 += (card_number[i] - '0');
>
> And here you don't even attempt to test if what the user
> entered was a digit...
>
> > }
>
> Here's an idea how it could done a bit differently:
>
> char card_number[ 17 ];
> printf( "Enter card number: " );
> while ( ! ( scanf( "%16[0-9]", card_number ) == 1
> && getchar( ) == '\n' ) )
> {
> printf( "Not a card number, please re-ennter it: " );
> while ( getchar( ) != '\n' )
> /* empty */ ;
> }
>
> The "%16[0-9]" format specifier tells scanf() to read in only
> digits (and 16 at most). The additional test for '\n' makes
> sure that this was all the user entered and scanf() didn't
> stop because it found something that was not a digit (or
> more than 16 digits). In the loop there's a second while
> loop to remove everything from the input buffer the user
> typed (which obviously wasn't something that could appear
> in a card number).
>
I am trying to understand this part.
Please, correct me if I am wrong in my understanding
char card_number[ 17 ];
> printf( "Enter card number: " );
> while ( ! ( scanf( "%16[0-9]", card_number ) == 1
> && getchar( ) == '\n' ) )
/* while the user's input is not a numerical number
(while (!(scanf( "%16[0-9]", card_number ) == 1..)
and while there are still some characters in the user's
input (...&& getchar() == '\n')
tell the user to re-enter the card number. Is it a correct
interpretation of this part? */
> {
> printf( "Not a card number, please re-ennter it: " );
> while ( getchar( ) != '\n' )
/* I don't understand the function and meaning of
the while ( getchar( ) != '\n' ) used inside the loop.
What else does this add to the same line within while
loop condition? Isn't while ( getchar( ) != '\n' )
equal to while ( ! ( getchar( ) == '\n' ) )?
> /* empty */ ;
> The summing up could also simplified a bit:
>
> int sum = 0;
> size_t i = strlen( card_number );
> while ( i > 0 )
> {
> sum += card_number[ --i ] - '0';
> if ( i > 0 )
> sum += 2 * card_number[ --i ] - '0';
> }
>
> You actually don't need two loops, a single one will do.
> Here no tests if what the user typed was all digits, that
> has all been done by scanf().
>
> > if (sum % 10 == 0)
> > {
> > switch (strlen(card_number))
> > {
> > case 15:
> > printf ("It's a valid AMEX\n");
> > break;
> > case 16:
> > printf ("It's a valid MASTERCARD or VISA\n");
> > break;
> > case 13:
> > printf ("It's a valid VISA\n");
> > break;
> > default:
>
> Here you should also have (as in your other version) some-
> thing like
>
> printf( "Vaild card from unknown card issuer\n" );
>
> > break;
> > }
> > }
> >
> > else
> > printf ("Sorry, the card number failed the test\n");
> > }
> >
> > printf ("\n");
> > return 0;
> > }
>
> There's one more snag though: if the user just enters '0'
> this will be seen as a valid card number, but which it
> probably isn't. I guess the specifications are a bit
> incomplete, there rather likely is a lower bound for
> the length of a card number.
>
> Regards, Jens
> --
> \ Jens Thoms Toerring ___ jt@toerring.de
> \__________________________ http://toerring.de
[toc] | [prev] | [next] | [standalone]
Page 1 of 3 [1] 2 3 Next page →
Back to top | Article view | comp.lang.c
csiph-web