Program is not entering the loop as expected

Hi forum,

For some reason, when I run the below code, I always get the following output:

1
2
3
4
5
6
7
8
9
10
11
12
13
Canada Revenue Agency Account App
=================================

Please enter your family name: tet
Please enter your given name: we
Please enter your social insurance number (0 to quit): 193456787
Please enter the year of your tax return (0 to quit): 2013
Please enter the balance owing on your tax return (0 to quit): 12
Please enter the year of your tax return (0 to quit): 2014
Please enter the balance owing on your tax return (0 to quit): -12
Please enter the year of your tax return (0 to quit): 2015
Please enter the balance owing on your tax return (0 to quit): 1
Please enter the year of your tax return (0 to quit): 0
Testing the display function
----------------------------------------
Family Name: tet
Given Name : we
CRA Account: 193456787
Year 2013 balance owing: 12.00
Year 2013 balance owing: 12.00
Year 2013 balance owing: 12.00
Year 2013 balance owing: 12.00
----------------------------------------


Where 2013 is the first year entered into the array.

Instead, I should be seeing,

1
2
3
4
5
6
7
8
9
10
11
12
13
Canada Revenue Agency Account App
=================================

Please enter your family name: tet
Please enter your given name: we
Please enter your social insurance number (0 to quit): 193456787
Please enter the year of your tax return (0 to quit): 2013
Please enter the balance owing on your tax return (0 to quit): 12
Please enter the year of your tax return (0 to quit): 2014
Please enter the balance owing on your tax return (0 to quit): -12
Please enter the year of your tax return (0 to quit): 2015
Please enter the balance owing on your tax return (0 to quit): 1
Please enter the year of your tax return (0 to quit): 0
Testing the display function
----------------------------------------
Family Name: tet
Given Name : we
CRA Account: 193456787
Year 2013 balance owing: 12.00
Year 2014 refund due: -12.00
Year 2015 No balance owing or refund due!
----------------------------------------


Any advice would be much appreciated, thank you.

//header

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
#ifndef SICT_CRA_ACCOUNTING
#define SICT_CRA_ACCOUNTING
#define minSin 100000000
#define maxSin 999999999

namespace sict
{
	const int max_name_length = 40;
	const int max_yrs = 4;
	class CRA_Account
	{
		char lastName[max_name_length + 1];
		char firstName[max_name_length + 1];
		int numSIN;
		int taxReturnYrs[max_yrs];
		double ttlBalance[max_yrs];
		int ttlYrs;
	public:
		void set(const char* familyName, const char* givenName, int sin);
		void set(int year, double balance);
		void setEmpty();
		void display() const;
		bool isEmpty();
		bool isValidSIN(int sin);
	};

}
#endif // !SICT_CRA_ACCOUNTING 


//implementation file
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
#include <iostream>
#include <cstring>
#include "CRA_Account.h"

using namespace std;

namespace sict
{
	void CRA_Account::setEmpty()
	{
		lastName[0] = '\0';
		firstName[0] = '\0';
		numSIN = 0;
	}

	void CRA_Account::set(const char* familyName, const char* givenName, int sin)
	{
		if      (isValidSIN(sin) && '\0' != familyName && '\0' != givenName)
		{
			strcpy(lastName, familyName);
			strcpy(firstName, givenName);
			numSIN = sin;
			ttlYrs = 0;
		}
		else
		{
			setEmpty();
		}
	}

	void CRA_Account::set(int year, double balance)
	{
		if (0 != numSIN && ttlYrs < max_yrs)
		{
			for (int i = 0; i < max_yrs; i++)
			{
				if (0 != taxReturnYrs[i])
				{
					taxReturnYrs[i] = year;
					ttlBalance[i] = balance;
					ttlYrs++;
				}
			}
		}
	}

	bool CRA_Account::isValidSIN(int sin)
	{
		int sum = 0;
		int check = sin % 10;
		int evens[4] = { (((sin / 10) % 10) * 2), (((sin / 1000) % 10) * 2), (((sin / 100000) % 10) * 2), (((sin / 10000000) % 10) * 2) };
		int odds[4] = { (((sin / 100) % 10)), (((sin / 10000) % 10)), (((sin / 1000000) % 10)), (((sin / 100000000) % 10)) };
		for (int i = 0; i < 4; i++)
		{
			sum += ((((evens[i] / 1) % 10) + ((evens[i] / 10) % 10)));
			sum += odds[i];
		}
		int upIntTen = ((sum + 9) / 10) * 10;
		if (((upIntTen - sum) == (sin / 1) % 10) && sin >= minSin && sin <= maxSin)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	void CRA_Account::display() const
	{
		if (0 != numSIN || '\0' != lastName || '\0' != firstName)
		{
			cout << "Family Name: " << this->lastName << endl;
			cout << "Given Name : " << this->firstName << endl;
			cout << "CRA Account: " << this->numSIN << endl;
			cout.setf(ios::fixed);
			cout.precision(2);
			for (int i = 0; i < max_yrs; i++)
			{
				cout << "Year " << taxReturnYrs[i];
					if (ttlBalance[i] > 2)
					{
						cout << " balance owing: " << ttlBalance[i] << endl;
					}
					else if (ttlBalance[i] < -2)
					{
						cout << " refund due: " << ttlBalance[i] << endl;
					}
					else
					{
						cout << " No balance owing or refund due! " << endl;
					}
			}
			cout.unsetf(ios::fixed);
			cout.precision(6);

		}
		else
		{
			cout << "Account object is empty!" << endl << endl;
		}
	}

	bool CRA_Account::isEmpty()
	{
		if (0 == this->numSIN || this->numSIN <= minSin || this->numSIN >= maxSin || '\0' == this->firstName[0] || '\0' == this->lastName[0])
		{
			return true;
		}
		else
		{
			return false;
		}
	}
}


//main
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
#include <iostream>
#include "CRA_Account.h"
using namespace std;
using namespace sict;

int main() {
	sict::CRA_Account myCRA;
	int sin;
	bool quit = false;
	char familyName[sict::max_name_length + 1];
	char givenName[sict::max_name_length + 1];

	cout << "Canada Revenue Agency Account App" << endl
	     << "=================================" << endl << endl;

	do {
		cout << "Please enter your family name: ";
		cin.getline(familyName, max_name_length);
		cout << "Please enter your given name: ";
		cin.getline(givenName, max_name_length);
		cout << "Please enter your social insurance number (0 to quit): ";
		cin >> sin;
		cin.ignore();
		if (sin != 0) {
			myCRA.set(familyName, givenName, sin);
			if (myCRA.isEmpty()) {
				cout << "Invalid input! Try again." << endl;
			}
			else {
				int year;
				double balance;
				do {
					cout << "Please enter the year of your tax return (0 to quit): ";
					cin >> year;
					cin.ignore();
					if (year != 0) {
						cout << "Please enter the balance owing on your tax return (0 to quit): ";
						cin >> balance;
						cin.ignore();
						myCRA.set(year, balance);
					}
				} while (year != 0);
				quit = true;
			}
		}
		else {
			quit = true;
		}
	} while (!quit);
	cout << "----------------------------------------" << endl;
	cout << "Testing the display function" << endl;
	cout << "----------------------------------------" << endl;
	myCRA.display();
	cout << "----------------------------------------" << endl;

	return 0;
}
Hello chuvak,

First question is which loop? Where?

The way I set up the program I had to change lines 18 and 20 to:
1
2
		std::cin.getline(familyName, sict::max_name_length);
		std::cin.getline(givenName, sict::max_name_length);


I changed line 23 to:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // Requires header file limits.
and the program worked better.

The only loop I found a problem with is: void CRA_Account::set(int year, double balance). The for loop stores the same number in all the arry's elements and only works once. Still working on a fix, but it is a problem. Elements 1,2, and 3 have the same number as element 0 and never change.

I still feel that you should be using std::strings instead of the C style arrays and avoid using "strcpy" as it is outdated and a possible security risk.

That is as far as have reached for now.

Hope that helps,

Andy
Yes, my thoughts exactly. The void CRA_Account::set(int year, double balance) function is totally wrong. Every time it is called, it will simply overwite every taxReturnYrs[i] and ttlBalance[i] with the current year and balance, which is why the last year is always showing up. Any thoughts as to how to get it to modify individual cells, not all of them? I feel like it's a very simple solution, but Im drawing a huge blank here. I reckon the first step is to remove the for loop, but I'll wait for your advice first.

Thanks Andy
Last edited on
Hello chuvak,

I had this written out once and lost it all when it was to large. Look over the comments in the code and if you have any questions let me know.

CRA_Account.h
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
#ifndef SICT_CRA_ACCOUNTING
#define SICT_CRA_ACCOUNTING
#define minSin 100000000
#define maxSin 999999999

namespace sict
{
	const int max_name_length = 40;
	const int max_yrs = 4;

	class CRA_Account
	{
	public:
		CRA_Account();  // <--- Added.
		void set(const char* familyName, const char* givenName, int sin);
		void set(int year, double balance);
		void setEmpty();
		void display() const;
		bool isEmpty();
		bool isValidSIN(int sin);
		int GetTtlYrs();  // <--- Added.
	private:
		char lastName[max_name_length + 1];
		char firstName[max_name_length + 1];
		int numSIN;
		int taxReturnYrs[max_yrs];
		double ttlBalance[max_yrs];
		int ttlYrs;
	};

}
#endif // !SICT_CRA_ACCOUNTING  


CRA_Account.cpp
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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#include <iostream>
#include <iomanip>
#include <cstring>

#include "CRA_Account.h"

namespace sict
{
	CRA_Account::CRA_Account()  // <--- Added.
	{
		lastName[0] = '\0';   // <--- Should also be a for loop, but works this way.
		firstName[0] = '\0';  // <--- Should also be a for loop, but works this way.
		numSIN = 0;
		for (size_t lc = 0; lc < max_yrs; lc++) taxReturnYrs[lc] = 0;
		for (size_t lc = 0; lc < max_yrs; lc++) ttlBalance[lc] = 0.0;
		ttlYrs = 0;
	}

	//  This function does not have much use right now.
	//  Should look like above when/if needed.
	void CRA_Account::setEmpty()
	{
		lastName[0] = '\0';
		firstName[0] = '\0';
		numSIN = 0;
	}

	void CRA_Account::set(const char* familyName, const char* givenName, int sin)
	{
		if (isValidSIN(sin) && '\0' != familyName && '\0' != givenName)
		{
			strcpy(lastName, familyName);
			strcpy(firstName, givenName);
			numSIN = sin;
			ttlYrs = 0;
		}
		else
		{
			setEmpty();
		}
	}

	void CRA_Account::set(int year, double balance)
	{
		//  Removed for loop.
		//  This uses "ttlYrs" as the subscript so it changes each time the function is called.
		//  This funcion only works four times until "ttlYrs" is >= max_yrs.
		if (0 != numSIN && ttlYrs < max_yrs)
		{
				if (0 == taxReturnYrs[ttlYrs])  // <--- Changed != to ==.
				{
					taxReturnYrs[ttlYrs] = year;
					ttlBalance[ttlYrs] = balance;
					ttlYrs++;
				}
		}
	}

	bool CRA_Account::isValidSIN(int sin)
	{
		int sum = 0;
		int check = sin % 10;
		int evens[4] = { (((sin / 10) % 10) * 2), (((sin / 1000) % 10) * 2), (((sin / 100000) % 10) * 2), (((sin / 10000000) % 10) * 2) };
		int odds[4] = { (((sin / 100) % 10)), (((sin / 10000) % 10)), (((sin / 1000000) % 10)), (((sin / 100000000) % 10)) };

		for (int i = 0; i < 4; i++)
		{
			sum += ((((evens[i] / 1) % 10) + ((evens[i] / 10) % 10)));
			sum += odds[i];
		}

		int upIntTen = ((sum + 9) / 10) * 10;

		if (((upIntTen - sum) == (sin / 1) % 10) && sin >= minSin && sin <= maxSin)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	void CRA_Account::display() const
	{
		if (0 != numSIN || '\0' != lastName || '\0' != firstName)
		{
		        // <--- It works, but the use of "this->" is not need here in this type of member function.
		        // Becuse the function has direct access to the private variables.			std::cout << "Family Name: " << this->lastName << std::endl;
			std::cout << "Given Name : " << this->firstName << std::endl;
			std::cout << "CRA Account: " << this->numSIN << std::endl;
			std::cout.setf(std::ios::fixed);
			std::cout.precision(2);
			
			for (int i = 0; i < max_yrs; i++)
			{
				if (taxReturnYrs[i] == 0)  // <--- Added if/else.
					break;
				else
				{
					std::cout << "Year " << taxReturnYrs[i];
					if (ttlBalance[i] > 2)
					{
						std::cout << " balance owing: $" << ttlBalance[i] << std::endl;  // <--- Changed.
					}
					else if (ttlBalance[i] < -2)
					{
						std::cout << " refund due: $" << abs(ttlBalance[i]) << std::endl;  // <--- Changed.
					}
					else
					{
						std::cout << " No balance owing or refund due! " << std::endl;
					}
				}
			}
			std::cout.unsetf(std::ios::fixed);
			std::cout.precision(6);

		}
		else
		{
			std::cout << "Account object is empty!" << std::endl << std::endl;
		}
	}

	bool CRA_Account::isEmpty()
	{
		// <--- It works, but the use of "this->" is not need here in this type of member function.
		// Becuse the function has direct access to the private variables.
		// An example is the next function.
		if (0 == this->numSIN || this->numSIN <= minSin || this->numSIN >= maxSin || '\0' == this->firstName[0] || '\0' == this->lastName[0])
		{  //  <--- These not needed for a single line. Also for else statement.
			return true;
		}
		else
		{
			return false;
		}
	}

	int CRA_Account::GetTtlYrs() { return ttlYrs; }  // <--- Added.
}  // End namespace 


Main.cpp
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
#include <iostream>
#include "CRA_Account.h"
int main()
{
	sict::CRA_Account myCRA;
	int sin;
	bool quit = false;
	char familyName[sict::max_name_length + 1];
	char givenName[sict::max_name_length + 1];

	std::cout << "\nCanada Revenue Agency Account App" << std::endl
		<< "=================================" << std::endl << std::endl;

	do {
		//  <--- Changed. Should be done first to avoid any unnecessary entry.
		//  Would also be a good time to validate "sin"before continuing.
		std::cout << "Please enter your social insurance number (0 to quit): ";
		std::cin >> sin;
		//std::cin.ignore();
		// <--- This mmust be done before a getline.
		std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // <--- Requires header file "limits".

		if (sin == 0)
		{
			quit = true;
			continue;  // <--- Skips everything and goes to the while condition.
		}

		std::cout << "Please enter your family name: ";
		std::cin.getline(familyName, sict::max_name_length);
		std::cout << "Please enter your given name: ";
		std::cin.getline(givenName, sict::max_name_length);

		if (sin != 0)
		{
			myCRA.set(familyName, givenName, sin);
			if (myCRA.isEmpty())
			{
				std::cout << "Invalid input! Try again." << std::endl;
			}
			else
			{
				int year;
				double balance;
				do
				{
					std::cout << "Please enter the year of your tax return (0 to quit): ";
					std::cin >> year;
					std::cin.ignore();  // <--- Not really needed here.
					if (year == 0)  // <--- Added.
						continue;  // <--- Skipps everything and goes to the while condition.

					if (year != 0)
					{
						std::cout << "Please enter the balance owing on your tax return: ";  // <--- Removed zero to quit. Because you ight want ot enter a zero and not quit.
						std::cin >> balance;
						std::cin.ignore();  // <--- Not really needed here.

						myCRA.set(year, balance);
					}

				} while (year != 0 && myCRA.GetTtlYrs() < sict::max_yrs);  // <--- Changed.

				quit = true;
			}
		}
		else
		{
			quit = true;
		}
	} while (!quit);

	std::cout << "\n\n----------------------------------------" << std::endl;
	std::cout << "Testing the display function" << std::endl;
	std::cout << "----------------------------------------" << std::endl;
	myCRA.display();
	std::cout << "----------------------------------------" << std::endl;

        return 0;
}


See What you think nd let me know.

Hope tht helps,

Andy
Your question is too vague to answer. Can you be more specific which loop you're exactly talking about and where exactly is it in the syntax you provided. On analyzing your codes the only problem with loop I found was with "void CRA_Account::set(int year, double balance)". You should use std::strings instead of C style arrays to prevent errors.

https://show-box.ooo/
Topic archived. No new replies allowed.