Using getline to read data from a file in C++ - c++

I want to read from a file two things, the full name (first name and last name)
and age. After that I want to store them in an array then print the data.
However, when I try to reading the first record is read find, but the other two are not.
Please tell me what am I missing.
Thank you.
The content of the file is:
sampleFirst1 sampleLast1
30
sampleFirst2 sampleLast2
25
sampleFirst3 sampleLast3
40
The Output is:
Name: sampleFirst1 Age: 30
Name: Age: 30
Name: Age: 30
Here's my Code:
#include "Person.h"
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
ifstream inputFile("data.txt", ios::in);
string full_name;
int age = 0;
int i = 0;
Person personArray[3];
while (i < 3)
{
getline(inputFile, full_name);
personArray[i].set_name(full_name);
inputFile >> age;
personArray[i].set_age(age);
++i;
}
inputFile.close();
printData(personArray, 3);
cout << endl;
return 0;
}

You should not mix getline and the >> operator in that way. Prefer a simpler code like this one :
#include <iostream>
#include <fstream>
#include <array>
#include <string>
using namespace std;
struct Person {
std::string name;
int age;
void set_name(std::string const& i_name) { name = i_name; }
void set_age(int i_age) { age = i_age; }
};
int main()
{
ifstream inputFile("data.txt", ios::in);
std::string first;
std::string last;
int age = 0;
int i = 0;
std::array<Person,3> personArray;
while (i < personArray.size()) {
inputFile >> first >> last >> age;
personArray[i].set_name(first + " " + last);
personArray[i].set_age(age);
++i;
}
inputFile.close();
for(Person const& person : personArray) {
std::cout << "Name: " << person.name << " Age: " << person.age << "\n";
}
std::cout << std::flush;
return 0;
}
Or use only getline and a istringstream to pase the age if you dont want to pay the string concatenation extra cost for the full name.
A lot could be said of the parsing method but that is not the point here.

Related

How to skip reading the first line of file?

How can I ignore the first line of the text file and start at the second line when I called it in the code? I was wondering how. Also, how can I sort the file according to first name, last name and grade? I just have the first name sorted but not the last name and grade accordingly. If you have any idea, I hope you can share it with me. Thanks for the help! Here's my code:
#include <iostream>
#include <fstream>
using namespace std;
struct studentRecord{
string lastname;
string firstname;
string grade;
};
int main(){
ifstream ifs("student-file.txt");
string lastname, firstname, grade, key;
studentRecord records[20];
if(ifs.fail()) {
cout << "Error opening student records file" <<endl;
exit(1);
}
int i = 0;
while(! ifs.eof()){
ifs >> lastname >> firstname >> grade;
records[i].lastname = lastname;
records[i].firstname = firstname;
records[i].grade = grade;
i++;
}
for (int a = 1, b = 0; a < 20; a++) {
key = records[a].firstname ;
b = a-1;
while (b >= 0 && records[b].firstname > key) {
records[b+1].firstname = records[b].firstname;
b--;
}
records[b+1].firstname = key;
}
for (int k = 0; k < 20; k++) {
cout << "\n\t" << records[k].firstname << "\t"<< records[k].lastname << "\t" << records[k].grade;
}
}
When I saw this post it reminded me of a similar task completed at uni. I have rewritten your code to perform the same task but using classes instead of structs. I have also included a way to sort the vector by using the function here.
I have included the "ignore first line" method #Scheff's Cat mentioned.
Here it is:
#include <iostream>
#include <fstream>
#include <sstream>
#include <limits>
#include <string>
#include <vector>
using namespace std;
class studentrecord{
string firstname, lastname, grade;
public:
studentrecord(string firstname, string lastname, string grade){
this -> firstname = firstname;
this -> lastname = lastname;
this -> grade = grade;
}
friend ostream& operator<<(ostream& os, const studentrecord& studentrecord) {
os << "\n\t" << studentrecord.firstname << "\t" << studentrecord.lastname << "\t" << studentrecord.grade;
return os;
}
};
void displayRecords(vector <studentrecord*> records){
for(int i = 0; i < records.size(); i++){
cout << *records[i];
}
}
int main(){
//read in file
ifstream infile;
infile.open("student-file.txt");
infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (!infile.is_open()){
cout << "Error opening student records file" <<endl;
exit(1);
}
vector <studentrecord*> records;
string firstname, lastname, grade;
while (infile >> firstname >> lastname >> grade;) {
records.push_back(new studentrecord(firstname, lastname, grade));
}
displayRecords(records);
return 0;
}
To sort the vector so that it prints in order of either first name, last name or grade I used the following functions:
bool sortfirstname(studentrecord* A, studentrecord* B) {
return (A->getfirstname() < B->getfirstname());
}
bool sortlastname(studentrecord* A, studentrecord* B) {
return (A->getlastname() < B->getlastname());
}
bool sortgrade(studentrecord* A, studentrecord* B) {
return (A->getgrade() < B->getgrade());
}
sort(records.begin(), records.end(), (sortfirstname));
sort(records.begin(), records.end(), sortlastname);
sort(records.begin(), records.end(), sortgrade);
If you wanted to sort by first name you would call the sort(records.begin(), records.end(), (sortfirstname)); function and then the displayrecords() function.
The advantage of using classes stored in vectors is that you don't have to state the size of the vector containing the details about students since you can keep adding information to the end of the vector using the vector.push_back() function. It also makes sorting the data contained easier.
If anything isn't clear, let me know and I can give you a hand.

Store substring between double quotes in cpp

I am implementing the ALV tree, and I need to read input from the command line.
An example of the command is as follows:
insert “NAME_ANYTHING_IN_QUOTES_$” ID
where NAME_ANYTHING_IN_QUOTES_$ is the data being stored in the AVL tree, and ID is used to decide if the info will be stored in the left subtree or right subtree.
Code snipet is as follows:
if (comand == "insert")
{
int ID = 0;
string Name;
cin >> Name;
cin >> ID;
root = insertInfo(root, Name, ID);
}
I can not figure out how to scan in the substring that is between two double-quotes.
Thanks.
Use std::quoted:
std::string name;
std::cin >> std::quoted(name);
I found the answer....😊
string name,ID,concat;
getline(cin, concat);
for(int i =0; i< concat.length();i++){
if(!isdigit(concat[i])&& concat[i] != 34){
name += concat[i];
}
if(isdigit(concat[i])){
ID += concat[i];
}
}
cout<<"name is ->"<<name<<endl;
cout<<"ID is ->"<<ID<<endl;
I'm just adding to HolyBlackCat's answer above.
Here's code that works:
#include <iostream>
#include <iomanip>
using namespace std;
int main(int argc, const char** argv)
{
//if (comand == "insert")
{
int ID = 0;
string Name;
cin >> std::quoted(Name);
cin >> ID;
cout << "name is " << Name << " and ID is " << ID << endl;
//root = insertInfo(root, Name, ID);
}
}
When input is "MyName_$" 34
I get
name is MyName_$ and ID is 34
So, HolyBlackCat's solution works. Show us your code and input.
On second thought, those strange open and close braces may depend on the font, etc. The std::quoted should have worked for you, but it you say it doesnt. Let us know what env and compiler you are using. If you're sure they're always there, you can just delete the first and last char in that string as in:
#include <iostream>
#include <string>
using namespace std;
int main(int argc, const char** argv)
{
//if (comand == "insert")
{
int ID = 0;
string Name;
cin >> Name;
Name.erase(0, 1);
Name.erase(Name.length() - 1, 1);
cin >> ID;
cout << "name is " << Name << " and ID is " << ID << endl;
//root = insertInfo(root, Name, ID);
}
}

C++ Trouble parsing telephone number using istringstream and istringstream.ignore

I'll say first that sending my code a hardcoded, perfectly formatted string works fine. But when letting user input string, the code parses areaCode but fails during exchange parsing. Here is my .h
// PhoneNumber.h
#ifndef PHONENUMBER_H
#define PHONENUMBER_H
#include <string>
class PhoneNumber {
private:
short areaCode;
short exchange;
short line;
public:
PhoneNumber(std::string number);
void setPhoneNumber(std::string number);
std::string getPhoneNumber() const;
void printPhoneNumber() const;
};
#endif
Here is my .cpp implementation
// PhoneNumber.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <cctype>
#include <stdexcept>
#include "PhoneNumber.h"
PhoneNumber::PhoneNumber(std::string number) {
setPhoneNumber(number);
}
void PhoneNumber::setPhoneNumber(std::string number) {
int length = number.length();
std::istringstream iss(number);
int count = 0;
while (!isdigit(number[count])) {
count += 1;
iss.ignore(1);
}
iss >> std::setw(3) >> areaCode;
count += 3;
while (!isdigit(number[count])) {
count += 1;
iss.ignore(1);
}
iss >> std::setw(3) >> exchange;
count += 3;
while (!isdigit(number[count])) {
count += 1;
iss.ignore(1);
}
if (length - count < 4) {
throw std::invalid_argument("Something wrong with your phone number input");
}
else {
iss >> std::setw(4) >> line;
}
}
void PhoneNumber::printPhoneNumber() const {
std::cout << "(" << areaCode << ") " << exchange << "-" << line;
}
And now my short test code.
// PhoneNumber testing
#include <iostream>
#include <string>
#include "PhoneNumber.h"
int main() {
std::string p1;
std::cout << "Enter phone number in format of (800) 555-1212: ";
std::cin >> p1;
PhoneNumber phone1(p1);
phone1.printPhoneNumber();
std::cout << std::endl;
}
I have tried to write my setPhoneNumber code so that it is user error tolerant. So first question is how do I make this work with user input? Secondary (need not be answered) why does it work with hardcoded telephone number string and not user input?
std::cin >> p1;
will only read to the first space or carriage return. So, if the user inputs (800) 555-0123, you'll only read "(800)".
You need
std::getline(std::cin, p1);
to read the input.
The reason it works with a hardcoded string is that the string assignment operator is not affected by this. When you code p1 = "(800) 555-0123";, p1 gets set to "(800) 555-0123"

C++ program hangs when using cin.getline()

I am making a program keeping track of different persons, which I try to read in from a file. I use a constructor that takes an ifstream file as an argument, and I then try to read in the data from the file. I can read the first line, which is just an int (a unique number for each person), but when I try to go to the next line and getline it, the program hangs. Does anyone know why?
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
#include <cstdlib>
using namespace std;
const int MAXPERS = 100;
const int MAXTXT = 80;
const int DATELEN = 7;
class Person {
private:
int nr;
char* firstName;
char birthDate[DATELEN];
public:
Person() {
char fname[MAXTXT];
cout << "First name: "; cin.getline(fname, MAXTXT);
firstName = new char[strlen(fname) + 1];
strcpy(firstName, fname);
cout << "Birth date (DDMMYY): ";
cin >> birthDate; cin.ignore();
}
Person(int n, ifstream & in) {
nr = n;
char fname[MAXTXT];
cin.getline(fname, MAXTXT);
firstName = new char[strlen(fname) + 1];
strcpy(firstName, fname);
in >> birthDate;
}
void display() {
cout << "\nFirst name: " << firstName;
cout << "\nBorn: " << birthDate;
}
void writeToFile(ofstream & ut) {
ut << firstName << "\n" << birthDate;
}
};
void readFromFile();
Person* persons[MAXPERS + 1];
int lastUsed = 0;
int main() {
readFromFile();
persons[1]->display();
return 0;
}
void readFromFile() {
ifstream infile("ANSATTE.DAT");
if(infile) {
while(!infile.eof() && lastUsed < MAXPERS) {
int nr;
infile >> nr;
persons[++lastUsed] = new Person(nr, infile);
}
}
}
My file looks like this:
1
Andy
180885
2
Michael
230399
In your constructor you have
cin.getline(fnavn, MAXTXT);
So your program is waiting for you to type something in. If you meant to get the name from the file then you need
in.getline(fnavn, MAXTXT);
^^ ifstream object
You are also going to run into the issue of mixing >> with getline. You will need to add
infile.ignore(std::numeric_limits<std::streamsize>::max(), '\n')
after infile >> nr; in your while loop.
strlen(fname + 1) will be strlen(fname) - 1 if fname is one-character long or more and indeterminate if fname is zero-character long. It should be strlen(fname) + 1.
strlen(fnavn + 1) has the same issue and should be strlen(fnavn) + 1.

Reading from File and store in differernt arrays

I need coding for reading from File and store in differernt arrays !!!
for eg :
paul 23 54
john 32 56
My requirement are as follows: I need to store paul,john in string array and 23,32 in one integer array; and similarly 54,56 in another int array.
I read the inputs from the file and print it but I am unable to save in 3 different arrays.
int main()
{
string name;
int score;
ifstream inFile ;
inFile.open("try.txt");
while(getline(inFile,name))
{
cout<<name<<endl;
}
inFile.close();
}
So kindly suggest me some logics for doin this and I would really appreciate that... !!!
I assume you are new to programming? Or new to C++? So I provided the sample code to get you started. :)
#include <string>;
#include <iostream>
#include <vector>
using namespace std;
int main() {
vector<string> name;
vector<int> veca, vecb;
string n;
int a, b;
ifstream fin("try.txt");
while (fin >> n >> a >> b) {
name.push_back(n);
veca.push_back(a);
vecb.push_back(b);
cout << n << ' ' << a << ' ' << b << endl;
}
fin.close()
return 0;
}
You can try the following code:
#include <string>
#include <vector>
#include <iostream>
#include <fstream>
int main()
{
std::string fileToRead = "file.log";
std::vector<int> column2, column3;
std::vector<std::string> names;
int number1, number2;
std::string strName;
std::fstream fileStream(fileToRead, std::ios::in);
while (fileStream>> strName >> number1 >> number2)
{
names.push_back(strName);
column2.push_back(number1);
column3.push_back(number2);
std::cout << "Value1=" << strName
<< "; Value2=" << number1
<< "; value2=" << number2
<< std::endl;
}
fileStream.close();
return 0;
}
The idea is to read the first column in file to a string (strName) and then push it to a vector (names). Similarly, second and third columns are read into number1 and number2 first and then pushed into vectors named column1 and column2, respectively.
Running it will get you the following results:
Value1=paul; Value2=23; value2=54
Value1=john; Value2=32; value2=56