Using the getline function in C++ to extract certain characters - c++

I need to get only specific characters from a text file. I am using the getline() function in C++. my compiler keeps giving me the error that there is no matching member function call for getline(), how can I fix that?
I'm trying to pull last names and scores from the file.
the file looks like:
Weems 50 60
Dale 51 60
Richards 57 60
...
Here's the code I'm trying:
#include <iostream>
#include <cmath>
#include <fstream>
using namespace std;
int main ()
{
//input variables
float GradeScore;
float TotalPoints;
float GradePercent;
string LastName;
ifstream myFile;
//open file
myFile.open ("/Users/ravenlawrence/Documents/TestGrades.rtf",ios::in);
// if file is open
if (myFile.is_open()) {
while(!myFile.eof()) {
string data;
getline(myFile,data); //reading data on line
myFile.getline(LastName, ' ');//storing data in LastName
myFile.getLine(GradeScore,' ');//storing data in GradeScore
myFile.getLine(TotalPoints,' ');//storing data in Total Points
cout << LastName << endl;
// cout<<data<<endl; //print it out
}
}
return 0;
}

Begin with a design, breaking down the work into small steps:
open file
loop, reading line from file while more lines
split line into fields
convert fields into variables
display variables
Now tackle each step
// open file
ifstream myFile ("/Users/ravenlawrence/Documents/TestGrades.rtf",ios::in);
if( ! myFile ) {
cerr << "cannot open file\n";
exit(1);
}
//loop, reading line from file while more lines
string data;
while( getline( myFile, data ) ) {
// split line into fields
std::stringstream sst(data);
std::string a;
std::vector<string> vfield;
while( getline( sst, a, ' ' ) )
vfield.push_back(a);
// ignore lines that do not contain exactly three fields
if( vfield.size() != 3 )
continue;
//convert fields into variables
LastName = vfield[0];
GradeScore = atof( vfield[1].c_str() );
TotalPoints = atof( vfield[2].c_str() );
// display
...
}

You do not need to use the function getline here, you can read file word by word.Secondly, you need to close the file after it reaches eof. Here is the code:
int main()
{
//input variables
float GradeScore;
float TotalPoints;
float GradePercent;
string LastName;
ifstream myFile;
//open file
myFile.open("check.txt", ios::in);
// if file is open
if (myFile.is_open()) {
while (!myFile.eof()) {
myFile >> LastName;//storing data in LastName
myFile >> GradeScore;//storing data in GradeScore
myFile >> TotalPoints;//storing data in Total Points
cout << LastName << endl;
// cout<<data<<endl; //print it out
}
myFile.close();
}
system("pause");
return 0;
}
Rather than checking if file is open or not a better approach is to check if file exist or not:
if(!myfile)
{
cout<<"error!file donot exist";
}

Related

How to load data into a vector from a text file that has been created inside the same program. in C++

I want to load data from a Text file that has been created in the same program into a vector of strings. But no line of text is getting pushed into the vector here.
Here First I am reading data from some input file and then doing some operations (Removing extra spaces) on it then I save this file as "intermediate.txt". This intermediate.txt is being created and all the operations that I want to do happen successfully. Finally, I want to read this file into a vector<string> code but it doesn't work. I can't store anything in the vector<string> code. Its size is Zero.
#include <bits/stdc++.h>
using namespace std;
int main()
{
string inputFileName;
cout << "Enter the Input File Name: ";
cin >> inputFileName;
ifstream f1(inputFileName);
ofstream f0("intermediate.txt");
string text_line;
while (getline(f1, text_line))
{
string word;
istringstream text_stream(text_line);
while (text_stream >> word)
{
f0 << word << " ";
}
f0 << "\n";
}
f0.close()
ifstream file("intermediate.txt");
vector<string> code;
string line;
while (getline(file, line, '\n'))
{
code.push_back(line);
}
for (auto it : code)
{
cout << it << "\n";
}
}
Here's a mini-code review:
#include <bits/stdc++.h> // Don't do this; doesn't even compile for me
using namespace std; // Don't do this either
int main()
{
string inputFileName;
cout << "Enter the Input File Name: ";
cin >> inputFileName;
ifstream f1(inputFileName); // Bad name
ofstream f0("intermediate.txt"); // Bad name
// You never check that you successfully opened *any* files.
string text_line;
/*
* You don't describe why this is necessary, can a line not be read and
* written as-is? Is it already a line of space-separated variables?
*
* In any case, this is where you already have the words; so store them in
* the vector here as well.
*/
while (getline(f1, text_line))
{
string word;
istringstream text_stream(text_line);
while (text_stream >> word)
{
f0 << word << " ";
}
f0 << "\n";
}
f0.close() // Forgot your semi-colon
// Left f1 open, that's bad practice
ifstream file("intermediate.txt");
vector<string> code;
string line;
/*
* I would hope you felt that reading from a file, writing to a new file,
* closing both files, opening the new file, and reading from the new file
* into the vector was wasteful.
*/
while (getline(file, line, '\n'))
{
code.push_back(line);
}
for (auto it : code)
{
cout << it << "\n";
}
}
The most immediate issue with your original question was that you tried to open the same file in two different streams. The second time, the file failed to open, but because you never check if you actually opened the file, you assumed everything worked fine, but it didn't, which brought you here.
However, there is a better way.
#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>
int main() {
std::string inputFileName;
std::cout << "Enter the Input File Name: ";
std::cin >> inputFileName;
// Always check that you successuflly opened the file.
std::ifstream fin(inputFileName);
if (!fin) {
std::cerr << "Error opening: " << inputFileName << ". Exiting...\n";
return 1;
}
std::ofstream fout("intermediate.txt");
if (!fout) {
std::cerr << "Error opening: intermediate.txt. Exiting...\n";
return 2;
}
std::vector<std::string> code;
std::string text_line;
while (std::getline(fin, text_line)) // You've read the line
{
std::string word;
std::istringstream text_stream(text_line);
while (text_stream >> word) {
fout << word << " ";
}
fout << "\n";
code.push_back(text_line); // Just store it while you have it
}
fin.close(); // Best practice is to close a file as soon as you're done
fout.close(); // with it. Don't hog resources.
for (const auto& it : code) // Avoid making copies
{
std::cout << it << "\n";
}
}
The while loop, where you read the lines that you want to store in the vector, now writes to your file and stores the lines into the vector. We also now check whether we successfully opened files, and we close the file streams as soon as we're done with the file so as to not keep it locked for no good reason.
A good next step for improving this program a bit more would be to avoid asking the user for a file name. Instead, take it as an argument to main(). That way, someone only has to type ./a.out input.txt on the command line and the program will do the job automatically.

Need help taking a line from a text file and sorting that line into multiple variables

I`m trying to take a name and 3 numbers from a text file then take that input and store the name into color and the 3 numbers into r,g,b then it will take the r,g,b numbers and turn them into hex color codes.the text file format is as follows
color1 190 190 190
color2 20 50 70
This following code is where my problem lies
ifstream ReadFile;
ReadFile.open(filename);
if(ReadFile.fail())
{
cout<<"Could not open "<<filename<<endl;
}
else
{
while ( getline (ReadFile,line) )
{
cout << line << '\n';
}
}
//for(string line; getline(ReadFile, line, '.'); )
//{
//cout<<line<<endl;
//}
ReadFile.close();
//cout<<"Enter the value of RGB(from range 0 to 255):";
cin>>r>>g>>b;
cout<<rgbtohex(r,b,g,true)<<endl;
You have to read file line by line and tokenize that line with space delemeter
std::ifstream file("fileName");
std::string line;
while(std::getline(file, line))
{
std::stringstream linestream(line);
std::string data;
std::string color;
int r;
int g;
int b;
// If you have truly space delimited data use getline() with third parameter.
// If your data is just white space separated data
// then the operator >> will do (it reads a space separated word into a string).
// so no need to third params
std::getline(linestream, data);
// example of comma delemeter
//std::getline(linestream, data,',');
// Read the integers using the operator >>
linestream >> r>> g>>b;
// and before calling close file file you have store all r,g,b value other wise
//process within this loop
}
I assume you seems to be having issue parsing the input line to get the color name, r, g, b values as your code for reading from text file is correct. For that, you can use istringstream object (iss) to get the values for multiple variables of different types separated by spaces from each file line
#include<iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main () {
string filename = "colors.txt"; // Color input file
ifstream ReadFile;
istringstream iss;
ReadFile.open(filename);
string line, color;
int r, g, b;
if(ReadFile.fail()) {
cout<<"Could not open "<<filename<<endl;
}
else {
while (getline (ReadFile,line)) {
iss.clear();
iss.str(line);
iss >> color >> r >> g >> b;
cout << "Color: " << color << endl;
cout << "R: " << r << endl;
cout << "G: " << g << endl;
cout << "B: " << b << endl;
}
ReadFile.close();
}
}

The number of lines is always 0

Why is the number of lines always 0? It should be 10, but the output is always 0.Is anything wrong with the method?
int main() {
vector<double> doubleCoefficient; // vector to store unknown number of equations (double)
/* Read from file and assign values to vector */
//File stream object
ifstream inputFile;
//Open the txt file
inputFile.open("test.txt");
//search for the text file
if(!inputFile.is_open())
{
cerr << "Error opening file \n";
exit(EXIT_FAILURE);
}
else
{
cout << "File found and successfully opened. \n";
}
double x;
while(!inputFile.eof()){
inputFile >> x;
doubleCoefficient.push_back(x);
}
int count =0;
string line;
while (getline(inputFile, line)){
count++;
}
cout << "Number of lines in text file:" << count << endl;
inputFile.close();
}
With while(!inputFile.eof()) You go to the end of the file, so after that, You cann't read lines.
You need to go back to the start using fseek()
try
fseek ( inputFile , 0 , SEEK_SET );
before counting the lines.

Avoiding the use of eof in this case

I have posted the following code where I am reading from an input file -- storing information in a structure -- and then writing to an output file. I know that the eof function is not safe and hence one must use the getline function to check whether the end of file has been detected or not; however, in this particular code, I have not been able to use the getline function and hence has finally relied on the eof function. Hence, can you please suggest an alternative to the eof function or let me know how I can use the getline function when I am trying to initialize an array of structures . I have used two asterisk symbols to indicate where I want to use the getline function.
#include <iostream>
#include <fstream>
using namespace std;
//student structure
struct student
{
char name[30];
char course[15];
int age;
float GPA;
};
ifstream inFile;
ofstream outFile;
student getData();
void writeData(student writeStudent);
void openFile();
int main (void)
{
const int noOfStudents = 3; // Total no of students
openFile(); // opening input and output files
student students[noOfStudents]; // array of students
// Reading the data from the file and populating the array
for(int i = 0; i < noOfStudents; i++)
{
if (!inFile.eof()) // ** This where I am trying to use a getline function.
students[i] = getData();
else
break ;
}
for(int i = 0; i < noOfStudents; i++)
writeData(students[i]);
// Closing the input and output files
inFile.close ( ) ;
outFile.close ( ) ;
}
void openFile()
{
inFile.open("input.txt", ios::in);
inFile.seekg(0L, ios::beg);
outFile.open("output.txt", ios::out | ios::app);
outFile.seekp(0L, ios::end);
if(!inFile || !outFile)
{
cout << "Error in opening the file" << endl;
exit(1);
}
}
student getData()
{
student tempStudent;
// temp variables for reading the data from file
char tempAge[2];
char tempGPA[5];
// Reading a line from the file and assigning to the variables
inFile.getline(tempStudent.name, '\n');
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
tempStudent.age = atoi(tempAge);
inFile.getline(tempGPA, '\n');
tempStudent.GPA = atof(tempGPA);
// Returning the tempStudent structure
return tempStudent;
}
void writeData(student writeStudent)
{
outFile << writeStudent.name << endl;
outFile << writeStudent.course << endl;
outFile << writeStudent.age << endl;
outFile << writeStudent.GPA << endl;
}
You want to write an operator>> for your student type. Something like:
std::istream& operator>>(std::istream& in, student& s) {
in >> s.age; // etc.
return in;
}
Which then allows you to write:
int studentNo = 0;
students[maxStudents];
while (studentNo < maxStudents && (in >> students[studentNo]))
++studentNo;
Why not write this way?
instead of
inFile.getline(tempStudent.name, '\n');
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
You may
while(inFile.getline(tempStudent.name, '\n'))
{
inFile.getline(tempStudent.course, '\n');
inFile.getline(tempAge, '\n');
//do stuffs
}

Input line by line from an input file and tokenize using strtok() and the output into an output file

What I am trying to do is to input a file LINE BY LINE and tokenize and output into an output file.What I have been able to do is input the first line in the file but my problem is that i am unable to input the next line to tokenize so that it could be saved as a second line in the output file,this is what i could do so far fro inputing the first line in the file.
#include <iostream>
#include<string> //string library
#include<fstream> //I/O stream input and output library
using namespace std;
const int MAX=300; //intialization a constant called MAX for line length
int main()
{
ifstream in; //delcraing instream
ofstream out; //declaring outstream
char oneline[MAX]; //declaring character called oneline with a length MAX
in.open("infile.txt"); //open instream
out.open("outfile.txt"); //opens outstream
while(in)
{
in.getline(oneline,MAX); //get first line in instream
char *ptr; //Declaring a character pointer
ptr = strtok(oneline," ,");
//pointer scans first token in line and removes any delimiters
while(ptr!=NULL)
{
out<<ptr<<" "; //outputs file into copy file
ptr=strtok(NULL," ,");
//pointer moves to second token after first scan is over
}
}
in.close(); //closes in file
out.close(); //closes out file
return 0;
}
The C++ String Toolkit Library (StrTk) has the following solution to your problem:
#include <iostream>
#include <string>
#include <deque>
#include "strtk.hpp"
int main()
{
std::deque<std::string> word_list;
strtk::for_each_line("data.txt",
[&word_list](const std::string& line)
{
const std::string delimiters = "\t\r\n ,,.;:'\""
"!##$%^&*_-=+`~/\\"
"()[]{}<>";
strtk::parse(line,delimiters,word_list);
});
std::cout << strtk::join(" ",word_list) << std::endl;
return 0;
}
More examples can be found Here
You are using C runtime library when C++ makes this neater.
Code to do this in C++:
ifstream in; //delcraing instream
ofstream out; //declaring outstream
string oneline;
in.open("infile.txt"); //open instream
out.open("outfile.txt"); //opens outstream
while(getline(in, oneline))
{
size_t begin(0);
size_t end;
do
{
end = oneline.find_first_of(" ,", begin);
//outputs file into copy file
out << oneline.substr(begin,
(end == string::npos ? oneline.size() : end) - begin) << ' ';
begin = end+1;
//pointer moves to second token after first scan is over
}
while (end != string::npos);
}
in.close(); //closes in file
out.close(); //closes out file
Input:
a,b c
de fg,hijklmn
Output:
a b c de fg hijklmn
If you want newlines, add out << endl; at the appropriate point.