Invalid Null Pointer in user-defined Class? - c++

everyone. This is my first time using classes in C++. The instructions in the assignment I'm working on seemed a little ambiguous to me, so I'm including them in case someone more experienced thinks I'm not following them properly in my code.
Anyway, I wrote my program, and it works and creates the output I want based on my perception of the assignment. However, when I run it, an error also pops up that says "Invalid Null Pointer." I've done some research but I can't seem to figure out why this is.
Can someone help me fix my code and help a student understand what they did wrong? Thanks! :)
Assignment
Write a Person class that contains the following fields and methods:
• First Name
• Last Name
• ID Number
• Necessary constructors
•
Methods to return last name, first name, full name, and ID number
•
Methods to print last name, first name, and ID number
Write a main program to test your class.
My Program
#include <iostream>
#include <string>
using namespace std;
class Person {
private:
string FirstName;
string LastName;
string FullName;
int IDNumber;
public:
void SetFirstName(string);
void SetLastName(string);
void SetIDNumber(int);
string SetFullName(string first, string last);
string GetFirstName();
string GetLastName();
string Method1();
string Method2();
int GetIDNumber();
};
void Person::SetFirstName(string first) {
FirstName = first;
}
void Person::SetLastName(string last) {
LastName = last;
}
void Person::SetIDNumber(int ID) {
IDNumber = ID;
}
string Person::SetFullName(string first, string last) {
FullName = string(first + " " + last);
return FullName;
}
string Person::GetFirstName() {
return FirstName;
}
string Person::GetLastName() {
return LastName;
}
int Person::GetIDNumber() {
return IDNumber;
}
string Person::Method1() {
cout << "LAST NAME: " << LastName << endl;
cout << "FIRST NAME: " << FirstName << endl;
cout << "FULL NAME: " << FullName << endl;
cout << "ID NUMBER: " << IDNumber << endl;
return 0;
}
string Person::Method2() {
cout << "LAST NAME: " << LastName << endl;
cout << "FIRST NAME: " << FirstName << endl;;
cout << "ID NUMBER: " << IDNumber << endl;
return 0;
}
int main() {
string firstname, lastname;
int id;
char command;
Person Person;
cout << "What is the subject's first name? For example: Bob Smith" << endl;
cin >> firstname >> lastname;
cout << "What is " << firstname << " " << lastname << "'s ID number?" << endl;
cin >> id;
Person.SetFirstName(firstname);
Person.SetLastName(lastname);
string fullname = Person.SetFullName(firstname, lastname);
Person.SetIDNumber(id);
cout << "COMMANDS:" << endl;
cout << "f : Returns first name." << endl << "l : Returns last name." << endl << "i : returns ID number." << endl << "n : returns full name." << endl;
cout << "1 : Returns last name, first name, full name, and ID number." << endl;
cout << "2 : Returns last name, first name, and ID number." << endl << endl;
cout << "Please input the letter of your command: ";
cin >> command;
switch (command) {
case 'f':
case 'F':
cout << "FIRST NAME: " << Person.GetFirstName() << endl;;
break;
case 'l':
case 'L':
cout << "LAST NAME: " << Person.GetLastName() << endl;
break;
case 'i':
case 'I':
cout << "ID NUMBER: " << Person.GetIDNumber() << endl;
break;
case 'n':
case 'N':
cout << "FULL NAME: " << fullname << endl;
break;
case '1':
Person.Method1();
cout << endl;
break;
case '2':
Person.Method2();
cout << endl;
break;
default:
cout << "That is not a valid command." << endl;
}
}

string Person::Method1() {
// ...
return 0;
}
There's your problem.
Your method returns a std::string. 0, in this context, is treated as a NULL pointer, and your code blows up attempting to convert a NULL pointer into a string.
P.S. If you used a debugger to step through your code, a line at a time, you would've been able to figure it out yourself, instead of asking strangers on stackoverflow.com for help. Learning how to use a debugger is a required skill for every C++ developer.

Related

How to use struct members in a struct's member function?

So the purpose of the program is to Create an array of 3 people, allow the user to populate the data in a for loop, ensure that the results are capitalized, and output the results.
These new projects instructions were to
1. Rewrite capitalize() as a method within the structure.
2. Rewrite printPerson() as a method within the structure
The program itself works just fine, it's just not in the format that my professor wanted. He said the point of it is to not use any arguments but again, I don't know what he means. I just started programming a few months ago and even though I'm trying I don't have a strong knowledge of the terminology.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
struct Person {
string firstName;
string middleName;
string lastName;
int age;
string gender;
void capitalize(Person &arg);
void printPerson(Person arg);
};
Pretty sure these are the methods right here, but I'm not sure if the (person &arg) and (person arg) are the arguments itself or if they are parameters. I thought it was the "arg" part but I can't find a way to get the program to run without them as I'm pretty sure I need the & of operator to modify the information.
int main(void) {
Person myPerson;
Person a[3];
const int size = 5;
for (int i = 0; i <= 2; i++) {
cout << "What is First Name #" << i + 1 << "? ";
getline(cin, a[i].firstName);
cout << "What is Middle Name #" << i + 1 << "? ";
getline(cin, a[i].middleName);
cout << "What is Last Name #" << i + 1 << "? ";
getline(cin, a[i].lastName);
cout << "Age #" << i + 1 << "? ";
cin >> a[i].age;
cin.ignore();
cout << "Male or Female #" << i + 1 << "? ";
getline(cin, a[i].gender);
cout << endl;
}
for (int i = 0; i <= 2; i++) {
myPerson.capitalize(a[i]);
cout << "PERSON #" << i + 1 << endl;
cout << "~~~~~~~~~~~~~~~" << endl;
myPerson.printPerson(a[i]);
}
system("pause");
return 0;
}
Along with that, I don't know how to manipulate the functions to work without the "parameters/arguments" (I'm not sure the difference at this point) or without the "arg"
void Person::capitalize(Person &arg) {
transform(arg.firstName.begin(), arg.firstName.end(), arg.firstName.begin(), ::toupper);
transform(arg.middleName.begin(), arg.middleName.end(), arg.middleName.begin(), ::toupper);
transform(arg.lastName.begin(), arg.lastName.end(), arg.lastName.begin(), ::toupper);
}
void Person::printPerson(Person arg) {
cout << "\nFirst Name: " << arg.firstName << endl;
cout << "\nMiddle Name: " << arg.middleName << endl;
cout << "\nLast Name: " << arg.lastName << endl;
cout << "\nAge: " << arg.age << endl;
cout << "\nGender: " << arg.gender << endl;
cout << "\n\n";
}
The capitalize and the printPerson are now members (usually called methods) of the struct Person. This means that they operate on the member variables of an Person instance. Like this, you can just access all the classes members in these methods. See the following code. I also completed it with a constructor and made it slightly more readable.
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
struct Person {
public:
Person();
void readFromUserInput();
void capitalize();
void print();
public:
string firstName;
string middleName;
string lastName;
int age;
string gender;
};
Person::Person() :
firstName(""),
middleName(""),
lastName(""),
age(0),
gender("")
{
}
void Person::readFromUserInput()
{
cout << "What is the First Name ? ";
getline(cin, firstName);
cout << "What is Middle Name ? ";
getline(cin, middleName);
cout << "What is Last Name ? ";
getline(cin, lastName);
cout << "Age ? ";
cin >> age;
cin.ignore();
cout << "Male or Female ? ";
getline(cin, gender);
}
void Person::capitalize()
{
transform(firstName.begin(), firstName.end(), firstName.begin(), ::toupper);
transform(middleName.begin(), middleName.end(), middleName.begin(), ::toupper);
transform(lastName.begin(), lastName.end(), lastName.begin(), ::toupper);
}
void Person::print()
{
cout << "\nFirst Name: " << firstName << endl;
cout << "\nMiddle Name: " << middleName << endl;
cout << "\nLast Name: " << lastName << endl;
cout << "\nAge: " << age << endl;
cout << "\nGender: " << gender << endl;
cout << "\n\n";
}
int main(void)
{
const int NUM_PERSONS = 3;
Person a[NUM_PERSONS];
for (int i = 0; i < NUM_PERSONS; i++)
{
cout << "### " << (i + 1) << ". User:" << endl;
a[i].readFromUserInput();
cout << endl;
}
for (int i = 0; i < NUM_PERSONS; i++)
{
a[i].capitalize();
cout << "PERSON #" << i + 1 << endl;
cout << "~~~~~~~~~~~~~~~" << endl;
a[i].print();
}
system("pause");
return 0;
}

How to get variable values from main and send them to a function?

I have encountered a problem while running this code in my IDE. You can see very early on that I've attempted to use a function. The reason for this is to save memory later on by outputting text, but the problem occurs with the variables in the function. The classType variable is uninitialized, how do I prevent this? I have defined them in main, but when I try to output the text with the variables from main then it doesn't work properly.
#include<iostream>
using namespace std;
string getName()
{
   string charName;
   int classType;
   cout << "What is your " << classType << "'s name?" << endl;
   cin >> charName;
   return charName;
}
int main()
{
   int classType; //Later we will ask the user what class they're playing.  
   string charName;
   /*We will use a function to ask a question.  
   We use a function to save memory instead of copy-pasting the text*/
   cout <<"Welcome to \"Orcs and Ogres\"" << endl;
   cout << "What class do you want to play?  " << endl;
   cout << "\tType 1 for Warrior class]" << endl;
   cout << "\tType 2 for Archer class ]" << endl;
   cout << "\tType 3 for Mage class   ]" << endl;
   cin >> classType;
   if(classType == 1)
   {
       cout << endl << "You are a warrior" << endl;
       string classType;
       classType = "warrior";
       getName();
   }
   else if(classType == 2)
   {
       cout << endl << "You are an archer" << endl;
       string classType;
       classType = "archer";
       getName();
   }
   else if(classType == 3)
   {
       cout << endl << "You are a mage" << endl;
       string classType;
       classType = "mage";
       getName();
   }
   else
   {
       cout << endl << "UserError:  Number too high or too low";
   }
}
On the lines of code that use getName(), it outputs something like "What is your blank's name?" instead of the proper classType. I want to know how I can send variable values to a function from main so that it outputs text properly here.
The reason why it's not working is because your getName function has no knowledge of whats stored in the classType variable. Read on how function variable scope works to understand the whole mechanism works might be beneficial.
If you wish to keep the current implementation of your program. Re-write your getName function to accept the string class as a parameter
string getName(string classType)
{
string charName;
cout << "What is your " << classType << "'s name?" << endl;
cin >> charName;
return charName;
}
and in your main you'd call the function as follow :
getName("Warrior"); // to ask warrior for a warriors' name
getName("Mage"); // to ask for a mage's name.
You may also want to add to include the string library at the top of your file as not having it might also cause your code to simply not work. As well as making sure to properly store the name returned from your getName() function as follow :
string name = getName("Warrior");
Also , as others have said , maybe reading a bit more on how function receive and return values might be beneficial to you.
It is as simple as this. Try this updated code...
#include<iostream>
using namespace std;
string getName(string classType)
{
string charName;
cout << "What is your " << classType << "'s name?" << endl;
cin >> charName;
cout<<"your "<<classType<< "'s name is "<<charName<<endl;
return charName;
}
int main()
{
int Type;
string charName;
cout <<"Welcome to \"Orcs and Ogres\"" << endl;
cout << "What class do you want to play? " << endl;
cout << "\tType 1 for Warrior class]" << endl;
cout << "\tType 2 for Archer class ]" << endl;
cout << "\tType 3 for Mage class ]" << endl;
cin >> Type;
if(Type == 1)
{
cout << endl << "You are a warrior" << endl;
string classType;
classType = "warrior";
getName("warrior");
}
else if(Type == 2)
{
cout << endl << "You are an archer" << endl;
string classType;
classType = "archer";
getName("archer");
}
else if(Type == 3)
{
cout << endl << "You are a mage" << endl;
string classType;
classType = "mage";
getName("mage");
}
else
{
cout << endl << "UserError: Number too high or too low";
}
return 0;
}

How to iterate over string variables of a class object in C++?

So here I have a class definition of a Car and then I create a carObject with it. I want the user to input values for all the variables in the carObject. As you see here, I have managed to get user input, but my approach to this problem is inefficient in my opinion.
I notice that all of the user inputs, except for the first one are very similar. I would like to use a loop of some kind to iterate over the declaration statements, or blocks of statements, and change the variable every time. I would like to put an if statement to enter different input only for the first iteration of the loop. I know that in bash I could use a string variable to stand for the variable name, but I don't know if that's possible in C++.
Notice that the object name does not change, but only the variables that are associated with it. I also use the same word for the user input, which preferably should be changed every iteration. I also have a series of arrays which are named similarly. The purpose of these arrays is to tell the user what options are available for a particular variable.
Although I have previous programming experience, I am relatively new to C++. A block of code that would serve as a solution to my problem that involves a call to another function would suit my purposes. Here is my code below.
#include <iostream>
#include <string>
using namespace std;
class Car {
public:
string Name;
string Model;
string Color;
string Transmission;
string Category;
};
int main() {
Car CarObject;
string modelOptions [3] = { "Ferrari", "Porsche", "Nissan" };
string colorOptions [4] = { "Blue", "Red", "Green", "White" };
string transmisionOptions [2] = { "Automatic", "Manual" };
string categoryOptions [3] = { "A", "B", "C" };
cout << "Enter " << "name" << " for Car 1." << endl;
cin >> carObject.Name;
cout << endl;
cout << "Enter " << "model" << " for Car 1." << endl;
cout << "Options are:";
for (const string &text: modelOptions) {
cout << " " << text;
}
cout << "." << endl;
cin >> carObject.Model;
cout << endl;
cout << "Enter " << "color" << " for Car 1." << endl;
cout << "Options are:";
for (const string &text: colorOptions) {
cout << " " << text;
}
cout << "." << endl;
cin >> carObject.Color;
cout << endl;
cout << "Enter " << "transmission" << " for Car 1." << endl;
cout << "Options are:";
for (const string &text: transmissionOptions) {
cout << " " << text;
}
cout << "." << endl;
cin >> carObject.Transmission;
cout << endl;
cout << "Enter " << "category" << " for Car 1." << endl;
cout << "Options are:";
for (const string &text: categoryOptions) {
cout << " " << text;
}
cout << "." << endl;
cin >> carObject.Category;
cout << endl;
...
return 0;
}
void Car::InputParameter(string& param, const string &msg, const vector<string>& options)
{
cout << msg << endl;
for (const string &text: options) {
cout << " " << text;
}
cout << "." << endl;
cin >> param;
cout << endl;
}
I think you might want something like this. You just call it for each member.
This block of code:
cout << "Enter " << "category" << " for Car 1." << endl;
cout << "Options are:";
for (const string &text: categoryOptions) {
cout << " " << text;
}
cout << "." << endl;
cin >> carObject.Category;
cout << endl;
… can be replaced with a call to a function like this:
carObject.Category = userInput( "category", categoryOptions );
Clearly it returns a string (that is, a std::string).
The options argument should better be made a vector<string>.
Then just replace the other similar blocks with ditto calls to that function.
Is it a good idea to make that function a member function of Car?
No.
Consider, for example, how to then use Car in a GUI program (Graphical User Interface).

Program not saving inputted entries? (C++) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
I am supposed to make a class AddressBook containing a class called Person. My program almost, works, except when I add a person, it doesn't remember it in the next iteration of the Command menu and Display All turns up "There are 0 people in your address book." What is wrong with my code?
#include <iostream>
#include <string>
using namespace std;
class AddressBook {
public:
class Person
{
public:
char firstName[15];
char lastName[15];
char personID[15];
};
Person entries[100];
unsigned int total;
AddressBook()
{
total = 0;
}
void AddPerson()
{
cout << "This is entry number " << (total + 1) << " in your address book. " << endl;
cout << "What shall we put for the first and last name? Limit both to under 15 characters. Example: Bob Smith" << endl;
cin >> entries[total].firstName >> entries[total].lastName;
cout << "What is " << entries[total].firstName << " " << entries[total].lastName << "'s ID code?" << endl;
cin >> entries[total].personID;
++total;
cout << "..." << endl << "Successfully Added." << endl;
};
void DisplayPerson(int i)
{
cout << "Entry " << i + 1 << ": " << endl;
cout << "FIRST NAME: " << entries[i].firstName << endl;
cout << "LAST NAME: " << entries[i].lastName << endl;
cout << "ID: " << entries[i].personID << endl;
};
void DisplayEveryone()
{
cout << "You have " << total << " People in your address book." << endl;
for (int i = 0; i < total; ++i)
DisplayPerson(i);
};
void SearchPerson()
{
char lastname[32];
cout << "Please enter the last name of the person you wish to find." << endl;
cin >> lastname;
for (int i = 0; i < total; ++i)
{
if (strcmp(lastname, entries[i].lastName) == 0)
{
cout << "Person Found. " << endl;
DisplayPerson(i);
cout << endl;
}
}
};
};
int main() {
char command;
bool Exit = false;
while (Exit == false)
{
AddressBook Address_Book;
cout << "---------------COMMANDS---------------" << endl;
cout << "A: Add Person To Address Book" << endl;
cout << "S: Search for Person in Address Book" << endl;
cout << "D: Display Everyone In Address Book" << endl << endl;
cout << "Type the letter of your command: ";
cin >> command;
cout << endl;
switch (command) {
case 'A':
case 'a':
Address_Book.AddPerson();
break;
case 'S':
case 's':
Address_Book.SearchPerson();
break;
case 'D':
case 'd':
Address_Book.DisplayEveryone();
break;
default:
cout << "That is not a valid command. Closing Address Book." << endl;
cout << endl;
}
}
}
The reason is that you create a new address book in each iteration of the while loop and throw it away at the end of the iteration:
This
AddressBook Address_Book;
creates a new address book that is "thrown away" when you reach the end of its scope (ie. the end of the loop).
In reality, do you buy a new address book whenever you want to make new entry? No. You first buy the book and then (possibly in a while loop) you add entries. Move the above line outside of the loop.
Your problem is in the declaration of your address book.
Change it to the following:
AddressBook Address_Book;
while (Exit == false) {
//Ask for input and respond.
}
In your version Address_Book is declared at the start of the while loop. This means that every time an iteration of the loop completes and execution returns to the start of the block, a new local Address_Book object is created that has no knowledge of the previous objects data.

I Think my code is perfect but the output is not proper

Here's my code:
#include <iostream>
#include <string>
using namespace std;
class Personal_Record {
public:
Personal_Record();
Personal_Record(string nam, string dob, string addr, int mobNum, string ema, string hob);
void Get_PersonalRecord();
void Display_PersonalRecord();
protected:
string name;
string dateOfBirth;
string address;
int mobileNumber;
string emailId;
string hobby;
};
Personal_Record::Personal_Record()
{
name = "";
dateOfBirth = "";
address = "";
hobby = "";
}
Personal_Record::Personal_Record(string nam, string dob, string addr, int mobNum, string ema, string hob)
{
name = nam;
dateOfBirth = dob;
address = addr;
mobileNumber = mobNum;
emailId = ema;
hobby = hob;
}
void Personal_Record::Get_PersonalRecord()
{
cout << endl << "Enter the name of the person: ";
cin >> name;
cout << endl << "Enter the date of birth: ";
cin >> dateOfBirth;
cout << endl << "Enter the address: ";
cin >> address;
cout << endl << "Enter the mobile number: ";
cin >> mobileNumber;
cout << endl << "Enter the e-mail id: ";
cin >> emailId;
cout << endl << "Enter any hobby the person has: ";
cin >> hobby;
}
void Personal_Record::Display_PersonalRecord()
{
cout << "Personal Record:" << endl << endl;
cout << "1.Name: " << name << endl;
cout << "2.Date Of Birth: " << dateOfBirth << endl;
cout << "3.Address: " << address << endl;
cout << "4.Mobile Number: " << mobileNumber << endl;
cout << "5.E-mail Id: " << emailId << endl;
cout << "6.Hobby" << hobby << endl;
}
class Professional_Record {
public:
Professional_Record();
Professional_Record(string nameOfCom, string pos, int xp);
void Get_Professional_Record();
void Display_Professional_Record();
protected:
string nameOfCompany;
string position;
int experienceInYears;
};
Professional_Record::Professional_Record()
{
nameOfCompany = "";
position = "";
experienceInYears = 0;
}
Professional_Record::Professional_Record(string nameOfCom, string pos, int xp)
{
nameOfCompany = nameOfCom;
position = pos;
experienceInYears = xp;
}
void Professional_Record::Get_Professional_Record()
{
cout << endl << "Enter name of the company: ";
cin >> nameOfCompany;
cout << endl << "Enter position in this company: ";
cin >> position;
cout << endl << "Enter number of years of experience: ";
cin >> experienceInYears;
}
void Professional_Record::Display_Professional_Record()
{
cout << "Professional Record: " << endl << endl;
cout << "Name of the Company: " << nameOfCompany << endl;
cout << "Position in this company: " << position << endl;
cout << "Number of years of experience: " << experienceInYears << endl;
}
class Academic_Record {
public:
Academic_Record();
Academic_Record(string nameOfCou, string nameOfCol, int passOut, float percent, string special);
void Get_Academic_Record();
void Display_Academic_Record();
protected:
string nameOfCourse;
string nameOfCollege;
int passOutYear;
float percentage;
string specialization;
};
Academic_Record::Academic_Record()
{
nameOfCourse = "";
nameOfCollege = "";
passOutYear = 0;
percentage = 0.0;
specialization = "";
}
Academic_Record::Academic_Record(string nameOfCou, string nameOfCol, int passOut, float percent, string special)
{
nameOfCourse = nameOfCou;
nameOfCollege = nameOfCol;
passOutYear = passOut;
percentage = percent;
specialization = special;
}
void Academic_Record::Get_Academic_Record()
{
cout << endl << "Enter the name of the course: ";
cin >> nameOfCourse;
cout << endl << "Enter the name of the college: ";
cin >> nameOfCollege;
cout << endl << "Enter year of passout: ";
cin >> passOutYear;
cout << endl << "Enter the percentage: ";
cin >> percentage;
cout << endl << "Enter the subject the person has specialized in: ";
cin >> specialization;
}
void Academic_Record::Display_Academic_Record()
{
cout << endl << "Academic Details:" << endl;
cout << "Name of the Course: " << nameOfCourse << endl;
cout << "Name of the College: " << nameOfCollege << endl;
cout << "Year of passout: " << passOutYear << endl;
cout << "Percentage acquired: " << percentage << endl;
cout << "The person has specialized in: " << specialization << endl;
}
class Bio_Data : public Personal_Record, public Professional_Record, public Academic_Record {
public:
void Display_BioData();
};
void Bio_Data::Display_BioData()
{
Display_PersonalRecord();
Display_Professional_Record();
Display_Academic_Record();
}
int main()
{
Bio_Data bd;
cout << "Enter Personal Information: " << endl << endl;
bd.Get_PersonalRecord();
cout << "Enter Professional Information: " << endl << endl;
bd.Get_Professional_Record();
cout << "Enter Academic Information: " << endl << endl;
bd.Get_Academic_Record();
bd.Display_BioData();
return 0;
}
Output of the following code:
Enter Personal Information:
Enter the name of the person: Suraj
Enter the date of birth: 02/04/1996
Enter the address: Varnam,A/38,Pune
Enter the mobile number: 8552004340
Enter the e-mail id:
Enter any hobby the person has: Enter Professional Information:
Enter name of the company:
Enter position in this company:
Enter number of years of experience: Enter Academic Information:
Enter the name of the course:
Enter the name of the college:
Enter year of passout:
Enter the percentage:
Enter the subject the person has specialized in: Personal Record:
1.Name: Suraj
2.Date Of Birth: 02/04/1996
3.Address: Varnam,A/38,Pune
4.Mobile Number: 2147483647
5.E-mail Id:
6.Hobby
Professional Record:
Name of the Company:
Position in this company:
Number of years of experience: 0
Academic Details:
Name of the Course:
Name of the College:
Year of passout: 0
Percentage acquired: 0
The person has specialized in:
The problem here is that after taking the mobile number it doesn't give me a prompt for email id or taking input for any other fields.It just gives me the output.And even in the output the mobile no. is turned into some garbage value not the original no. I entered.I really don't know whats going on.Can someone help me!
I have run the code on ubuntu and c++ shell online and they both seem to give me same results.
I don't know what this problem is called so don't get angry at me for asking this question!
You are storing the mobile number as an int, which has a max size of 32767 http://www.cplusplus.com/reference/climits/
8552004340 is too big!
Better to store it as a string.