std::string’ has no member named ‘get_name' - c++

I keep getting this error,
error: ‘std::string’ has no member named ‘get_name’
cout << name.get_name() << name.get_won() << name.get_lost << endl << endl;
even though 'name = name_of_player;' and 'cout << name;' prints the correct name. I am guessing that it is taking the variable and not the actual string? I am not entirely sure, thus I need help.
#include <iostream>
#include <string>
using namespace std;
class person {
string name_;
int won_;
int lost_;
public:
void set_name(string);
void set_wl(int,int);
int get_won() const {return won_;}
int get_lost() const { return lost_;}
string get_name() const {return name_;}
};
void person :: set_name(string n) {
name_ = n;
}
void person :: set_wl(int x, int y) {
won_ = x; lost_ = y;
}
int number_of_players;
string name;
string name_of_player[31];
int counter;
void get_player()
{
counter = 1; //Initiating the counter
cout << endl << "Ok! Now we are going to enter their names in. " << endl;
for (int i=1; number_of_players >= i; i++)
{
cout << "Enter player #" << counter << "'s name... " << endl;
cout << "The max is 30 players... " << endl;
getline (cin, name);
cout << endl;
cout << "Okay, so player #" << counter << " is " << name << "." << endl;
cout << "Please press Enter to continue..." << endl;
cin.ignore();
name_of_player[counter] = name;
person name;
name.set_name(name_of_player[counter]);
name.set_wl(0,0);
counter = (counter + 1);
}
}
void list_players()
{
counter = 1; //initiating the counter
cout << "Here are the current players with their respective win/loss ration... " << endl << endl;
for (int i=1; number_of_players >= i; i++)
{
name = name_of_player[counter];
cout << name.get_name() << name.get_won() << name.get_lost << endl << endl;
counter = counter +1;
}
}
int main()
{
cout << "Welcome to the Chess Tournament Organizer. " << endl;
cout << "How many people will be playing today? " << endl;
cin >> number_of_players;
cin.ignore();
get_player();
list_players();
return (0);
}
******************************************************************************
EDIT: I have solved it and figured it out, past all of my terrible code. The problem was, for every name, I was creating a class of 'person' with that name. But this was bad because it was a local scope. So what I did was change the global string 'name_of_players' to a global variable of the person class with
person name_of_player[31];
Changing also...
cout << "Enter player #" << counter << "'s name... " << endl;
cout << "The max is 30 players... " << endl;
getline (cin, name);
cout << endl;
cout << "Okay, so player #" << counter << " is " << name << "." << endl;
cout << "Please press Enter to continue..." << endl;
cin.ignore();
name_of_player[counter].set_name(name);
name_of_player[counter].set_wl(0,0);
And doing the same to the 'list_of_players' function.
I am still not completely sure why it didn't work, I wanted several 'person's identified by their names, created by using the name given. So if a user were to input "mike" there would be a person class called mike, and I could find the information of the person class mike, by inputing mike.get_info();
TL;DR
I needed to fix the scope and not run my string as a name of the person class for each person.

name_of_player is defined as an array of 31 strings:
string name_of_player[31];
You get the element from that array enumerated by counter when you do:
name = name_of_player[counter];
So name is a string. strings do not have a get_name method.
You may be confused about what name is cause you define a local person name in get_player, but then you never use that locally defined name.
An ugly way to solve this would be to create another global where you declare name_of_player as:
person stats_of_player[31];
Then at the bottom of the for-loop in get_player you can assign the locally declared variable to the global array:
stats_of_player[counter] = name;
You would then be able to use stats_of_player in list_players instead of your for-loop as follows:
for (int i=1; number_of_players >= i; i++)
{
cout << stats_of_player[i].get_name() << stats_of_player[i].get_won() << stats_of_player[i].get_lost() << endl << endl;
}

name_of_player is array of strings, not person objects. So you trying to call get_name on string object and this is why you are getting such error.

Running your code I get that std::string has no member named get_name, get_won, or get_lost. This is because you are trying to invoke those methods on a c++ string object, which does not have those methods.
Furthermore it seems like you expect name_of_player to be an array of players when it is in fact an array of strings.
Because the methods of your person class are public and not static you need an instance of your person class to invoke those methods (outside of the class definition e.g. main).
void get_player() {
....
player p();
p.set_name("Bob");
p.get_name();
...
}

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).

error C2601: "Name": local function definitions are illegal

I'm new to C++ and learning about Inheritance and Polymorphism. We require to write an employee project that have 4 types of employee (BasePlusCommission, CommisisonEmployee, Salaried and TipWorker). My project has one main() class that I used switch method for each type of employee. I got stuck on TipWorker where we have to do Polymorphism. Here what I got so far.
int main()
{
void virtualViaPointer(const Employee * const);
{
cout << "Enter First Name: " << endl;
cin >> firstName;
cout << "Enter Last Name: " << endl;
cin >> lastName;
cout << "Enter SSN: " << endl;
cin >> SSN;
if (SSN.length() == 9)
{
SSN = true;
}
else
{
cout << "Please enter SSN again with 9 digits only:" << endl;
cin >> SSN;
}
cout << "Enter wages: " << endl;
cin >> wage;
cout << "Enter hours: " << endl;
cin >> hours;
cout << "Enter tips: " << endl;
cin >> tips;
TipWorker employee4(firstName, lastName, SSN, wage, hours, tips);
employee4.print();
cout << fixed << setprecision(2);
vector < Employee * > employees(1);
employees[0] = &employee4;
cout << "Employee processed polymorphically via dynamic binding: \n\n";
cout << "Virtual function calls made off base-class pointers:\n\n";
for (const Employee *employeePtr : employees)
virtualViaPointer(employeePtr);
void virtualViaPointer(const Employee * const baseClassPtr)
{
baseClassPtr->print();
cout << "\nEarned $" << baseClassPtr->earnings() << "\n\n";
}
break;
}
}
When I run the project, I came up with this error:
error C2601: "virtualViaPointer": local function definitions are
illegal
void virtualViaPointer(const Employee * const baseClassPtr)
{
baseClassPtr->print();
cout << "\nEarned $" << baseClassPtr->earnings() << "\n\n";
}
Can anyone please help me? Thank you so much!
You may not define one function inside an other function. Any function definition shall be outside any other function definition.
Place the definition of virtualViaPointer outside the body of main.
You can have a declaration of a function inside a function, but no definition(!) of that function. However, you can have a local struct/class or lambda in the function:
#include <iostream>
void f()
{
void print(); // mostly useless - maybe a most vexing parse error
struct Print {
static void apply(const char* s) { std::cout << s << '\n'; }
}
Print::apply("Hello");
auto lambda = [] (const char* s) { std::cout << s << '\n'; };
lambda("World");
}
Note: A local struct does not require C++11 (Also, it may look nicer while debugging)

C++ doesn't convert string from data

I want to write a little program which should be used in supermarkets. everything is fictitious and it's only for learning purposes.
However, The tool generate a new data for every new article. in the data there are 2 lines, the name and the prise.
The data is named as the article number of the product. So the user enter a articlenumber and the tool looks for a data with this number, if it found it, it reads the 2 lines and initiates the variables.
But for some reasons it does not convert and copy the strings correctly.
here is the part which loads the data.
int ware::load()
{
string inhalt;
cout << "please insert article number" << endl;
cin >> articlenumber;
productname.open(articlenumber, ios::in);
if (!productname.is_open())
{
cout << "can't find the product." << endl;
return 1;
}
if (productname.is_open())
{
while (!productname.eof())
{
getline(productname, inhalt);
strcpy(name,inhalt.c_str());
getline(productname, inhalt);
price = atoi (inhalt.c_str());
cout << inhalt << endl;
}
warenname.close();
}
cout << endl << endl <<
"number: " << inhalt <<
" preis: " << price <<
" name: " << name <<
endl << endl; //this is a test and will be deleted in the final
}
hope you can help me!
Here is the class:
class ware{
private:
char articlenumber[9];
char name[20];
int price;
fstream warennamefstream;
ifstream warenname;
public:
void newarticle(); //this to make a new product.
void scan(); //this to 'scan' a product (entering the article number ;D)
void output(); //later to output a bill
int load(); //load the datas.
};
hope everything is fine now.
First, you have a using namespace std; somewhere in your code. This occasionally leads to subtle bugs. Delete it. ( Using std Namespace )
int ware::load()
{
string inhalt;
cout << "please insert article number" << endl;
cin >> articlenumber;
The type of articlenumber is incorrect. Declare it std::string, not char[]. ( What is a buffer overflow and how do I cause one? )
productname.open(articlenumber, ios::in);
There is no reason to have an ifstream lying around waiting to be used. Also, there is no point in providing ios::in -- it is the default. Just use the one-argument form of the ifstream constructor.
if (!productname.is_open())
{
cout << "can't find the product." << endl;
return 1;
}
Don't bother checking to see if the file opened. Your users don't care if the file was present or not, they care whether the file was present AND you retrieved the essential data.
if (productname.is_open())
{
while (!productname.eof())
{
getline(productname, inhalt);
strcpy(name,inhalt.c_str());
getline(productname, inhalt);
price = atoi (inhalt.c_str());
cout << inhalt << endl;
}
warenname.close();
}
This loop is just wrong.
Never invoke eof(). It doesn't do what you think it does, and will cause bugs.
Why is this a loop? Aren't there only two lines in the file?
There is no point in calling close. Just let the file close when the istream goes out of scope.
Why is warename different than productname?
Don't store your data in char[]. This is the 21st century. Use std::string.
.
cout << endl << endl <<
"number: " << inhalt <<
" preis: " << price <<
" name: " << name <<
endl << endl; //this is a test and will be deleted in the final
Never use endl when you mean to say '\n'. Each of those endl manipulators invokes flush, which can be very expensive. ( What is the C++ iostream endl fiasco? )
You forgot to return a value.
Try this instead:
int ware::load()
{
// This declaration should be local
std::string articlenumber;
cout << "please insert article number" << endl;
cin >> articlenumber;
// This declaration should be local
std::ifstream productname(articlenumber.c_str());
// These declarations can be class members:
std::string name;
int price;
std::string number;
if(getline(productname, name) &&
productname>>price &&
productname>>number)
{
cout << "\n\n" <<
"number: " number <<
" preis: " << price <<
" name: " << name <<
"\n\n"; //this is a test and will be deleted in the final
return 0;
} else {
cout << "can't find the product." << endl;
return 1;
}
}