Hey guys! Im new to C++ and having a little difficulty with this program, Its supposed to be where it prompts you for a name and you can enter anything, for example: "Andre the giant" it then asks for that names career, where the user enters 1-4, and it produces a line such as: "Andre the giant is a certified Professional". The issue im having though, is when someone enters somehting other than 1-4 it needs to say "Wrong Entry!" And start at the line "Please enter another student name", the issue it my getline is grabbing the wrong input and using that then as the name? How do I get around it? I can use cin and it will work correctly, but getline is causing me some issues, however, i need the full string? Any advice ? Thanks alot <3
std::getline() can run into problems when used before std::cin >> var.
The solution is to add std::cin.ignore(); immediately after the first std::cin statement. This will grab a character off of the input buffer (in this case, newline) and discard it.
#include <iostream>
#include <string>
#include <iomanip>
usingnamespace std;
void func(int studentProf, string studentName);
int main()
{
string studentName;
int studentProf = 0;
int i = 0;
cout << "Please enter a student name (\"done\" to leave the program):" << endl;
getline(cin, studentName);
if (studentName != "done")
{
//Call function that spits out prof
func(studentProf, studentName);
while (studentName != "done")
{
cout << "Please enter another student name (\"done\" to leave the program):" << endl;
getline(cin, studentName);
if (studentName != "done")
{
//check prof
func(studentProf, studentName);
}
}
}
}
void func(int studentProf, string studentName)
{
string jobName;
cout << "Please enter the profession of: " << studentName << endl;
cin >> studentProf;
if (studentProf == 1)
cout << studentName << " is a Certified Professional" << endl;
elseif (studentProf == 2)
jobName = "Management Professional";
elseif (studentProf == 3)
jobName = "Service Professional";
elseif (studentProf == 4)
jobName = "Law_and_Order Professional";
else
cout << "Wrong answer" << endl;
cin.ignore();
cin.clear();
studentName.clear();
}
std::cin::ignore should be located after std::cin, not std::getline. I'd recommend moving line 59 to underneath the std::cin at line 46. And modify the statement to something like std::cin.ignore(10000, '\n');
so it discards the ending carriage return left in the istream by std::cin. That carriage return is removed from the istream when using std::getline.
Having std::cin::clear along with std::cin::ignore is a bit of overkill since the istream hasn't actually gone in an error state. The problem was caused by mixing inputs with std::cin and std::getline; that is not an error affecting the stream.
I see! These changes seem to be much better! I will definitely try to format it better sorry! So i changed the code with your recommendations, it seems the problem still remains. If i type input the profession as "e", it will return, 'wrong answer' and the next line will print the "enter a student name", immediately followed by "Please enter the profession of e:". How would this be solved?
#include <iostream>
#include <limits> // <--- Added.
#include <string>
#include <iomanip>
usingnamespace std; // <--- Best not to use.
//void func(int studentProf, string studentName);
voidGetProfession(string& studentName); // <--- All that is needed for this function
int main()
{
string studentName;
int studentProf = 0; // <--- This will always be (0)zero. Passing it to the function has no effect.
int i{}; // <--- "i" has no meaning. Does this variable have a purpose?
cout << "\n Please enter a student name (\"done\" to leave the program): "; // <--- No (\n) or "endl" needed
getline(cin, studentName);
if (studentName != "done")
{
//Call function that spits out prof
//func(studentProf, studentName);
GetProfession(studentName);
while (studentName != "done")
{
cout << "\n Please enter another student name (\"done\" to leave the program): ";
getline(cin, studentName);
if (studentName != "done")
{
//check prof
//func(studentProf, studentName);
GetProfession(studentName);
}
}
}
return 0; // <--- Not required, but makes a good break point for testing.
}
//void func(int studentProf, string studentName)
//{
// string jobName;
// //std::string jobNames[]{ "", "Certified", "Management", "Service", "Law_and_Order" };
//
// cout << "Please enter the profession of: " << studentName << ": ";
// cin >> studentProf;
//
// if (studentProf == 1)
// jobName = "Certified";
// else if (studentProf == 2)
// jobName = "Management";
// else if (studentProf == 3)
// jobName = "Service";
// else if (studentProf == 4)
// jobName = "Law_and_Order";
// else
// cout << "Wrong answer" << endl;
//
// cout << studentName << " is a "<< jobName <<" Professional\n";
//
// cin.ignore();
// cin.clear();
// studentName.clear();
//}
voidGetProfession(string& studentName)
{
int studentProf{};
std::string jobNames[]{ "", "Certified", "Management", "Service", "Law_and_Order" };
std::cout << "\n The professions are:\n";
for (int idx = 1; idx < 5; idx++)
{
std::cout << idx << ") " << jobNames[idx] << " Professional\n";
}
while (cout << " Please enter the profession of " << studentName << ": " && !(std::cin >> studentProf) || studentProf < 1 || studentProf > 4)
{
if (!std::cin)
{
std::cerr << "\n Invalid entry! Must be a number.\n\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
}
elseif (studentProf < 1 || studentProf > 4)
{
std::cerr << "\n Invalid choice! Try again.\n\n";
}
}
cout << "\n " << studentName << " is a " << jobNames[studentProf] << " Professional\n";
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
}
The function I changed not only has a better name that describes the function it also deals with entering a non numeric value when a numeric value is expected with the formatted input of cin >> studentProf;.
And you do not have to pass "studentProf". It should be defined as a local variable in the function. Also the defined variable back in "main" is never changed or used.
Not saying it is the best way to write the program. "main" could still be done differently, but it is a start.
Thank you very much Andy! Im stepping through to make sure I understand each component of what you have done to try and learn! Thank you very much and i appreciate you taking the time to help me out! :)
In the function definition it is better to pass more complicated variables like "std::string", "std::vector" and other containers by reference rather than have the overhead of making a copy.
#include <iostream>
//#include <iomanip> // <--- Good that you know about this, but not used in this program.
#include <limits> // <--- Added.
#include <string>
constexprint MAXSIZE{ 5 };
usingnamespace std; // <--- Best not to use.
using JOBNAMES = std::string[MAXSIZE];
const JOBNAMES jobNames{ "", "Certified", "Management", "Service", "Law_and_Order" };
int GetProfession(string& studentName);
int main()
{
int studentProfIdx{};
string studentName{ " " };
while (!studentName.empty())
{
//cout << "\n Please enter another student name\n (\"Enter when done\" to leave the program): ";
cout << "\n Please enter a student name\n (\"Enter when done\" to leave the program): ";
getline(cin, studentName);
if (!studentName.empty())
{
//check prof
//func(studentProf, studentName);
studentProfIdx = GetProfession(studentName);
cout << "\n " << studentName << " is a " << jobNames[studentProfIdx] << " Professional\n";
}
}
return 0; // <--- Not required, but makes a good break point for testing.
}
int GetProfession(string& studentName)
{
int studentProf{};
std::cout << "\n The professions are:\n";
for (int idx = 1; idx < 5; idx++)
{
std::cout << idx << ") " << jobNames[idx] << " Professional\n";
}
while (cout << " Please enter the profession of " << studentName << ": " && !(std::cin >> studentProf) || studentProf < 1 || studentProf > 4)
{
if (!std::cin)
{
std::cerr << "\n Invalid entry! Must be a number.\n\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
}
elseif (studentProf < 1 || studentProf > 4)
{
std::cerr << "\n Invalid choice! Try again.\n\n";
}
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); // <--- Requires header file <limits>.
return studentProf;
}
"main" should direct the program flow, but in this case that is not as easy to do. A function should do 1 thing and either return a value or use variables passed by reference.
I eliminated the duplication in "main" and only used the while loop.
Line 9 may seem strange. What it is doing is defining a user variable type similar to "char" and "int". The advantage I have found is that it makes it much easier to pass an array by reference. The array type does not matter and it works well for 2D arrays.
Notes:
Try to use the new line (\n) over the function "endl" The changes and upgrades to the C++11 standards and the others that follow make using the (\n) work much the same as "endl". Also a "cout" statement followed by a "cin" statement will flush the buffer before any input is allowed. Unfortunately this does not work in reverse.
If you can figure out where to make the change, usually under a "Tools" menu, change the tab setting to use spaces instead of the tab character. The indenting will not look as exaggerated here.
#include <iostream>
#include <limits>
#include <string>
#include <iterator>
const std::string jobNames[] {"Certified", "Management", "Service", "Law_and_Order"};
int GetProfession(const std::string& studentName);
int main()
{
for (std::string name; (std::cout << "\nEnter student name (or CR to exit): ") && std::getline(std::cin, name) && !name.empty(); ) {
constauto studentProfIdx {GetProfession(name)};
std::cout << '\n' << name << " is a " << jobNames[studentProfIdx] << " Professional\n";
}
}
int getInt(const std::string& prm)
{
int i {};
while ((std::cout << prm) && (!(std::cin >> i) || std::cin.peek() != '\n')) {
std::cout << "Not an integer\n";
std::cin.clear();
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
return i;
}
int GetProfession(const std::string& studentName)
{
std::cout << "\nThe professions are:\n";
size_t idx {};
for (/*size_t idx {}; */ constauto& job : jobNames)
std::cout << ++idx << ") " << job << " Professional\n";
int prof {};
do {
prof = getInt("\nPlease enter the profession of " + studentName + ": ");
} while ((prof < 1 || prof > std::size(jobNames)) && (std::cout << "Invalid number\n"));
return prof - 1;
}
Enter student name (or CR to exit): seeplus
The professions are:
1) Certified Professional
2) Management Professional
3) Service Professional
4) Law_and_Order Professional
Please enter the profession of seeplus: 1
seeplus is a Certified Professional
Enter student name (or CR to exit):