-2

In my CRA_Account.cpp file my socialInsuranceNumber gets changed after for

(j = 0; j <= max_name_length; j++) {
                given_name[j] = givenName[j];
            }

occurs. example: If i enter 123123123 as my SIN, it gets changed to 123123148. The previous for loop that has

for (j = 0; j <= max_name_length; j++) {
                family_name[j] = familyName[j];
            }

doesnt change my socialInsuranceNumber value.

My code is:

w3_in_lab.cpp

#include <iostream>
#include "CRA_Account.h"

using namespace std;
using namespace sict;

int main() {
    const int size = 1000;
    char familyName[size];
    char givenName[size];
    sict::CRA_Account myCRA;
    int sin;
    bool quit = false;
    if (sict::max_name_length + 1 > size) {
        cerr << "Increase size to value greater than " 
            << sict::max_name_length + 1 << endl;
        return 1;
    }

    cout << "Canada Revenue Agency Account App" << endl
         << "=================================" << endl << endl;
    cout << "Please enter your family name: ";
    cin >> familyName;
    cin.ignore();
    cout << "Please enter your given name: ";
    cin >> givenName;
    cin.ignore();

    do {
        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 {
                quit = true;
            }
        }
        else {
            quit = true;
        }
    } while (!quit);
    cout << "----------------------------------------" << endl;
    cout << "Testing the display function" << endl;
    cout << "----------------------------------------" << endl;
    myCRA.display();
    cout << "----------------------------------------" << endl;

    return 0;
}

CRA_Account.cpp

#include <iostream>
#include "CRA_Account.h"
#include <cstring>

using namespace std;
using namespace sict;
    void CRA_Account::set(const char* familyName, const char* givenName, int sin) {
        int j;
        if (sin >= min_sin && sin <= max_sin) {
            socialInsuranceNumber = sin;
            for (j = 0; j <= max_name_length; j++) {
                family_name[j] = familyName[j];
            }
            for (j = 0; j <= max_name_length; j++) {
                given_name[j] = givenName[j];
            }
        }
        else {
            socialInsuranceNumber = 0;
        }
    }

    bool CRA_Account::isEmpty() const {
        bool empty = false;
        if (socialInsuranceNumber <= 0) {
            empty = true;
        }
        return empty;
    }
    void CRA_Account::display() const {

        if (isEmpty()) {
            cout << "Account object is empty!" << endl;
        }
        else {

            cout << "Family Name: " << family_name << endl;
            cout << "Given Name: " << given_name << endl;
            cout << "CRA Account: " << socialInsuranceNumber << endl;

        }
    }

CRA_Account.h

#ifndef CRA_ACCOUNT_H
#define CRA_ACCOUNT_H

namespace sict {
    static int max_name_length = 40;
    static int min_sin = 100000000;
    static int max_sin = 999999999;

    class CRA_Account {
    public:
    void set(const char* familyName, const char* givenName, int sin);
    bool isEmpty() const;
    void display() const;

    private:
        char family_name[40];
        char given_name[40];
        int socialInsuranceNumber = 0;

    };

}
#endif
Andrew
  • 1
  • 2
  • 3
    Use strings instead of char arrays. Please provide a [mcve]. – Ron Feb 14 '18 at 20:22
  • 4
    This looks iffy `j <= max_name_length` – Richard Critten Feb 14 '18 at 20:23
  • You should use `std::string` instead of `char array`, if you are required to use array, then use `strncpy()` instead of loop. – Slava Feb 14 '18 at 20:26
  • 1
    [Debug](http://idownvotedbecau.se/nodebugging/) and [minimze to relevant code](https://stackoverflow.com/help/mcve) before posting a question please! –  Feb 14 '18 at 20:27
  • [You're not the only person working on their taxes today](https://stackoverflow.com/questions/48793373/having-trouble-initiating-an-array-in-a-structure). You should consider teaming up. – user4581301 Feb 14 '18 at 20:37
  • @user4581301: lol... – Lightness Races in Orbit Feb 14 '18 at 20:38
  • Warning: `cin >> familyName;` cannot handle names like Von Doom, and trust me. You don't want to piss that guy off. – user4581301 Feb 14 '18 at 20:38
  • 1
    Or names like "in Orbit" – Lightness Races in Orbit Feb 14 '18 at 20:39
  • With the `cin.ignore();`s I think you're trying to avoid this problem: [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction), but without `getline` in play (even though it should be) there is no need for the ignore. `>>` automatically discards preceding whitespace. – user4581301 Feb 14 '18 at 20:43
  • And same advice I gave the other dude, `socialInsuranceNumber` is a number, but it's not used like a number. It is always and exactly 9 digits and 0 is a valid leading digit so, `static int min_sin = 100000000;` is not true and printing `socialInsuranceNumber` needs to prepend any leading 0s. If you really want to get fancy, there is a simple formula for validating SINs: multiply each digit by its corresponding digit in 121212121, sum the result, and if the numbers not divisible by 10, it's not valid. – user4581301 Feb 14 '18 at 20:53

1 Answers1

0

In C++ and C arrays indexes are 0 based, which means index is valid in [0,n-1] range inclusive. Common pattern to iterate is:

for( size_t i = 0; i < array_size; ++i )

some even prefer to write:

for( size_t i = 0; i != array_size; ++i )

so your loop:

for (j = 0; j <= max_name_length; j++) {

is wrong as it iterates over range [0,n] inclusive and leads to UB by accessing array with wrong index. In your case you copy part of memory where socialInsuranceNumber resides. So fix your loop and problem should disappear.

Note: you should use std::string instead of char array, this will not only simplify your code but make it less error prone. If you are required to use char array, then you should use strncpy() function from standard C library, not manual loop.

Slava
  • 40,641
  • 1
  • 38
  • 81
  • Is it really we have to answer _simple typo_ (well extended conception) questions like that over and over again? What about a comment and a close vote (or even better a dupe hammer)? –  Feb 14 '18 at 20:39
  • If you find dupe I will delete my answer, I swear – Slava Feb 14 '18 at 20:42
  • 1
    It's probably _too basic_ to find a better dupe than [The Definitive C++ Book Guide and List](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list) :-P ... But regarding my initial comment: You're getting in the way of _roomba_ (I don't really want to go into [depth about that matter](https://www.today.com/home/when-roomba-met-dog-poop-man-s-poopocalypse-goes-viral-t101883) further). –  Feb 14 '18 at 20:44
  • @Andrew Sure `strncpy()` requires another argument specifying the maximum size of your target buffer. –  Feb 14 '18 at 20:52