C++ Problem with using getline for strings in a text file - c++

I am writing a program that takes a text file and inputs the values from the text file into class functions and a vector. I am using a while loop that uses getline to collect the values from the text file. The issue I am having is that getline functions properly, but only on the second line of the text file. It seems to be either skipping the first line of the file or the first line is somehow overwritten by the second line.
Code as follows
void readContacts(vector<Person>& contacts, ifstream& infile)
{
Person temp;
string line;
cout << " " << endl;
cout << "File opening ... " << endl;
while(getline(infile, line))
{
cout << " " << endl;
infile >> line;
temp.setFirstName(line);
cout << "First Name: " << line << endl;
infile >> line;
temp.setLastName(line);
cout << "Last Name: " << line << endl;
infile >> line;
temp.setPhone(line);
cout << "Phone Number: " << line << endl;
infile >> line;
temp.setEmail(line);
cout << "Email: " << line << endl;
contacts.push_back(temp);
}
}
The text file contains
Kortni Neal 555-555-5555 kdd195#google.com
Aubrey Knight 444-444-4444 akk5#google.com
The console outputs
Welcome to your address book manager!
Please enter a file to read your contacts from (include extension): contacts.txt
File opening ...
First Name: Aubrey
Last Name: Knight
Phone Number: 444-444-4444
Email: akk5#google.com
First Name:
Last Name:
Phone Number:
Email:
File read. Closing the file from read mode.
Menu:
0. Exit
1. Display Address Book
2. Add Contact
What would you like to do?
Thanks for your help.

Yes it does, because the getline() function call reads the first line.
Then you go in and do a infile >> line, which reads starting from the second line.
If you had more lines in your file, you would have seen that it would have skipped every other line .

Related

Why isn't my file reading the inputs correctly in this program?

So I'm trying to build a program for myself(for the time being) where basically I have the option of adding in books that I've completed, including the name of the author and the dates of completion, which is supposed to add the input into a file, and then I have another option that's supposed to just read off the entries onto the txt file line by line to display each entry. The only problem is that when I'm inputting each entry, I can't seem to get passed the input for "author", and when it's stored into the file it looks like this for example: (after inputting "for whom the bell tolls") for/twhom/t0-858993460-858993460. It also doesn't seem to retain the entries past the first(incomplete) entry.
Anybody have suggestions for how I could fix this? File handling is definitely something that I've had some of the most trouble with, so I'd really appreciate figuring out how to fix similar problems I might have in the future.
Sample of what the input file should look like:
Title: Author: Date:
book1 name1 01-01-2022
book2 name2 01-02-2022
book3 name3 01-03-2022
Here's the source:
`
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//Program will enter books into a file and display the amount of books read, and the completed books
int main() {
fstream completedBooks;
int booksRead,
monthOfCompletion,
dayOfCompletion,
yearOfCompletion,
option;
string bookTitle,
author,
booksFinished;
cout << "book tracker: \n" << "1.) add entry \n" << "2.) print list \n";
cout << "Enter which option you would like to choose: \n";
cin >> option;
if (option == 1) {
completedBooks.open("completedBooks.txt", ios::out);//writing into book list
if (completedBooks.is_open()) {
completedBooks << "Title: Author: Date:" << endl;
completedBooks.close();
}
completedBooks.open("completedBooks.txt", ios::app);//appending input into book list
if (completedBooks.is_open()) {//Gathering input for book
cout << "Enter the name of the most recent book you've read: \n";
cin >> bookTitle;
//Gathering input for author
cout << "Enter the name of the author of that book: \n";
cin >> author;
//Getting input for dates
cout << "Enter the month you completed the book: \n";
cin >> monthOfCompletion;
cout << "Enter the day you completed the book: \n ";
cin >> dayOfCompletion;
cout << "Enter the year you completed the book: \n ";
cin >> yearOfCompletion;
//Storing input into file
completedBooks << bookTitle << "/t" << author << "/t"
<< monthOfCompletion << dayOfCompletion << yearOfCompletion;
completedBooks.close();
}
}
if (option == 2) {
completedBooks.open("completedBooks.txt", ios::in);
if (completedBooks.is_open()) {//displaying text in book list
string line;
while (getline(completedBooks, line)) {
cout << line << endl;
}
completedBooks.close();
}
}
return 0;
}
You have to flush cin before reading the line.
If you use this, should do the trick:
if (completedBooks.is_open())
{ // Gathering input for book
cout << "Enter the name of the most recent book you've read: \n";
cin >> ws;
getline(cin, bookTitle);
// Gathering input for author
cout << "Enter the name of the author of that book: \n";
cin >> ws;
getline(cin, author);
// Getting input for dates
cout << "Enter the month you completed the book: \n";
cin >> monthOfCompletion;
cout << "Enter the day you completed the book: \n";
cin >> dayOfCompletion;
cout << "Enter the year you completed the book: \n";
cin >> yearOfCompletion;
// Storing input into file
completedBooks << bookTitle << "\t" << author << "\t"
<< monthOfCompletion << "-" << dayOfCompletion << "-" << yearOfCompletion;
completedBooks.close();
}
Altough, to get the desired output you will have to format the line to write in the file. You can use setw to give a maximum width to the title and author.

Finding a string in a text file and displaying the entire line in c++

I want my program to look for a student's name in a text file and then display that particular line.
I'm just getting the first line of the text file as output and not the line I'm looking for.
void OTHERS::search_acc()
{
string srch;
string line;
fstream Myfile;
Myfile.open("STUDENTS", ios::in|ios::out);
cout << "\nEnter Student Name: ";
cin.ignore();
getline(cin, srch);
if(Myfile.is_open()) //The problem is in this if block
{
getline(Myfile, line);
line.find(srch, 0);
cout << "\nSearch result is as follows: \n" << line << endl;
}
else
{
cout << "\nSearch Failed... Student not found!" << endl;
system("PAUSE");
}
}
Also, is it possible to return the location of the string I'm looking for in the text file?
You need to read all the lines in a loop, and search in each one of them, e.g.
if(Myfile.is_open())
{
while(getline(Myfile, line)) // read all the lines
if (line.find(srch) != std::string::npos) // search each line
cout << "\nFound on this line: \n" << line << endl;
}
int line=0;
while(!Myfile.eof()){
getline(Myfile, line);
line.find(srch, 0);
++line;
}
//this line will tell you the line number
cout << "\nSearch result is as follows: \n" << line << endl;
you are reading one line read the whole file

Display abnormal for read a txt file

I wrote some codes below.The types of title and authors are char array and i can not change it.When data is inputed from keyboard the result is normal.
void BookException::getBook()
{
cout<<"Id number: ";
cin>>booknum;
cout<<"Title: ";
cin.ignore(numeric_limits<streamsize>::max(), '\n');
cin.getline(title, sizeof(title), '\n');
cout<<"Authors: ";
cin.getline(authors, sizeof(authors), '\n');
cout<<"Number of pages:";
cin>>pagenum;
cout<<"Price: ";
cin>>price;
cout<<"over"<<endl;
}
Here is input text below
1
How to program C++
Paul Deitel, Harvey Deitel
1028
112.83
But when I try to read some text from a txt file.It displaied like this:
Id number: Title: Authors: Number of pages:Price: The no. 0 book error.
Title:
Authors:
Number of pages: 0
Price: 0.00
Incorrect price.
I think getline due to problem but i do not know how to fix it.Thank you.
I don't see the file being passed in or opened in your code. Also you never print any of the variables after you read them or newlines. Using strings would be much easier but if you have to use char arrays I would suggest writing a function to convert from c-string to string and back also, see: c_str().
void BookException::getBook() {
string booknum, title, authors, pagenum, price;
ifstream fin; //file in
fin.open("book.txt"); //Open the file
getline(fin, booknum); //Read line from file first
cout << "Id number: " << booknum << endl; //Then print
getline(fin, title);
cout << "Title: " << title << endl;
getline(fin, authors);
cout << "Authors: " << authors << endl;
getline(fin, pagenum);
cout << "Number of pages:" << pagenum << endl;
getline(fin, price);
cout << "Price: " << price << endl;
cout << "over" << endl;
fin.close(); //Close the file
}
I suggest reading this unless you understand all this: input/output with files
getline() usage can be found here.

Reading data line by line from a text file

Each line of the text file has first name, last name, and a salary. Something along the lines of this:
john doe 4000
bob miller 9000
I want my program to take the first name, last name, and salary of each line and assign them to strings (or integers). I have tried this so far:
while (inFile){
inFile >> firstName;
inFile >> lastName;
inFile >> grossPay;
cout << firstName << " " << lastName << " " << grossPay << endl;
}
When it outputs the names and the salary, the last line of the text file gets output twice by the program. How can I fix this?
After reading your last line, inFile is still in a valid state.
It's only when it tries to read more that your test would fail, but control has already entered the loop an additional time.
You want to test after reading.
while ( inFile >> firstName >> lastName >> grossPay ){
// ^^ Now the test happens AFTER reading...
cout << firstName << " " << lastName << " " << grossPay << endl;
}

Weird Text File Output and Writing Issues

In my code:
int newEntry()
{
string input;
Client person;
char response = 'y';
//create file object and open file
fstream customer("customer.dat", ios::out | ios::app);
if (!customer)
{
cout << "Error opening file. Program aborting." << endl;
return 0;
}
do
{
cout << "Enter person information:" << endl << endl;
cout << "Name: " << endl;
getline(cin, input);
strcpy(person.name, input.c_str());
cout << endl << "Street Adress (And Apartment Number):" << endl;
cin >> person.address1;
getline(cin, input);
strcpy(person.address1, input.c_str());
cout << endl << "City, State, Zipcode: " << endl;
cin >> person.address2;
getline(cin, input);
strcpy(person.address2, input.c_str());
cout << endl << "Phone: " << endl;
cin >> person.phone;
getline(cin, input);
strcpy(person.phone, input.c_str());
cout << endl << "Account Balance: " << endl;
cin >> person.acctBal;
//input validation to ensure a non neg number
cin.ignore();
cout << endl << "Last Payment: " << endl;
cin >> person.lastPay;
//input validation to ensure a non neg number
customer.write(reinterpret_cast<char *>(&person),
sizeof(person));
cout << endl << "Do you want to enter another record? (Enter Y for Yes, N
for No) " << endl;
cin >> response;
cout << "_______________________________________________" << endl << endl;
if (toupper(response) == 'Y')
{
cin.ignore();
}
} while (toupper(response) == 'Y');
customer.close();
return 1;
}
It seems as though the block:
cout << endl << "Street Address (And Apartment Number):" << endl;
cin >> person.address1;
getline(cin,input);
strcpy(person.address1, input.c_str());
and its neighboring address 2 prompt (identical) are causing bad output to the file when
customer.write(reinterpret_cast<char *>(&person),sizeof(person));
is used to write to the file. The output is missing the very first word . For example if "211 Harvey Road" was entered, 211 would be cut off. Another example, if "Harvey Road" was entered, than it seems as though "harvey" is cut off. When (in another function) the file is read, the structure of arrays is missing the beginning, as well as the file.
On top of that, in the textfile, this is the data being written to it:
Frank Palmasani ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ Harvey Road ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ Haven, Alabama ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ 504617772 ÌÌÌÌ èŽ# èŽ#James Harris ni ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ Street AVEN ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ China. Alabama ÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌÌ 546457474 ÌÌÌÌ ð? ð?
As you can see, where the Ì are popping up is where the file and program are somehow losing the first word. I have tried everything I can think of to fix this problem, hopefully someobody else has ran into a similar problem.
I have tried changing methods of saving the data held in the structure of arrays to the file, but found that I couldn't read from the file in one large grouping. In my text book, the method I used to read out to the file is used so that is the one I believe I should follow.
However, I am considering writing each one separately on each line, and saving it precisely in the order so that I can read it in the same order, saving it to a structure of vectors. Again, I'd I would like to avoid that but would love to hear your opinion on the matter whether if you are able to help me here or not.
In case you needed it, here is my structure:
const int NAME_SIZE = 51, ADDR_SIZE = 51, PHONE_SIZE = 14;
struct Client
{
char name[NAME_SIZE];
char address1[ADDR_SIZE];
char address2[ADDR_SIZE];
char phone[PHONE_SIZE];
double acctBal;
double lastPay;
};
Your output file looks like that because you are doing a raw dump of the Client struct. So there will be 51 bytes written for name, 51 for address1, etc. Regardless of string length.
You need to properly write each field individually.
customer << input.name << endl;
customer << input.address1 << endl;
etc.....
cout << endl << "Street Adress (And Apartment Number):" << endl;
cin >> person.address1;
getline(cin, input);
strcpy(person.address1, input.c_str());
You're getting the first token, in the case you mentioned 211 and putting it in address1, then getting the rest of the line and replacing what was in address1 with it. That's where your 211 went.
You should open the file in binary mode if your intent is to write/read entire structures as a binary blob like this. If you want to store the data as text use std::string, avoid the strcpy mess, and write/read each member individually on their own ines.