Beginner's C++ program for a class - c++

the assignment is the basic "cin a full name" and then "retrieve First Middle Last" bit, where you create a program that asks the user to type in their full first name into a single string and the programs picks apart the name and outputs it organized seperately. this is what i wrote:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string name;
int index;
index = name.find(' ');
cin >> name;
cout << "First name: " << name.substr(0, index) << endl;
name = name.substr(index+1, name.length()-1);
index = name.find(' ');
cout << "Middle Name: " << name.substr(1, index) << endl;
name = name.substr(index+1, name.length()-1);
cout << "Last name: " << name;
return 0;
}
the code just wont seperate them right, and will not redefine 'name' correctly.
It always just bounces back to the beginning of the string.
any help for a newbie?
here's an example output:
Teenage Wonder Land
First name: Teenage
Middle Name: eenag
Last name: Teena
Process returned 0 (0x0) execution time : 7.942 s
Press any key to continue.

You wont' find anything before type your in console and sbustr should read from index 0
string name;
int index;
//index = name.find(' '); // comment out, name is empty, you won't find anything
cin >> name;
index = name.find(' '); // now you can find first space
cout << "Middle Name: " << name.substr(0, index) << endl;
// ^
Or just use std::stringstream
#include <sstream>
std::stringstream ss(name);
std::string token;
int i = 0;
while(ss >> token)
{
switch(i)
{
case 0:
std::cout << "First name: " << token << std::endl;
break;
case 1:
std::cout << "Middle name: " << token << std::endl;
break;
case 2:
std::cout << "Last name: " << token << std::endl;
break;
default:
break;
i++;
}
}

You clearly can't search for something in name before you assign it a value, which is what you're doing now:
string name;
int index;
index = name.find(' '); // No value assigned to name yet - nothing to search
cin >> name; // Now you're giving it a value (too late)
Instead, assign and then try to find a value:
string name;
int index;
cin >> name; // Assign a value first
index = name.find(' '); // Now try to find something in it

I think you should use std::getline to get the entire line of text at once. Currently you are only reading in the first word (>> operator will only extract text up to the next whitespace character).
std::string name;
if (std::getline(cin, name))
{
// extraction successful, "name" should contain entire line
}
Then, you can use one of the other answers in this question or continue with your own approach.

The extraction operator >> for istream will grab all non-whitespace characters in the buffer until it encounters a whispace.
So your input here:
Teenage Wonder Land
contains 3 whitespaces including the invisible newline at the end when you hit enter. From this you should be able to figure out what the following does:
cin >> name;
Hint: name doesn't contain the entire line you just entered.

#include <iostream>
#include <string>
using namespace std;
string getnext(const string &full, const string &delim, size_t &beg) {
size_t prev = beg;
beg = full.find(delim, beg);
if (beg != string::npos)
return full.substr(prev, beg-prev);
return full.substr(prev, full.length()-prev);
}
int main()
{
string name, temp, error = "NameError: Enter first, middle, last";
size_t index = 0;
getline(cin, name); //Get the full name
temp = getnext(name, " ", index); //Get first name
if (index == string::npos) {
cout << error;
return -1;
}
cout << "First name: " << temp << endl;
temp = getnext(name, " ", ++index); //Get middle name
if (index == string::npos) {
cout << error;
return -1;
}
cout << "Middle Name: " << temp << endl;
temp = getnext(name, " ", ++index); //Get last name
cout << "Last name: " << temp << endl;
return 0;
}

Related

Getting the input from the file as string and also integer C++

I have a text file. I have a text file consisting of member data. I am developing a program where we can get the member data from the file. After searching in the internet, I have searched a way to read all the data from the file as char array. But I want to change it where upon reading from file I want the data to be string and also integer.
name, icno, email, phone_number, acc_num, password ( read from file AS STRING )
month, year ( read from file AS INTEGER )
Content of Membership.txt
Mathavan|021127100897|MathavanKrishnan27#gmail.com|0167750575|1410065449|Mathavan1234|3|2022
Mathavan|021127100897|MathavanKrishnan27#gmail.com|0167750575|1410065448|Mathavan1234|3|2024
Mathavan|021127100897|MathavanKrishnan27#gmail.com|0167750575|1410065447|Mathavan1234|3|2022
string member_login(){
title();
fstream member;
member.open("Membership.txt",ios::in);
string pass_input, line, acc_num1, password1;
int login_attempt = 0, count = 0 , account = 0;
char dummy, resp, accno_input[25], name[25], icno[25],email [40], phone_number[25],acc_num[25],password[25],month[25], year[25];
account_num:
cout << " Enter your account number : ";
cin >> accno_input;
ifstream file("Membership.txt");
while (!file.eof()){
getline(file, line);
count++;
}
cout << accno_input;
int i = 0;
while(i <= count)
{
member.getline(name,25,'|');
member.getline(icno,25,'|');
member.getline(email,40,'|');
member.getline(phone_number,25, '|');
member.getline(acc_num,25, '|');
member.getline(password,25,'|' );
member.getline(month,25,'|' );
member.getline(year, 25);
cout << name << " ";
cout << icno << " ";
cout << acc_num << " ";
cout << accno_input;
if (acc_num == accno_input){
account = 1;
break;
}
i ++;
}
cout << account;
member.close();
if ( account != 1 ){
cout << endl;
cout << " Your account not found !!!"<< endl;
cout << " Please try again !!" << endl << endl;
cout << " PLEASE ENTER ANY KEY TO CONTINUE >>> ";
cin >> dummy;
goto account_num;
}
password1 = password;
cout << endl;
cout << " Enter your account password : ";
cin >> pass_input;
for (login_attempt = 1 ; login_attempt <= 2 ; login_attempt ++){
if (pass_input == password1){
cout << "Login Successful !!!";
break;
}
cout << endl;
cout << "Login Failed. Attempt " << login_attempt << " of 3" << endl;
cout << "Please re-enter Password: " ;
cin >> pass_input;
if (pass_input == password1){
cout << "Login Successful !!!";
break;
}
}
if ( login_attempt == 3){
cout << endl;
cout << "Login Failed. Attempt 3 of 3";
}
return accno_input;
}
There are so many things completely wrong in your program that I do recomend to you:
Delete and start from scratch.
There is no meaningful fix possible. There is even a goto. And you MUST stop using C-Style arrays with some agic dimension in C++. And C++ has many things to make your live easier. Simply use them.
Please find below a C++ solution.
You can copy and paste it and stay as you are, or, you take 3 hours and google all constructs and try to understand and learn and become a better programmer. Your choise.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
#include <vector>
#include <regex>
#include <iterator>
#include <algorithm>
const std::regex re{ R"(\|)" };
struct Member {
// Memeber data
std::string name{};
std::string icno{};
std::string email{};
std::string phoneNumber{};
std::string accountNumber{};
std::string password{};
int month{};
int year{};
// Extractor operator
friend std::istream& operator >> (std::istream& is, Member& m) {
// Readone complete line
if (std::string line{}; std::getline(is, line)) {
// Split it into parts
std::vector parts(std::sregex_token_iterator(line.begin(), line.end(), re, -1), {});
// assign parts to member data
if (parts.size() == 8) {
m.name = parts[0]; m.icno = parts[1]; m.email = parts[2]; m.phoneNumber = parts[3]; m.accountNumber = parts[4]; m.password = parts[5];
m.month = std::stoi(parts[6]); m.year = std::stoi(parts[7]);
}
}
return is;
}
};
// Filename for member data
const std::string fileName{ "r:\\Membership.txt" };
int main() {
// Open the data file and check, if it could be opened
if (std::ifstream fileStream{ fileName }; fileStream) {
// Read complete source file, parse it and get all data
std::vector memberData(std::istream_iterator<Member>(fileStream), {});
// We want the user to give 3 trials to enter valid data
constexpr unsigned int MaxTrials = 3u;
unsigned int numberOfTrials{};
// A valid input will stop the loop immediately
bool validInputgiven{};
// Now, try to get the correct input
while (not validInputgiven and numberOfTrials < MaxTrials) {
// Get an acoount number
std::cout << "\nEnter a account number: ";
std::string account{};
std::cin >> account;
// Check, if the account number is in the member data
if (std::count_if(memberData.begin(), memberData.end(), [&](const Member& m) { return m.accountNumber == account; }) > 0) {
// Account info wasOK. Get the password
std::cout << "\nEnter your password: ";
std::string password{};
std::cin >> password;
if (std::count_if(memberData.begin(), memberData.end(), [&](const Member& m) { return m.accountNumber == account and m.password == password; }) > 0) {
// Valid data found
validInputgiven = true;
std::cout << "\n\nEverything OK. Data validated.\n\n";
}
}
// Next try
++numberOfTrials;
if (not validInputgiven and numberOfTrials < MaxTrials) std::cout << "\nInvalid input. Please try again\n\n\n";
}
if (not validInputgiven ) std::cout << "\nToo many wrong tries. Aborting . . .\n\n\n";
}
else std::cerr << "\n\nError. Could not open source file '" << fileName << "'\n\n";
}

Error on getline function no instance matches the arguments

Why my code is not executing and showing me error ?? Im getting error on this line
while (getline(s, word, ' , '))
my Code is below:
#include <fstream>
#include <string>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
// first we define a class that will represent all the candidates
class Candidate
{
string name;
int votes;
public:
Candidate()
{
name = "";
int votes = 0;
}
Candidate(string cand_name, int vote_count)
{
name = cand_name; votes = vote_count;
} string getName() { return name; } int getVotes() { return votes; } void get_details() { cout << name << ", " << votes << endl; }
//Following member method is used to increment the vote count
void vote_this_candidate() { votes++; }
};
int main()
{
cout << "Welcome to Student President Voting System!!!" << endl;
Candidate allCandidates[100];
int totalVotes = 0;
// File pointer fstream fin; // Open an existing file
fstream fin;
fin.open("candidantes.txt", ios::in); // Read the Data from the file // as String Vector
vector <string> row;
string line, word, temp; int index = 0; // Following while loop will iterate for each line in the file
while (fin >> temp) {
row.clear(); // read an entire row and // store it in a string variable 'line'
getline(fin, line); // used for breaking words
string s(line); // read every column data of a row and // store it in a string variable, 'word'
while (getline(s, word, ' , '))
{ // adding the splitted words to row
row.push_back(word);
} allCandidates[index] = Candidate(row[0], stoi(row[1])); totalVotes += stoi(row[1]); index++;
}
string name = ""; cout << "\nPlease enter the name of the candidante you want to vote : ";
getline(cin, name); int cand_no = -1; string userChoice; int i = 0; //Now we find the candidante with the same inputted name
while (i < index) {
if (allCandidates[i].getName() == " " + name) {
cand_no = i; cout << "Do you want to vote this candidante [y/n] : ";
cin >> userChoice; //After finding the candidate just ask the user to vote the candidante
if (userChoice == "y") { //to vote just call the member method that increments the vote count
allCandidates[cand_no].vote_this_candidate(); totalVotes++; cout << endl << "You successfully voted to " << name << " Thanks for voting!!!" << endl;
}
else { cout << "You didn't vote!!!" << endl; } break;
}
i++;
} if (cand_no == -1) {
cout << "Candidante not found!!! Do you like to add this candidate [y/n]: ";
cin >> userChoice; if (userChoice == "y") { allCandidates[index + 1] = Candidate(name, 1); totalVotes++; index++; }
}
//To show top five candidates we first sort the array with lambda
std::sort(allCandidates, allCandidates + 10, [](Candidate a, Candidate b) -> bool { return a.getVotes() > b.getVotes(); });
//then we show only first five candidates
cout << endl << "These are top 5 candidantes so far : " << endl;
for (int i = 0; i < 5; i++)
{
cout << i + 1 << ","; allCandidates[i].get_details();
} cout << endl << "Total studnets voted: " << totalVotes;
}
Problem is here:
string s(line);
while (getline(s, word, ' , '))
because getline has no overload that takes a std::string as its first parameter.
However, there is an overload that takes a stringstream, so you can do:
stringstream ss(line);
while (getline(ss, word, ' , '))
Also, ' , ' won't do what you think. Perhaps you meant ','.
Finally, int votes = 0; in your Candidate() constructor should just be votes = 0;. As it is, you are just declaring, initialising and then discarding a local variable.
The problem is that the compiler is telling you that the parameters you've given don't match a definition of the function. In your case I believe the problem is that you've given it 3 characters instead of 1 in the character portion (remember, a space is also a character). Try changing ' , ' to ','

How output a full name that starts with last name? What if the the first name or last name consist of words?

i need some help (C++)
Make a program that will input the full name once but output of full name will start with last name.
I attached my code but this code will read only the first word of first name or first word of last name. What if the first name or last name has two words? Thank you.
<pre>
#include <iostream>
#include <string>
using namespace std;
main()
{
string first, middle, last;
cout << "What is your full name? ";
cout << endl << "---> ";
cin >> first >> middle >> last;
cout << "---> " << last << ", " << first << " " << middle;
cout << endl;
return 0;
}
<code>
full name program
I think this may be what you mean, from an example name :
"first middle middle2 ... middle-n last"
you would like to output
"last, first middle .... middle-n".
To do this, you can..
Use std::getline(cin, name) to get the name.
Using cin >> name will truncates the string when it meets a whitespace " ". Which means only get the first "word" before whitespace.
To avoid this, use getline.
Use string::find_last_of(" ")
Use string::substr(pos, span) to get the desired substring.
http://www.cplusplus.com/reference/string/string/substr/
Here is the code :
#include <iostream>
#include <string>
using namespace std;
int main() {
string name, last;
cout << "What is your full name? ";
cout << endl << "---> ";
getline(cin,name);
int idx;
idx = name.find_last_of(" ");
cout << idx << endl;
last = name.substr(idx+1);
cout << "---> " << last << ", " << name.substr(0, idx);
cout << endl; return 0; }
Example output :
What is your full name :
---> first middle middle2 middle3 last
28
---> last, first middle middle2 middle3
The input stream will be in a failure state if the read fails (i.e. no word was read). So, the solution is to test the stream state after each read.
if (cin >> first)
{
if (cin >> middle)
{
if (cin >> last)
{
//...
}
else
{
last = middle;
}
}
}
You should test each name and output only if it is not empty.

c++ removing of line from a text file (need explanations)

I am trying to remove a line containing username and password from text file.
so I tried to following,
1)Read the text file.
2)store the userName and password inside the textfile.
3)prompt the user which user he wants to delete.
4)the entire line will be deleted in the vector if the input matches with the username in the vector.
5)copy back to text file(not done yet)
I managed to get it by luck
textfile(userInfo.txt)
amber abc
janet def
chris DEF
gerald AZC
my output of my codes
Before Deletion
amber abc
janet def
chris DEF
gerald AZC
Enter User Name to delete: amber
After Deletion
janet def
chris DEF
gerald AZC
but what I don't really understand is, how my codes actually delete the entire line after it matches with my input espcially starting from
string name;
cout << "Enter User Name to delete: ";
cin >> name;
cout << " " << endl;
cout << "After Deletion" << endl;
for (int i =0; i<userDetails.size(); i++) {
if(userDetails[i].getUserName() == name){
userDetails.erase(userDetails.begin() + i);
}
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}
I hope someone can explain it to me.
my codes
user.h
#ifndef user_user_h
#define user_user_h
#include <iostream>
class user {
public:
user() {
userName = " ";
password = " ";
}
user(std::string userName,std::string password);
std::string getUserName();
std::string getPassword();
void setUserName(std::string userName);
void setPassword(std::string password);
private:
std::string userName,password;
};
#endif
main.cpp
#include "user.h"
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <vector>
using namespace std;
user::user(string userName,string password) {
setUserName(userName);
setPassword(password);
};
string user::getUserName() {
return userName;
}
string user::getPassword() {
return password;
}
void user::setUserName(std::string userName) {
this->userName = userName;
}
void user::setPassword(std::string password) {
this->password = password;
}
int main(){
vector<user> userDetails;
string line;
string userName;
string password;
ifstream readFile("userInfo.txt");
while(getline(readFile,line)) {
stringstream iss(line);
iss >> userName >> password;
user userInfoDetails(userName,password);
userDetails.push_back(userInfoDetails);
}
readFile.close();
cout << "Before Deletion" << endl;
for (int i =0; i<userDetails.size(); i++) {
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}
cout << " " << endl;
string name;
cout << "Enter User Name to delete: ";
cin >> name;
cout << " " << endl;
cout << "After Deletion" << endl;
for (int i =0; i<userDetails.size(); i++) {
if(userDetails[i].getUserName() == name){
userDetails.erase(userDetails.begin() + i);
}
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}
}
I don't follow what you don't understand. However, I'm going to go over this snippet of code because it contains a serious bug that is common for beginners.
for (int i =0; i<userDetails.size(); i++) {
if(userDetails[i].getUserName() == name){
userDetails.erase(userDetails.begin() + i);
}
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}
The reason this "works" is that when your program encounters an object in the vector whose username matches the inputted username, you erase it from the vector. When this happens, the index of every object in the vector that is "further to the right" of the erased object gets shifted down by one. So suppose the matching name is "amber" (index 0). On the first loop iteration, amber will be deleted; janet shifts to index 0; chris shifts to index 1; and gerald shifts to index 2. Still on the first loop iteration, it will output index 0 which is now chris so everything is fine. On all the remaining loop iterations, userDetails.size() will evaluate to the new post-delete size, 3, so you will only get 3 iterations total, for indices 0, 1, 2.
NOW FOR THE BUG: Try entering "gerald" as the name to delete.
If you do this, remember that it will get processed on the fourth iteration of the loop, when i is 3. Gerald will be deleted, reducing the size to 3 and the last valid index to 2. But i is still 3 at this point! So
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
on the fourth iteration is equivalent to:
cout << userDetails[3].getUserName() << " " << userDetails[3].getPassword() << "\n";
but there is no userDetails[3] and your program should segfault.
Here is how you would implement it properly:
for (int i =0; i<userDetails.size(); i++) {
if(userDetails[i].getUserName() == name){
userDetails.erase(userDetails.begin() + i);
continue; // skip to next iteration because we can't guarantee 'i' is a valid
// index or that username on this iteration doesn't match
}
cout << userDetails[i].getUserName() << " " << userDetails[i].getPassword() << "\n";
}
However, I prefer the following idiom:
auto i = userDetails.begin(), e = userDetails.end();
while (i != e)
{
if (name == i->getUserName())
{
i = userDetails.erase(i); // i is now equal to next element after deleted one
e = userDetails.end(); // update e to be equal to the new end
// don't output because we deleted
}
else
{
std::cout << i->getUserName() << ' ' << i->getPassword() << std::endl;
++i;
}
}
I'm not sure I understood what you didn't understand but I'll try to help...
You delete the line in the correct location.
You give the erase method an iterator which points at the element you want to delete.
When you do this, the next line gets the index of the deleted line and you print it (the previously next line which is now the line in index i).
It works because
userDetails.erase(userDetails.begin() + i);
deletes a user, which contains a username and a password.

Error: Must have class type

I need to create a list of contacts and I keep getting this error in my code: expression must have class type.
Here's the code:
#include<iostream>
#include<string>
using namespace std;
class PhoneApp {
public:
string FirstName;
string LastName;
string PhoneNumber;
string EmailID;
PhoneApp() {
FirstName = "";
LastName = "";
PhoneNumber = "";
EmailID = "";
}
void addContact(){
cout << "Enter your contact's first name: ";
cin >> FirstName;
cout << "Enter your contact's last name: ";
cin >> LastName;
cout << "Enter your contact's phone number: ";
cin >> PhoneNumber;
cout << "Enter your contact's email address: ";
cin >> EmailID;
}
void displayContact(){
cout << "Here's your contact details: " << endl;
cout << "FirstName: " << FirstName << endl;
cout << "LastName: " << LastName << endl;
cout << "PhoneNumber: " << PhoneNumber << endl;
cout << "EmailID: " << EmailID << endl;
}
};
int main(){
PhoneApp myPhoneApp[50];
int index = 0;
while(1){
cout << "Press 1 to add contacts" << endl;
cout << "Press 2 to search for a contact" << endl;
cout << "Anything else to quit" << endl;
int choice;
cin >> choice;
switch(choice){
case 1:{ myPhoneApp[index].addContact();
index++;
break;}
case 2: { cout << "Enter a first name to search for: " << endl;
string search = "";
cin >> search;
for (int i = 0; i < index; i++) {
if(myPhoneApp[50].FirstName[i].compare(index) == 0);
break;
}
}
default: exit(1);
}
}
system("pause");
return 0;
}
The error pops up at
if(myPhoneApp[50].FirstName[i].compare(index) == 0
What exactly is the problem here and how do I fix it?
Thanks for the help
There are multiple errors in your code, but the one that you are pointing to is as follows:
myPhoneApp[50].FirstName is a string
Strings consist of characters. You access characters in a string using a subscript operator [i]
Characters are primitives.
You can access members using a dot . on classes and structures, but not on primitives
Since myPhoneApp[50].FirstName[i] is a char, and since char is a primitive, using a dot on it is invalid.
cout << "Enter a first name to search for: " << endl;
string search = "";
cin >> search;
for (int i = 0; i < index; i++) {
if(myPhoneApp[i].FirstName.compare(search) == 0) {
//do stuff
break;
}
}
Several things were going wrong.
First off, you need to compare the entire FirstName string to search, not individual characters of FirstName.
Second, you need to iterate through the contacts in myPhoneApp[], not just keep checking different characters of the FirstName string in index 50, which isn't even necessarily set.
Third, no string.compare() overloads take a single int as an argument. What you're looking for is the method to compare two strings, which is what my answer will do.
Fourth, an issue you didn't get to yet... you had a semicolon after your if statement, so regardless of the condition of the if statement, nothing really executes... and you'd just hit that break; after a single iteration, no matter what.
dashblinkenlight's answer explains why the error message was what it was, mine shows you how to fix your program.
There are several small things coming together here to cause you a problem.
if(myPhoneApp[50].FirstName[i].compare(index) == 0);
break;
Firstly: You have a stray semicolon on the end of the "if" line
if();
means "do the test, and then forget about it. always do the thing on the next line".
Secondly, you are only ever checking one element of your contacts list
myPhoneApp[50]
surely you mean't
myPhoneApp[i]
Next, myPhoneApp[50].Firstname resolves to a single instance of std::string, you then try to index the letters in that name and compare them with the number of entries in your index.
myPhoneApp[50].FirstName[i].compare(index)
What you presumably mean is
if(myPhoneApp[i].FirstName == search)
break;
---- Edit ----
You've given your member variables of "myPhoneApp" upper-camelcase names, just like your class names. This is going to confuse you, and it means you can't name your member variables to match their type:
PhoneApp PhoneApp;
is a compile error.
A common practice is to give member variables distinctive names by adding a prefix ("m_" for member) or suffix (some places add "_" to indicate a member variable).
E.g.
class PhoneApp {
public:
string m_FirstName;
string m_LastName;
string m_PhoneNumber;
string m_EmailID;
PhoneApp() {
m_FirstName = "";
m_LastName = "";
m_PhoneNumber = "";
m_EmailID = "";
}
};
or "m_firstName", "m_lastName" etc.