There is an error when i try to compile and im not sure whats wrong with it.
This is a program which authencate username and password with textfile, seperated with ";" delimeter in a single textfile.
The error is quite long.
/tmp/ccgs7RYV.o: In function 'Employee::Employee()':
main2.cpp:(.text+0xa5): undefined reference to 'Employee::authenticate(std::basic_string, std::allocator>, std::basic_string, std::allocator>)'
/tmp/ccgs7RYV.o: In function `Employee::Employee()':
main2.cpp:(.text+0x231): undefined reference to 'Employee::authenticate(std::basic_string, std::allocator>, std::basic_string, std::allocator>)'
collect2: ld returned 1 exit status
#include<iostream>
#include<string>
#include <fstream>
using namespace std;
class Employee
{
public:
Employee();
bool authenticate(string, string);
};
Employee::Employee()
{
string username, password;
cout << "Username: ";
cin >> username;
cout << "Password: ";
cin >> password;
if (authenticate(username, password) == true)
cout << "Sucess" << endl;
else
cout << "fail" << endl;
}
bool authenticate(string username, string password)
{
std::ifstream file("login.txt");
std::string fusername, fpassword;
while (!file.fail())
{
std::getline(file, fusername, ';'); // use ; as delimiter
std::getline(file, fpassword); // use line end as delimiter
// remember - delimiter readed from input but not added to output
if (fusername == username && fpassword == password)
return true;
}
return false;
}
int main()
{
Employee();
return 0;
}
bool Employee::authenticate(string username, string password) {
std::ifstream file("login.txt");
std::string fusername, fpassword;
while (!file.fail()) {
std::getline(file, fusername, ';'); // use ; as delimiter
std::getline(file, fpassword); // use line end as delimiter
// remember - delimiter readed from input but not added to output
if (fusername == username && fpassword == password)
return true;
}
You need to use the scope resolution operator. You were just missing that.
Ok I'm going to try to sort out class design a bit.
class Employee
{
public:
Employee( std::string name, std::string password ) :
m_name( name ), m_password( password )
{
}
bool authenticate( const char * filename ) const;
private:
std::string m_name;
std::string m_password;
};
Employee readEmployeeFromConsole()
{
std::string name, password;
std::cout << "Name: ";
std::cin >> name;
std::cout << "Password: "
std::cin >> password;
return Employee( name, password );
}
bool Employee::authenticate( const char * filename ) const
{
// your implementation
}
int main()
{
Employee emp = readEmployeeFromConsole();
if( emp.authenticate( "input.txt" ) )
{
std::cout << "You're in!\n";
}
else
{
std::cout << "Get out!\n";
}
}
Related
Source: text file stores list of account info. e.g:
10041249,Mr,Vincent,Rogan,Rogan Locksmiths Ltd,Nell,5287.000000,,491.691000,
10021250,Mrs,Adele,Cunningham,Cunningham Demolition Ltd,Dr Scott,2941.000000,,273.513000,
10051251,Mr,Rodney,Shaw,Shaw Meat Packaging Ltd,Eddie,7552.000000,,740.096000,
10001252,Mrs,Christine,Nichols,Nichols Scaffolding Ltd,Brad,6723.000000,Eddie:Brad:,672.300000,
10021253,Mr,Alexander,Marshall,Marshall Chemicals Ltd,Dr Scott,1768.000000,,173.264000,
10021254,Ms,Shirley,Hagman,On Point Sportswear Ltd,Dr Scott,52.000000,,5.200000,
....
....
....
How to extract string with comma delimiter from txt file and parse every element separate by comma delimiter into a class constructor?
I have try to use stringstream to extract data from every line. But it does not work.
The EmployeeAccount class I got is down below:
#include <iostream>
#include <sstream>
#include <string>
using namespace std;
class EmployeeAccount {
private:
//member variable
string acountNumber;
string title;
string firstname;
string lastname;
string company;
string salesperson;
double purchaseValue;
string prev_salestaff;
double commission;
public:
//overload constructor
EmployeeAccount(const string& employeeAccountInfo)
{
string str;
stringstream employeeAccountStream(employeeAccountInfo);
while (getline(employeeAccountStream, str, ','))
{
stringstream sso(str);
sso >> acountNumber;
sso >> title;
sso >> firstname;
sso >> lastname;
sso >> company;
sso >> salesperson;
sso >> purchaseValue;
sso >> prev_salestaff;
sso >> commission;
}
}
//Access methods
string getAccountNumber() { return acountNumber; };
string getTitle() { return title; };
string getFirstname() { return firstname; };
string getLastname() { return lastname; };
string getCompany() { return company; };
double getPurchaseValue() { return purchaseValue; };
string getPrev_salesstaff() { return prev_salestaff; };
double getCommission() { return commission; };
string getAccountDetail() { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};
//Destructor
~EmployeeAccount() {};
};
The testing code is this:
cout << testEmployee.getAccountDetail() << endl;
cout << testEmployee.getAccountNumber() << endl;
cout << testEmployee.getTitle() << endl;
cout << testEmployee.getFirstname() << endl;
cout << testEmployee.getLastname() << endl;
cout << testEmployee.getCompany() << endl;
cout << testEmployee.getPurchaseValue() << endl;
cout << testEmployee.getPrev_salesstaff() << endl;
cout << testEmployee.getCommission() << endl;
}
Parsing CSV file is an old topic. You will find at least 100 answers with code examples here on stackoverflow. Very often you will find a solution with the function std::getline. Please read the documentation here. It can read characters from a std::ifstream until or up to a delimiter (a comma , in our case), then store the result, without the comma, in a string and discard the comma from the stream. So, throwing that away. The characters will be stored in a std::string. If numbers or other types are needed, we need to convert the string to the other type, using the appropriate function.
Example: We have a string consisting of characters ‘1’, ‘2’ and ‘3’, so, “123”. The quotes indicate the string type. If we want to convert this string into an integer, we can use for example the function std::stoi.
In your case, you have 2 double values. So, we would split the input of the file into strings and then convert the 2 strings with the double values in it, using the function std::stod.
What you need to know additionally is, that often a 2 step approach is used. This is done to prevent potential problems arising from extracting all the string parts from one csv line. So,
we first read a complete line,
then put that line into a std::istringstream, and finally
read input and split the CSV from there.
Then, the rest is simple. Just use std::getline to al the data that you need.
Last but not least, to read the file, we will simply open it, read line by line, create an “EmployeeAccount” and push that into a std::vector
At the end we do some debug output.
Please see below one of may potential implementation proposals:
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
#include <vector>
class EmployeeAccount {
private:
//member variable
std::string acountNumber;
std::string title;
std::string firstname;
std::string lastname;
std::string company;
std::string salesperson;
double purchaseValue;
std::string prev_salestaff;
double commission;
public:
//overload constructor
EmployeeAccount(const std::string& employeeAccountInfo)
{
std::istringstream employeeAccountStream(employeeAccountInfo);
std::getline(employeeAccountStream, acountNumber, ',');
std::getline(employeeAccountStream, title, ',');
std::getline(employeeAccountStream, firstname, ',');
std::getline(employeeAccountStream, lastname, ',');
std::getline(employeeAccountStream, company, ',');
std::getline(employeeAccountStream, salesperson, ',');
std::string temp;
std::getline(employeeAccountStream, temp, ',');
purchaseValue = std::stod(temp);
std::getline(employeeAccountStream, prev_salestaff, ',');
std::getline(employeeAccountStream, temp, ',');
commission = std::stod(temp);
}
//Access methods
std::string getAccountNumber() const { return acountNumber; };
std::string getTitle() const { return title; };
std::string getFirstname() const { return firstname; };
std::string getLastname() const { return lastname; };
std::string getCompany() const { return company; };
double getPurchaseValue() const { return purchaseValue; };
std::string getPrev_salesstaff() const { return prev_salestaff; };
double getCommission() const { return commission; };
std::string getAccountDetail() const { return acountNumber + " " + title + " " + firstname + " " + lastname + " " + company;};
//Destructor
~EmployeeAccount() {};
};
int main() {
std::ifstream ifs{ "accounts.txt" };
if (ifs) {
// Here we will store all accounts
std::vector<EmployeeAccount> accounts{};
// Read the file line by line
std::string line{};
while (std::getline(ifs, line)) {
// Create one account by splitting the input line
EmployeeAccount account(line);
// Add the new accounts to the vector of accounts
accounts.push_back(account);
}
// Debug output. For all accounts that we read, output all data
for (const EmployeeAccount& account : accounts) {
std::cout << "\n--------------------------\n"
<< account.getAccountDetail() << '\n'
<< account.getAccountNumber() << '\n'
<< account.getTitle() << '\n'
<< account.getFirstname() << '\n'
<< account.getLastname() << '\n'
<< account.getCompany() << '\n'
<< account.getPurchaseValue() << '\n'
<< account.getPrev_salesstaff() << '\n'
<< account.getCommission() << '\n';
}
}
else
std::cerr << "\n*** Error: Could not open source file\n\n";
}
I want to make a program that inputs data of participants in a txt file through the input function of the class. The output function is then used to extract the information of a single participant at a time by keying in their ID.
In this code of mine, my while loop runs infinitely as soon as I enter an ID. I suspect that it is unable to find the eof(). Any help would be greatly appreciated. I am new to C++.
#include <fstream>
#include <sstream>
#include <iostream>
#include <string>
using namespace std;
class Participant{
private:
int id, score;
string name;
public:
Participant(){
id = 0; score = 0; name = "";
}
void input(){
char choice;
ofstream in;
in.open("Participant.txt", ios::app);
do{
cout<<"Enter your ID: \t";
cin>>id;
cout<<"Enter your name: \t";
cin>>name;
cout<<"Enter your Score:\t";
cin>>score;
in<<name<<" ";
in<<id<<" ";
in<<score<<endl;
cout<<"Add another entry? (Y/N)\n";
cin>>choice;
}while(choice == 'y' || choice == 'Y');
in.close();
}
void output(){
int idout, holderID, holderS;
string holder, output;
cout<<"Enter the ID for more information related to the person:";
cin>>idout;
fstream out;
out.open("Participant.txt");
while(!out.eof()){
out>>holderID;
cout<<"looping...\n";
if(idout == holderID){
out>>holder;
cout<<"Name: \t"<<holder<<endl;
out>>holderS;
cout<<"Score:\t"<<holderS<<endl;
holder ="";
holderS=0;
break;
}
else continue;
}
out.close();
}
void max(){
}
};
int main(){
char choice;
Participant player;
cout<<"Asking for Input: \n";
player.input();
system("pause");
system("cls");
cout<<"Data Viewing: \n";
do{
player.output();
cout<<"\nDo you wish to extract information on other players?\n";
cout<<"Y - Yes."<<endl;
cout<<"N - No."<<endl;
cout<<"Choice: ";
cin>>choice;
}while (choice == 'y' || choice == 'Y');
cout<<"\n\nEnd of Data Viewing.\n";
}
I want it to, at first, read just the ID, in the first line its 1037. If the ID matches, it should display the next 2 members in the file; the name and the score.
The Problem is that you tried to use holderID (int) Directly from the out stream. Try to use string to read the same out value and use stoi() to convert the same to int.
Also note as you write the first is name followed by id and score.
Also use the below as a reference. I have used std::map to store the value of id, name and score.
#include <string>
#include <fstream>
#include <map>
#include <iostream>
#include <algorithm>
#include <sstream>
class Participants
{
int id;
int score;
std::string name;
public:
Participants(): id(0), score(0)
{}
Participants(int id, int score, std::string name): id(id), score(score), name(name)
{}
~Participants()
{}
int GetId()
{
return id;
}
std::string encode()
{
auto strRet = std::string( name + " " + std::to_string(id) + " " + std::to_string(score) + "\n");
return strRet;
}
void decode(std::string text)
{
std::stringstream ss(text);
std::string buf;
//Read Name
std::getline( ss, buf , ' ');
name = buf;
//Read id
std::getline( ss, buf , ' ');
id = std::stoi( buf );
//Read Score
std::getline( ss, buf , '\n');
score = std::stoi( buf );
}
};
class DataReader
{
std::string fileName;
std::fstream myfile;
public:
DataReader(std::string fileName): fileName(fileName)
{
}
~DataReader()
{
}
void ReadParticipants(std::map<int, Participants> &MapParticipants)
{
myfile.open(fileName, std::ios::in);
MapParticipants.clear();
if ( myfile.is_open() )
{
std::string line;
while ( std::getline(myfile, line) )
{
Participants oParticipants;
//Decode and Add to map
oParticipants.decode(line);
//Add to map
MapParticipants[ oParticipants.GetId() ] = oParticipants;
}
}
myfile.close();
}
void WriteParticipants(std::map<int, Participants> &MapParticipants)
{
//Load Map to find Duplicates
std::map<int, Participants> MapParticipants_exist;
ReadParticipants(MapParticipants_exist);
myfile.open(fileName, std::ios::app);
if ( myfile.is_open() )
{
for ( auto oParticipants : MapParticipants)
{
//Check for Duplicates (to Write or not)
if ( MapParticipants_exist.find(oParticipants.first) == MapParticipants_exist.end() )
{
auto text = oParticipants.second.encode();
myfile << text.c_str();
}
}
}
myfile.close();
}
};
int _tmain(int argc, _TCHAR* argv[])
{
DataReader oReader("File.txt");
std::map<int, Participants> MapParticipants;
//Make Some Participants
Participants p1(1, 50, "TOM");
Participants p2(2, 40, "TIM");
Participants p3(3, 80, "JERRY");
//Add them to map
MapParticipants[p1.GetId()] = p1;
MapParticipants[p2.GetId()] = p2;
MapParticipants[p3.GetId()] = p3;
oReader.WriteParticipants(MapParticipants);
oReader.ReadParticipants(MapParticipants);
//Find and Display
int id = 2;
auto it = MapParticipants.find(id);
if ( it != MapParticipants.end() )
{
//Show/Print
...
}
return 0;
}
I'm trying to take the profile info(username, email, etc.) from one directory and put it in another. I've been debugging the code for this program, and while there are no errors, the program won't run, saying that the program "has stopped working". I have already looked on this website and others for any possible answers, and found none.
#include <string>
#include <cstring>
#include <iostream>
#include <istream>
#include <ostream>
#include <fstream>
#include <iomanip>
#include <filesystem>
using namespace std;
class path{
public:
string parent_directory;
string root_directory;
};
class Data{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d){
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
int main(){
ifstream myfile("myfunk.txt", ios::in);
ofstream arena("arena.txt");
myfile.open("myfunk.txt", ios::in);
if(myfile){
cout << "Input file open." << endl;
}
arena.open("arena.txt", ios::out | ios::app);
if(arena){
cout << "Output file open." << endl;
}
cout << "file opening test: success" << endl;
int x = 0;
int y = 4101; //Total number of users in the directory.
int z = 0; //For inputting the required lines of info for each profile.
int profile = 0;
bool valid = false;
string role;
//string arenaRole;
bool post = false;
string line;
string p = "This PC/..."; //Path to the folder of the individual pictures.
//myVar.save("...");
string p = "...";
path path1;
path root_directory;
path parent_directory;
//bool is_directory(const std::filesystem::path& p, std::error_code& ec) noexcept; //Checks if current location is a directory.
//bool postPic;
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
cout << "All variables but the filesystem have been accepted! Please install this program on the network." << endl;
while(x < y){
cout << "Primary loop functioning" << endl;
if(post = true){
getline(myfile, line); //Grab and read next line.
myfile >> line;
line = userName[x];
arena << "Username: " << userName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = role[x];
arena << "Role: " << role[x] << "\n";
z++;
getline(myfile, line);
line = nickName[x];
myfile >> nickName[x];
arena << "nickname: " << nickName[x] << "\n";
z++;
getline(myfile, line);
line = fName[x];
myfile >> fName;
arena << "First Name: " << fName[x] << "\n";
z++;
getline(myfile, line);
line = lName[x];
myfile >> lName;
arena << "Last Name: " << lName[x] << "\n";
z++;
getline(myfile, line);
myfile >> line;
line = email[x];
arena << "Email: " << email[x] << "\n";
getline(myfile, line);
z = 0; //Next profile...
}
int data;
while(myfile >> data){
if(nickName[x] = NULL){
myfile >> "<Error> Some required information is missing! Contact user! </Error> /n";
valid = false;
post = false;
x++;
}
if(email[x] != NULL){
std::string str("#");
std::string str2(".com");
std::string str3(".net");
std::string str4(".edu");
if(std::size_t found = email[x].find(str) & (std::size_t found = email[x].find(str2) || std::size_t found = email[x].find(str3) || std::size_t found = email[x].find(str4)){
valid = true;
if(valid = true){
post = true;
}
}
else{
valid = false;
post = false;
x++;
}
}
}
}
}
}
x++;
}
//x++;
myfile.close(); //Closes the file in the directory.
arena.close(); //Closes the file in Arena.
return 0;
}
Let's rework your code.
First, let's create a data structure for the data:
class Data
{
public:
string userName;
string nickName;
string fName;
string arena_FName;
string lName;
string arena_LName;
string email;
string arenaEmail;
};
If you need an array for the data, it would be declared as:
const unsigned int MAXIMUM_DATA = 4100u;
Data database[MAXIMUM_DATA];
Next, let's overload the extraction operator>> to make reading easier:
class Data
{
public:
//...
friend std::istream& operator>>(std::istream& input, Data& d);
};
std::istream& operator>>(std::istream& input, Data& d)
{
std::getline(input, d.userName);
std::getline(input, d.nickName);
//...
std::getline(input, d.arenaEmail);
return input;
}
This simplifies your input loop to:
std::vector<Data> database;
Data d;
while (my_file >> d)
{
database.push_back(d);
}
You can query the amount of data read in by using the std::vector::size() method, i.e. database.size().
Also, you don't need a separate structure for a file path. A simple std::string will suffice. I recommend using forward slash, '/', because it is recognized by both Windows and *nix operating systems and won't be interpreted as an escape character.
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 7 years ago.
Using the following code in c++:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
class User
{
public:
User();
void setName(string username);
string getName();
private:
string name;
};
User::User()
{}
void User::setName(string username)
{
name = username;
}
string User::getName()
{
return name;
}
class System
{
public:
System();
void createUser();
void postMessage();
string getCurrentUser();
string messageBuffer;
private:
vector<User> users;
string currentUser;
};
System::System()
{
messageBuffer = "";
}
void System::createUser()
{
string username;
bool userExists = false;
cout << "Please enter a user name: ";
cin >> username;
cout << endl;
for(int i = 0; i < users.size(); i++)
{
if(users.at(i).getName() == username)
userExists = true;
}
if(!userExists)
{
User temp; //creates a temporary user stored in vector of Users
users.push_back(temp); //puts new User at end of users
users.back().setName(username);
currentUser = users.back().getName();
}
if(userExists)
cout << "User already exists." << endl << endl;
}
void System::postMessage()
{
string line;
string message;
cout << "Enter message: ";
while(getline(cin,line))
{
if(line == "!!")
break;
message = message + line + "\\n";
}
messageBuffer = "{[" + currentUser + "::tweet]}" + message + messageBuffer;
cout << endl;
}
string System::getCurrentUser()
{
return currentUser;
}
int main()
{
System system;
system.createUser(); //create user named Cam
system.postMessage(); //input message "Hello!"
cout << system.messageBuffer << endl;
return 0;
}
I am outputted with messageBuffer equal to "{[Cam]}\nHello!\n". What I want to happen is messageBuffer to be set to "{[Cam]}Hello!\n". The message inputted can be more than one line long.
Example message input could be:
Hello!
How are you all?
I am great!
!!
messageBuffer should then be:
"{[Cam]}Hello!\nHow are you all?\nI am great!\n"
In actuality I get:
"{[Cam]}\nHello!\nHow are you all?\nI am great!\n"
Where does this mystery "\n" come from?!
This is because you have to flush your stdin buffer before starting to read the messages (you have some unflushed characters which cause getline() to read it and apped \\n to the message string).
In your case I would advice to do it that way:
cin.clear();
cin.ignore(INT_MAX,'\n');
while(getline(cin,line))
if(line == "!!")
break;
message = message + line + "\\n";
}
I have a text file that has information format like this:
id last,first string
for example:
0 Snow,John nothing
1 Norris,Chuck everything
How do i get last name and first name stored separately?
To get information from file, I did:
#include <fstream>
int id;
string str;
string last;
string first;
int main()
{
ifstream myfile(ex.txt);
myfile >> id;
while (myfile)
{
for (int i = 0; i < 4; i++) // this is the amount of times i'll get information from 1 line
{
id = id; // its actually some_structure.id = id, omit
getline(myfile, last, ','); // i think i need to use another function as getline get the whole line
cout << id;
cout << last; // print out the whole line!
}
}
}
ifstream myfile;
string line;
while (getline(myfile, line))
{
istringstream ss(line);
int id;
ss >> id;
string fullname;
ss >> fullname;
string firstname, lastname;
{
istringstream ss2(fullname);
getline(ss2, lastname, ',');
getline(ss2, firstname);
}
}
if (std::ifstream input(filename))
{
int id;
string lastname, firstname, other_string;
while (input >> id && getline(input, lastname, ',') &&
input >> firstname >> other_string)
... do whatever you like...
if (!input.eof())
std::cerr << "error while parsing input\n";
}
else
std::cerr << "error while opening " << filename << '\n';
The code above has more error checking than the other answers I've seen, but admittedly - because it doesn't read text a line at a time then parse out the fields, it would happily accept e.g.:
10 Chuck,
Norris whatever
Would recomend something like this:
string name;
myfile >> id >> name >> str;
first = name.substr(0, name.find(","));
last = name.substr(name.find(",") + 1);
Note that your EOF checking is incorrect.
// The complete code that will do the job
// Please remove uncomment all code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("ex.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
string last = line.substr(line.find(" ") + 1, line.find(",") - 2);
string first = line.substr(line.find(",") + 1, line.find(",") + line.find(" ") - 1);
}
myfile.close();
}
else {
cout << "Unable to open file";
}
return 0;
}