Array Arithmetic

Hello, I'm new to this forum and somewhat new to programming in general. I'd like to start off by saying yes, I have looked around to find solutions, but the problem I come across 9 out of 10 times stems from my lack of knowledge on the subject; every explanation is written such that I can't understand it.

Anyway, I'm having a problem writing a program for Luhn's Algorithm for class (Yes, this is for a class, but I wonder if our teacher gave this to us in error or something because we had not even learned about arrays or pointers or anything of the such yet; I taught myself [to put it loosely] how to use them on a basic level.) I had struggled through it until I thought I was finished. I noticed it was always coming up as a valid card number, so I became suspicious and checked the output. Turns out something was happening when trying to change the inputted digits for the formula. My code is very... cluttered... to say the least, so here is a some-what cleaned version.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
void main()
{
	cout << "Please enter your credit card number one digit at a time: \n\n";  // I didn't know how to separate the string if it was inputted in just one line, so I did it one number at a time.
	while (a < 17 && a >= 1)  // Allows the numbers to be inputted normally while assigning them backwards, as is supposed to be done according to the algorithm.
	{
		cin >> Dig[a];
		a--;
	}

	while (b >= 0 && b < 16)  // Cannot divide / modulus an array by a static number (or so I figured), so this sets the entire Divisor array to 10.
	{
		Div[b] = 10;
		b++;
	}

	while (c >= 0 && b < 16)  // This procedure is supposed to double every other number and add up the digits separately if it is double digits after doubled, but this is where my problem is.
	{
		if (c == 1 || c == 3 || c == 5 || c == 7 || c == 9 || c == 11 || c == 13 || c == 15)
		{
			Dig[c] = ((Dig[c])*2);
			if (Dig[c] < 10)
			{
				NDig[c] = ((Dig[c]) / (Div[c]));  // Getting the left number for double digits.
				NDigR[c] = ((Dig[c]) % (Div[c]));  // Getting the right number for double digits.
				c++;  
			}
			else
			{
				NDig[c] = Dig[c];
				c++;
			}
		}
		else
		{
			NDig[c] = Dig[c];
			c++;
		}
	}
	
	// I'm also not sure if I'm allowed to sum the digits like this, seeing as I cannot even get passed the previous step.
	TotalSum = ((NDig[0]+NDig[1]+NDig[2]+NDig[3]+NDig[4]+NDig[5]+NDig[6]+NDig[7]+NDig[8]+NDig[9]+NDig[10]+NDig[11]+NDig[12]+NDig[13]+NDig[14]+NDig[15]) + (NDigR[0]+NDigR[1]+NDigR[2]+NDigR[3]+NDigR[4]+NDigR[5]+NDigR[6]+NDigR[7]+NDigR[8]+NDigR[9]+NDigR[10]+NDigR[11]+NDigR[12]+NDigR[13]+NDigR[14]+NDigR[15]));
	CheckDigitTest = ((TotalSum)%10);  // Performing modulus 10 on the Sum for the final result.
	
	if (CheckDigitTest == 0)
	{
		cout << "\n\n" << "Check digit test passed; credit card number is valid" << "\n\n\n";
	}
	else
	{
		cout << "\n\n" << "Check digit test failed; credit card number is invalid" << "\n\n\n";
	}

	 system("Pause");  // I also know this is a bad habit from reading other posts around here.  I will try to implement some of the other solutions later on.
}


My actual code is much worse than this looks... I know it could be MUCH cleaner and could be MUCH tighter, but please remember that I'm completely new to programming, having just been a huge computer geek previously with experience in HTML, CSS, ActionScript, and the such.

Anyway, my problem seems to lie in the middle where I'm trying to calculate NDig and NDigR for each number. While troubleshooting, I found that every NDig and NDigR had a value of 0, so I know I did SOMETHING wrong while trying to set them... I just don't know what. Any and all help is highly appreciated! Again.. please don't flame me just because I'm completely new.

Regards,
John
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int main(){// note int. compilers may allow void, but int is standard.
   char dig[17];//16 symbols + 1 null character.
   cin.getline(dig, 17);//reads a string
   for(int i = 0; i < 17; i++) dig[i] -= '0';// converts from char values '0', '1', ... to integers 0, 1, ...
   
   for(int i = 0; i < 17; i++){//use for loops where appropriate
      if( i % 2 != 0 ){// if i is odd..
         dig[i] *= 2;
         int first = dig[i]/10;//you can use temporary variables to save memory
         int second = dig[i]%10;//you don't need to check if dig[i] > 10. if it isn't first will be 0
         dig[i] = first + second;//and this will make no difference
      }//else do nothing
   }

   int sum = 0;
   for(int i = 0; i < 17; i++) sum += dig[i];//actually you could have only one big for loop in the whole program,
   sum %= 10;//but this will probably be more clear.

   cout << (sum == 0 ? "valid" : "invalid");//this isn't a better way, I'm just lazy..

   cin.get();
   return 0;
}
Thank you very much for your reply =) It has given me a lot of insight on how this works. However, after plugging in some of the code, editing it to fit my code (while hopefully not screwing it up, but I'm sure I did somewhere), and changing some things (specifically For; I don't know why it was happening but if for instance I did:
1
2
3
4
for (int b = 0; b < 16; b++)
{
      // Code inside this function
}

It would yell at me for not putting a semi-colon after it or something. Then I played around and found if I took out the b++ in the parameters it would stop yelling at me [I'm using Visual C++ by the way], so I changed it to:
1
2
3
4
for (int b = 0; b < 16)
{
      // Code inside this function
}

But then it was crashing, so I took it out all together and changed it to the While you see) I seemed to SOMEWHAT get it working... However, now it doesn't seem to be taking the input correctly because I'm getting NewDigit values in the three digits and the TotalSum being in the -300,000,000's... I don't know how to remedy this at all. This again most likely stems from my lack of experience in the field so I may have not changed some code to fit my needs correctly or whatever.

This time I'll just give you my actual code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include <iostream>

using namespace std;

int a = 15;
int b = 0;
int c = 0;
int d = 0;
char Digits[16];  // Represent the digits inputted by user
int NewDigits[16];  // Digits after multiplying by two every other digit
int NewDigitsRemainder[16];  // Digits left over (if any; if not, it's simply the first one + 0) after performing modulus 10 to see if it was double digits.
int Divisor[16];  // Telling it what to divide by and what to modulus by; it wouldn't let me divide / modulus by a static int Ex. int Divisor = 10;
int TotalSum = 0;  // Adds up the two digits (if only one, it is, again, Digit + 0, so it doesn't matter).
int CheckDigit;
int CheckDigitTest;
int NewestDigits[16];

int main()
{
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	//// Inputs random numbers automatically to make testing easier.
	//int e = 0;
	//while (e >= 0 && e < 16)
	//{
	//	Digits[e] = rand() % 10;
	//	e++;
	//}
	/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
	
	
	cout << "Please enter your credit card: \n\n";
	while (a >= 0)  // Allows the numbers to be inputted normally while assigning them backwards, as is supposed to be done according to the algorithm.
	{
		cin.getline(Digits, 16);
		while (b < 16)
		{
			Digits[b] += '0';
			b++;
		}
		a--;
	}
	

	while (c >= 0 && c < 16)  // "While" doing the same thing as in the first portion, this time calculating the final numbers.
	{
		if (c % 2 == 0)
		{
			NewDigits[c] = ((Digits[c]) / (10));  // Getting the left number for double digits.
			NewDigitsRemainder[c] = ((Digits[c]) % (10));  // Getting the right number for double digits.
			NewestDigits[c] = NewDigits[c] + NewDigitsRemainder[c];
			c++;
		}
		else
		{
			Digits[c] *= 2;  // Doubling every other number
			NewDigits[c] = ((Digits[c]) / (10));  // Getting the left number for double digits.
			NewDigitsRemainder[c] = ((Digits[c]) % (10));  // Getting the right number for double digits.
			NewestDigits[c] = NewDigits[c] + NewDigitsRemainder[c];
			c++;
		}
	}
	
	cout << "\n\n" << "Digits 0 - 9 equal: " << Digits[0] << Digits[1] << Digits[2] << Digits[3] << Digits[4] << Digits[5] << Digits[6] << Digits[7] << Digits[8] << Digits[9] << "\n" << "NewDigits 0 - 9 equal: " << NewDigits[0] << NewDigits[1] << NewDigits[2] << NewDigits[3] << NewDigits[4] << NewDigits[5] << NewDigits[6] << NewDigits[7] << NewDigits[8] << NewDigits[9] << "\n" << "NewDigitsRemainder 0 - 9 equal: " << NewDigitsRemainder[0] << NewDigitsRemainder[1] << NewDigitsRemainder[2] << NewDigitsRemainder[3] << NewDigitsRemainder[4] << NewDigitsRemainder[5] << NewDigitsRemainder[6] << NewDigitsRemainder[7] << NewDigitsRemainder[8] << NewDigitsRemainder[9] << "\n\n";  // For testing / troubleshooting purposes.  This and the one like it below are why I knew what was happening.
	
	while (d < 17)
	{
		TotalSum += NewestDigits[d];
		d++;
	}
	


	//TotalSum = ((NewDigits[0]+NewDigits[1]+NewDigits[2]+NewDigits[3]+NewDigits[4]+NewDigits[5]+NewDigits[6]+NewDigits[7]+NewDigits[8]+NewDigits[9]+NewDigits[10]+NewDigits[11]+NewDigits[12]+NewDigits[13]+NewDigits[14]+NewDigits[15]) + (NewDigitsRemainder[0]+NewDigitsRemainder[1]+NewDigitsRemainder[2]+NewDigitsRemainder[3]+NewDigitsRemainder[4]+NewDigitsRemainder[5]+NewDigitsRemainder[6]+NewDigitsRemainder[7]+NewDigitsRemainder[8]+NewDigitsRemainder[9]+NewDigitsRemainder[10]+NewDigitsRemainder[11]+NewDigitsRemainder[12]+NewDigitsRemainder[13]+NewDigitsRemainder[14]+NewDigitsRemainder[15]));  // Adding all the numbers together.
	//CheckDigitTest = ((TotalSum)%10);  // Performing modulus 10 on the Sum for the final result.
	/*
	//if (CheckDigitTest == 0)
	//{
	//	cout << "\n\n" << "Check digit test passed; credit card number is valid" << "\n\n\n";
	//}
	//else
	//{
	//	cout << "\n\n" << "Check digit test failed; credit card number is invalid" << "\n\n\n";
	//}

	*/
	cout << "TotalSum equals " << TotalSum << "\n" << "CheckDigitTest equals " << CheckDigitTest << "\n\n";  // This is again for testing / troubleshooting purposes.

	system("Pause");

	return 0;
}

Note that all of the comments except one near the bottom labeled for the forum are meant for my instructor, so ignore them.

Thank you again for all of your time and patience.

Regards,
John
Last edited on
If for loops don't work there's something horribly wrong with the compiler, but I have a feeling you made a mistake somehow..

lines 32-41. You have two nested for loops there meaning that you will be asked to enter 16 strings 16 chars each.
line 37. you add '0'. why? google "ascii table" and see what you need to do with '5' to get the integer 5.
If you need 16 digits, you need an array of 17 elements. 1 for null char.

lines 44-61. if c % i = 0, c is even. You know that Digits array has only digits in it, so why are you splitting them into digits? Your assignment tells you to do nothing if c is even..
when c is odd, why do you store the two digits in separate arrays? You have no use for them. Use locals.

line 63. This is insane. Loops are for that.
The for loop syntax requires you to have two semicolons in the () always. Yo don't need to fill any of the spots but you must always have two semicolons.

for (/*Initialize*/ ; /*Conditional*/; /*Increment*/) // Required Semicolons

You can leave the seconds blank, but need semicolons.
1
2
3
4
for (int i = 0; /*No condition. Expected to leave loop from inside via break or return.*/; ++i)
{
  // code here
}
Yeah, I knew I would screw it up somehow. Most of it I thought I was just taking your code and formatting it to fit mine, but I guess I didn't do that very well.

This part I thought I was taking your code correctly, but I guess not. I think I see how I messed it up anyway.

For line 37, that's what your code says (I think) except you're subtracting it instead. I was playing around with it to see what would differ since I don't know exactly what you're doing with that. I'm also afraid that I don't know much about chars and strings so I don't know what you mean by what I have to do to '5' to get the integer 5.

For 44-61, I need to double every other number going from right to left. I'm storing them in separate arrays because if it is odd I'm doubling the number, and if the result is two digits, I need to add the digits separately (i.e. 14 -> 1 + 4) to work with Luhn's Algorithm.

I know 63 is insane, but it wasn't a very well thought out idea. It was simply to see what the output is and it worked well enough so I didn't clean it up. I would of course take that out in the final result.

Wolfgang: Ah, thank you. I didn't know that about For =)

Thank you two for your help. My class is 6 PM EST which is when this is due and I hope I can get it working by then.

Regards,
John

EDIT: After changing the array to 17, taking out the first loop in the input part, and changing the ++ to -- I have the input working now thanks to you. I checked the output and it matches what I got when I did Luhn's Algorithm manually. My only problem now is that I get "TotalSum equals 101450810"... so I'm not adding it correctly. I'm still using the same code to add it:
1
2
3
4
5
while (d < 17)
	{
		TotalSum += NewestDigits[d];
		d++;
	}

I checked the output for NewestDigits and it's correct, so the problem lies within this part.

EDIT X2: I have it working except after testing some, it's not taking the last integer of Digits and putting it into NewDigits and NewDigitsRemainder. Instead, it seems to be putting in a static -4 and -8 in them respectively even if I cut the size of the arrays down so they wouldn't fit.

FINAL EDIT: I got it working finally. I took the solution from here:
http://www.daniweb.com/forums/thread28270.html
I took the code given there, reformatted it, and replaced your code with:
1
2
3
4
5
for (int b = 0; b < 16; b++)
	{
		char Temp = DigitsChar[b];
		Digits[b] = atoi(&Temp);
	}

It may not be the best solution, as stated in the thread, but I'm not concerned about the safety of my code as it's for a class. It works, so I'm good. Thank you two for your help.
Last edited on
Topic archived. No new replies allowed.