error C2601: "Name": local function definitions are illegal - c++

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)

Related

Make a String Variable a Class Name in C++

I'm working on a program in C++ to make schedules for me, since I have a hard time focusing on school work. The code will make priorities of assignments based on the due dates, duration to do the assignments, etc.
Anyway, I've run into a massive problem. I'm trying to assign a class variable's name to a variable! For example:
string a = "assignmentName" Class a(); //a is a variable and it's supposed to put the class's name as assignmentName
If you don't think this way will work, please tell me other solutions!
Also, I'm still a beginner, so please try to explain a little simple!
Here's the code:
#include <string>
#include <iostream>
using namespace std;
class Assignment
{
private:
int duration = 30; //Amount of time per assignment (in minutes)
int due = 1; //Amount of days till its due, if it's one then the assignment is due in 1 days
string name; //Name of assignment
public:
Assignment(int, int, string);
~Assignment();
void setDuration(int duration) {this -> duration = duration;}
void setDue(int due) {this -> due = due;}
void setDue(int name) {this -> name = name;}
int getDuration() { return duration; }
int getDue() { return due; }
string getName() { return name; }
};
Assignment::Assignment (int duration, int due, string name) //Constructor Method
{
this -> duration = duration;
this -> due = due;
this -> name = name;
}
Assignment::~Assignment() //Destructor Method
{
cout << "Assignment Object Destroyed" << endl;
}
int main()
{
int assignmentAmount;
int i;
int userInput1;
int userInput2;
string userInput3;
cout << "Enter assignment amount: ";
cin >> assignmentAmount << "\n" << endl;
for (i = 0; i < assignmentAmount; i++){
cout << "Enter assignment" << i <<"'s " << "duration: ";
cin >> userInput1 << endl;
cout << "Enter assignment" << i << "'s " << "due date in days from now: ";
cin >> userInput2 >> endl;
cout << "Enter assignment" << i <<"'s " << "name: ";
cin >> userInput3 >> endl;
Assignment i(userInput1, userInput2, userInput3); //I is the class's number and it's supposed to be a variable
}
return 0;
}
What you are looking for is an array of Assignment objects, eg:
int main()
{
Assignment *assignments;
int assignmentAmount;
int userInput1;
int userInput2;
string userInput3;
cout << "Enter assignment amount: ";
cin >> assignmentAmount << "\n" << endl;
assignments = new Assignment[assignmentAmount];
for (int i = 0; i < assignmentAmount; i++){
cout << "Enter assignment " << i << "'s duration: ";
cin >> userInput1 << endl;
cout << "Enter assignment " << i << "'s due date in days from now: ";
cin >> userInput2 >> endl;
cout << "Enter assignment " << i <<"'s name: ";
cin >> userInput3 >> endl;
// either:
assignments[i] = Assignment(userInput1, userInput2, userInput3);
// or:
assignments[i].setDuration(userInput1);
assignments[i].setDue(userInput2);
assignments[i].setName(userInput3);
}
// use assignments and assignmentAmount as needed...
delete[] assignments;
return 0;
}
Though, you should use std::vector instead of new[] directly:
#include <vector>
...
int main()
{
std::vector<Assignment> assignment;
int assignmentAmount;
int userInput1;
int userInput2;
string userInput3;
cout << "Enter assignment amount: ";
cin >> assignmentAmount << "\n" << endl;
for (int i = 0; i < assignmentAmount; i++){
cout << "Enter assignment " << i << "'s duration: ";
cin >> userInput1 << endl;
cout << "Enter assignment " << i << "'s due date in days from now: ";
cin >> userInput2 >> endl;
cout << "Enter assignment " << i << "'s name: ";
cin >> userInput3 >> endl;
// either:
assignments.push_back(Assignment(userInput1, userInput2, userInput3));
// or:
assignments.emplace_back(userInput1, userInput2, userInput3);
}
// use assignments as needed...
return 0;
}
Or:
#include <vector>
...
int main()
{
std::vector<Assignment> assignment;
int assignmentAmount;
int userInput1;
int userInput2;
string userInput3;
cout << "Enter assignment amount: ";
cin >> assignmentAmount << "\n" << endl;
assignments.resize(assignmentAmount);
for (int i = 0; i < assignmentAmount; i++){
cout << "Enter assignment " << i << "'s duration: ";
cin >> userInput1 << endl;
cout << "Enter assignment " << i << "'s due date in days from now: ";
cin >> userInput2 >> endl;
cout << "Enter assignment " << i << "'s name: ";
cin >> userInput3 >> endl;
// either:
assignments[i] = Assignment(userInput1, userInput2, userInput3);
// or:
assignments[i].setDuration(userInput1);
assignments[i].setDue(userInput2);
assignments[i].setName(userInput3);
}
// use assignments as needed...
return 0;
}
You can't get variable names as a variable, since a variable is basically like an alias to the data, when your program gets compiled all these names, don't exist anymore.
The compiler does not emit symbol names to the executable (the debug version may have symbol names).
If you want to associate or map symbol names to variables, you will need to declare the variable global and place the address into some kind of table.
Example:
int my_global_int_a;
std::map<std::string, int *> variable_dictionary;
variable_dictionary["my_global_int_a"] = &my_global_int_a;
// Here's how to get the variable
const std::string variable_name = "my_global_int_a";
int * p_variable = nullptr;
p_variable = variable_dictionary[variable_name];
std::cout << *p_variable << std::endl;
You may want to give deep thought to the need of retaining variable names.

How to create a function to read/write data to struct members?

I'm trying to create a program that read and print students' data with c++. for that, I've created a struct Student, a function to read data from the user and assign it to a struct instance s1 and a function to print students' data on the screen, and I think the problem is with the function that read/write data.
Here is the my code:
#include<iostream>
#include<string>
using namespace std;
struct Student
{
char name[30];
int age;
double gpa;
string department;
};
Student read_data(Student x)
{
cout << "Name (30 characters maximum): ";
cin.get(x.name, 30);
cout << "Age: ";
cin >> x.age;
cout << "Department: ";
cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
return x;
}
void print_data(Student x)
{
cout <<
"\n***************************************************************" << endl;
cout << "Name: " << x.name << endl;
cout << "Age: " << x.age << endl;
cout << "Department: " << x.department << endl;
cout << "GPA: " << x.gpa << endl;
}
int main()
{
Student s1, s2, s3;
cout << "This program stores -Temporarily- data of three students\n" << endl;
cout << "Enter 1st student's data" << endl;
read_data(s1);
print_data(read_data(s1));
system("pause");
return 0;
}
The output of this code is:
This program stores data of three students
Enter 1st student's data
Name (30 characters maximum): Ahmed Maysara
Age: 22
Department: CS
GPA: 3.5
Name (30 characters maximum): Age: Department: GPA:
***************************************************************
Name:
Age: -858993460
Department:
GPA: -9.25596e+61
Press any key to continue . . .
As you see, the output is out of my expectations :) ..
Any help ?!
Both CinCout and David are correct.
There are a couple of problems with your code as it now stands.
The first problem is that while you successfully call the function read_data(s1), s1 is a just a copy. So, when the function sets all of the values for the student using cin, it is really just setting a copy's values. You can either make it so that you are passing in the original, or you can return the student (which you are doing) and set s1 equal to the result (which you are not).
To make sure that you pass in the original, you can go to where you declared read_data. Instead of saying Student read_data(Student x), you should place an ampersand after the parameter that you don't want to copy Student read_data(Student &x). This is called passing by reference (you reference the original instead of referencing by copy)
Alternatively, you could con just set s1 to the result where you call it in main. You could say s1 = read_data(s1); and that would work fine, though a bit more inefficiently.
Lastly, the other glaring error in the code is that you accidentally call read_data again when you say print_data(read_data(s1)). Instead, say print_data(s1).
Instead of passing and returning the structure object each time on call of read_data and print_data we could add those inside the structure itself, We could create object of Student and call the functions read and print within the same.
struct Student
{
char name[30];
int age;
double gpa;
string department;
Student(): age(0), gpa(0)
{
memset( name, 0, 30 );
}
void read()
{
cout << "\nName (30 characters maximum): ";
cin.get(name, 30);
cout << "\nAge: ";
cin >> age;
cout << "\nDepartment: ";
cin >> department;
cout << "\nGPA: ";
cin >> gpa;
}
void print()
{
cout << "\n***************************************************************" << endl;
cout << "Name: " << name << endl;
cout << "Age: " << age << endl;
cout << "Department: " << department << endl;
cout << "GPA: " << gpa << endl;
}
};
int main()
{
Student s1;
s1.read();
s1.print();
return 0;
}
You are passing copy of s1 into the read_data function, but not bothering to update the value based on the return arg. i.e. something like this should work.
s1 = read_data(s1);
print_data(s1);
Alternatively, pass by reference instead of value:
void read_data(Student& x)
{
cout << "Name (29 characters maximum): "; // requires null terminator
cin >> x.name; // just read into the buffer directly
cout << "Age: ";
cin >> x.age;
cout << "Department: ";
cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
}
And then later:
read_data(s1);
print_data(s1);
change you read_data with something like this
void read_data(Student& x)
{
cout << "Name (30 characters maximum): ";
///cin.get(x.name, 30);
cin.getline(x.name, 30);
cout << "Age: ";
cin >> x.age;
cin.ignore();
cout << "Department: ";
std::getline(cin, x.department);
///cin >> x.department;
cout << "GPA: ";
cin >> x.gpa;
cin.ignore();
// return x; can't return a value from a void function
}
and in main function or where you are calling the read_data function use
Student s1, s2, s3;
cout << "This program stores -Temporarily- data of three students\n" << endl;
cout << "Enter 1st student's data" << endl;
read_data(s1);
read_data(s2);
read_data(s3);
the reason you are getting weird values in return is that you capture buffer with cin >> instead getline
see
description of getline function
description of cin.ignore function

Why won't Xcode (10.1) realize this class? What am I doing wrong

Basically trying to just run this program for extra learning, Xcode won't understand that I have written a class, and wont implement it. Really confused and need some guidance.
When I run the code only the main method is implemented, nothing else works...
#include <iostream>
using namespace std;
class students {
int id;
char name[20];
int s1;
int s2;
int s3;
public:
void getData() {
cout << "Enter the ID " << endl;
cin >> id;
cout << "Enter the name " << endl;
cin >> name;
cout << "Enter the grade in subject 1 " << endl;
cin >> s1;
cout << "Enter the grade in subject 2 " << endl;
cin >> s2;
cout << "Enter the grade in subject 3 " << endl;
cin >> s3;
}
void putData() {
cout << id << " " << name << " " << s1 << " " << s2 << " " << s3 << endl;
}
};
int main () {
students s[20];
int i, n; //i is for the for loop, n for number of students
cout << "Enter the number of students " << endl;
cin >> n;
for (i=0;i>n;i++)
{
s[i].getData();
}
for (i=0;i>n;i++)
{
s[i].putData();
}
return 0;
}

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;
}

Try to do cin >> string[array] and there is an error (""string subscript out of range")

The code :
class DataBase {
private:
int age, stuNumNew;
string stuName, command;
string ver = "Alpha";
float stuNum = 1;
public:
void Start() {
cout << "Welcome back to Sudent DataBase <ver " << ver << ">." << endl;
cout << "Type 'Add' for add a student.";
cin >> command;
if (command == "Add") {
Add();
}
else if (command == "Search") {
cout << "Student number: ";
cin >> stuNumNew; //Get input from user
cout << "Name: " << stuName[stuNumNew] << endl << "Age: " << age[&stuNumNew] << endl;
Start();
}
}
void Add() {
cout << "Name: ";
**cin >> stuName[stuNum] * *; //get the name
cout << "Age: ";
cin >> age[stuNum]; //get the age
cout << "Student Number: " << stuNum;
stuNum = stuNum++;
stuNumNew = stuNum;
Start();
}
};
Vectors allow you to create variable size arrays
The issue you're having is caused by using a fixed size variable. What you need in this case is a vector because what you are trying to do is assign names and numbers to arrays that are of variable sizes so that you can add new students in your program.
Vectors allow you to do just that.
Here is the modified code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class DataBase {
private:
int searchInput;
/* declare a vector of type int to contain your students' ages */
vector<int> studentAges;
/* declare a vector of type std::string to contain your students' names */
vector<string> studentNames;
string command;
string ver = "Alpha";
/* stuNum is removed because vectors keep track of their own sizes */
public:
void Start() {
cout << "Welcome back to Student DataBase <ver " << ver << ">." << endl;
cout << "Type 'Add' to add a new student or type 'Search' to search the database of students." << endl << " > ";
cin >> command;
if (command == "Add") {
Add();
} else if (command == "Search") {
/* You may want to build in a conditional that checks if there are any students yet. */
cout << "Student number: ";
cin >> searchInput;
if (searchInput < studentNames.size()) {
/* Make sure that the users input (the number) is actually a student's id number
* otherwise reject their input to keep the program from crashing or having undefined behavior.
*/
cout << "Name: " << studentNames[searchInput] << endl << "Age: " << studentAges[searchInput] << endl;
} else {
cout << "Student number invalid" << endl;
}
} else {
/* Tell them if their input is invalid */
cout << "Invalid option." << endl;
}
Start();
}
void Add() {
/* Append new positions for input */
studentNames.push_back("");
studentAges.push_back(0);
cout << "Name: ";
cin >> studentNames.back();
cout << "Age: ";
cin >> studentAges.back();
/* The student number is the newest index of the vector */
cout << "Student Number: " << studentNames.size() - 1 << endl;
}
};
int main() {
DataBase d;
d.Start();
}
You can also combine your variables studentNames and studentAges into a students vector if you create a class (or struct) that keeps both values together:
class Student {
public:
Student(string name, int age) {
this->age = age;
this->name = name;
}
string name;
int age;
};
Then you can use it with vector:
vector<Student> students;
NOTE:
You may want to add some input protecting because if you enter a string where it wants a number it breaks the program.