I have a program that reads input from the terminal and the stream from cin is used in multiple classes for parsing at various levels.
Instead of using cin for getting the data from the terminal, I want to read in a file that has the information I need to parse, but I don't want to modify all my header and .cpp files to accept an ifstream& parameter.
To keep the existing code in place I'm trying to simply redirect the ifstream to cin, but don't know how.
So assume I have the following in main:
ifstream inFile("myfile.txt", ifstream::io);
string line;
while(getline(inFile, line))
{
char firstChar;
inFile >> firstChar;
cout << firstChar;
inFile.ios::rdbuf(cin.rdbuf());
Continue myFile;
}
In my continue.cpp I'm just doing:
Continue()
{
string line;
cin >> line;
cout << "---remaining line: " << line << "\n";
}
However it's only printing the first char from main.
Simply swap pointers to std::streambuf:
ifstream file("myfile.txt");
string line;
if (file.is_open()) {
cin.rdbuf(file.rdbuf()); // swap
cin >> line;
}
std::cout << line;
istream objects read from a std::streambuf, and that can be swapped in an out. The relevant member function is .rdbuf
You can also redirect the underlying C stdin file handle to a different file, this will also affect your cin:
freopen ("myfile.txt", "r", stdin);
Here's a very quick and easy way to do it.
If your file is called "file.txt", the code would be:
fstream cin("file.txt");
This way, everything that's from the file would be redirected to cin >>
Related
I wrote a code in C++ that writes a .txt file.
Then I want to open the code again and give some information, so I can get a new text depending on what I gave as an input.
For example I want to give the name of a month, and print in another .txt file all the lines that came after the word "November".
I found some solutions, but none of them worked for me!
One solution that I found on stack overflow is the following:
void Keyword(ifstream & stream, string token) {
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
}
I can't print the next lines with the code above.
Any suggestion would be helpful!
Thanks!
If you want to perform operations on files such as 'Read' and/or 'Write',you might want to search on the net(or if you have a C++ book) on topics such as "File I/O operations using C++". Anyways moving on, C++ has 2 basic classes to handle files which are ifstream and ofstream. And to use them you have to include ethier the header fstream(i.e #include<fstream>) or include them separately as #include<ifstream> and #include<ofstream>. ifstream is basically used for all input operations such as reading files etc. Similarly ofstream is used for all output operations such as writing data to files.
You can open a file and write data to it by doing the following,
ofstream myFile("filename");// Create an instance of ofstream and open file for writing data
and to write data to the file use the << operator like below,
myFile<<data;
Similarly, You can open a file and read data as follows,
ifstream myFile("filename");//Create an instance of ifstream and open file to read data
and to read data from the file use the >> operator as shown below,
myFile>>data;
You can also open a file using the method void open(const char *filename, ios::openmode mode); as shown below,
//Writing only
ofstream outFile;
outFile.open("filename.txt",ios::out);
//Reading only
ifstream inFile;
inFile.open("filename.txt",ios::in);
//For reading and writing
fstream file;
file.open("filename.txt",ios::in|ios::out);
//For closing File
outFile.close();
//or
inFile.close();
//or
file.close();
Note the open() method takes various flags such as ios::in for reading mode, ios::out for writing mode, ios::app for adding data to the end etc.
All of these can also combined by using the bit OR operator | as shown below,
outFile.open("filename.txt",ios::out|ios::app);
There is a lot more in IO. I just covered the things required to start.
Here is the solution to your problem. Try to understand it.
#include<iostream>
#include<fstream>
#include<cstring>
using namespace std;
int main()
{
ofstream outFile;
ifstream inFile;
char fileName[10],data[50];
int noLines;
cout<<"Enter Month:"<<endl;
cin>>fileName;
cout<<"Enter Number of lines you want to enter:"<<endl;
cin>>noLines;
outFile.open(fileName,ios::out);
cout<<fileName<<"(Enter Data):";
for(int i=0;i<=noLines;i++)
{
cin.getline(data,50);
outFile<<data<<endl;
}
outFile.close();
cout<<"Openening "<<fileName<<" :"<<endl;
inFile.open(fileName,ios::in);
for(int i=0 ;i<=noLines ;i++)
{
inFile.getline(data,50);
cout<<data<<endl;
}
inFile.close();
return 0;
}
OP has found most of the solution already:
string line;
while (getline(stream, line)) {
if (line.find(token) != string::npos) {
cout << line << endl;
}
}
cout << token << " not found" << endl;
But this only prints the lines with the keyword. And always prints the "not found" message. Ooops.
Instead I pitch:
string line;
bool found = false;
while (!found && getline(stream, line))
{ // search for keyword
if (line.find(token) != string::npos)
{
found = true; // found keyword. Stop looking
}
}
if (found)
{ // print out all remaining lines in the file
while (getline(stream, line))
{
cout << line << endl;
}
}
else
{
cout << token << " not found" << endl;
}
The above splits the finding of the token and the printing of the remaining file into two stages for readability. It can be compressed into one loop, but two things make this a sucker bet:
this program will be IO bound. It will spend the vast majority of its time reading the file, so little tweaks that do not address getting the file into memory are wasted time.
combining the loops would require the addition of logic to the loop that would, over along run, dwarf the minuscule cost of switching loops.
Try this:
http://www.cplusplus.com/doc/tutorial/files/
and this:
http://www.cplusplus.com/forum/beginner/14975/
It's about reading and writing files in c++ and about searching in files.
I am working on a program that reads from a file and pushes back the contents of that file into a vector. It will read until the file reaches a space and push that string into a vector, then continue after the space. I have written this code.
ifstream inFile;
inFile.open("message1.txt");
if (inFile.fail()) {
cerr << "Could not find file" << endl;
}
while (inFile >> S) {
code1.push_back(S);
}
I am just confused about the while (inFile >> S) actually does. I understand that it reads from the inFile until it reaches the end of file. But what does the inFile >> S condition actually do? Thanks for your time.
What the inFile >> S does is take in the file stream, which is the data in you file, and uses a space delimiter (breaks it up by whitespace) and puts the contents in the variable S.
For example:
If we had a file that had the follow contents
the dog went running
and we used inFile >> S with our file:
ifstream inFile("doginfo.txt")
string words;
while(inFile >> words) {
cout << words << endl;
}
we will get the following output:
the
dog
went
running
The inFile >> S will continue to return true until there are no more items separated by whitespace.
The expression inFile >> S reads a value into S and will return inFile.
This allows you to chain variables together like infile >> a >> b >> c;
Since this inFile is being used in a bool context, it will be converted to bool. And iostream objects are defined to convert to a bool that's true if and only if the object has no current error state.
I'm trying to write a simple program that will print the contents of a text file one line at a time. However, whenever I run the program i just get a blank screen. I'm certain the file I am trying to read contains text over several lines. Any help as to why this isn't working would be super helpfull.
bool show() {
string line;
ifstream myfile;
myfile.open("tasks.txt", ios::app);
while (!myfile.eof()) {
getline (myfile, line);
cout << line << endl;
}
myfile.close();
return true;
}
The problem might be that you are using ios::app with ifstream (input stream), which makes no sense.
According to this,
ios::app: All output operations are performed at the end of the file, appending the content to the current content of the file. This flag can only be used in streams open for output-only operations.
Try this:
std::string line;
ifstream myfile ("tasks.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
std::cout << line << std::endl;
}
myfile.close();
}
Did you check return value of myfile.isopen()? Perhaps the file isn't there or you don't have read permission.
Oh yes, I missed that - the append flag. Should be ios::in
Check this program
ifstream filein("Hey.txt");
filein.getline(line,99);
cout<<line<<endl;
filein.getline(line,99);
cout<<line<<endl;
filein.close();
The file Hey.txt has alot of characters in it. Well over a 1000
But my question is
Why in the second time i try to print line. It doesnt get print?
The idiomatic way to read lines from a stream is this:
std::ifstream filein("Hey.txt");
for (std::string line; std::getline(filein, line); )
{
std::cout << line << std::endl;
}
Notes:
No close(). C++ takes care of resource management for you when used idiomatically.
Use the free std::getline, not the stream member function.
According to the C++ reference (here) getline sets the ios::fail when count-1 characters have been extracted. You would have to call filein.clear(); in between the getline() calls.
#include<iostream>
using namespace std;
int main()
{
ifstream in;
string lastLine1;
string lastLine2;
in.open("input.txt");
while(in.good()){
getline(in,lastLine1);
getline(in,lastLine2);
}
in.close();
if(lastLine2=="")
cout<<lastLine1<<endl;
else
cout<<lastLine2<<endl;
return 0;
}
As Kerrek SB said correctly There is 2 possibilities:
1) Second line is an empty line
2) there is no second line and all more than 1000 character is in one line, so second getline has nothing to get.
An easier way to get a line is to use the extractor operator of ifstream
string result;
//line counter
int line=1;
ifstream filein("Hey.txt");
while(filein >> result)
{
//display the line number and the result string of reading the line
cout << line << result << endl;
++line;
}
One problem here though is that it won't work when the line have a space ' ' because it is considered a field delimiter in ifstream. If you want to implement this kind of solution change your field delimiter to e.g. - / or any other field delimiter you like.
If you know how many spaces there is you can eat all the spaces by using other variables in the extractor operator of ifstream. Consider the file has contents of first name last name.
//file content is: FirstName LastName
int line=1;
ifstream filein("Hey.txt");
string firstName;
string lastName;
while(filein>>firstName>>lastName)
{
cout << line << firstName << lastName << endl;
}
While reading a file (ifstream), is there any way to direct it to make a new line?
For instance, I would like for THIS to happen:
myfile>>array[1]>>array[2]>>endl;
Obviously, the "endl" just isn't allowed. Is there another way to do this?
Edit---thanks for the quick responses guys!
From a text file, I'm trying to store two strings from that file into arrays and then do the same with the next line (or until I desire, using a for loop)
Using strings is important to me as it will make my future program a lot more flexible.
Several options:
You can use ignore.
myfile >> array[1] >> array[2];
myfile.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Or you can read each line into as string stream
std::string line;
std::getline(myfile,line);
std::stringstream stream(line);
stream >> array[1] >> array[2];
Please note: Array indexing starts at 0.
Use std::getline to read a line into a memory stream, then get the two strings from that.
while (cin)
{
string line;
getline(cin, line);
stringstream stream;
stream << line;
stream >> array[1]>>array[2];
}
Read your two items, then call myfile.ignore(8192, '\n')
I have no idea what this question means. Here's a simple way to read all the lines of a file into a vector of strings. It might be easier to do what you want to do if you do this first.
std::vector<std::string> lines;
std::string line;
while (std::getline(myFile, line))
lines.push_back(line);
Now you can say lines[4] to get the fifth line, or lines.size() to find out how many lines there were.
This should work:
stringstream stream;
string sLine;
int iLine;
while (cin)
{
getline(cin, sLine);
stream << sLine;
stream >> data[iLine][0] >> data[iLine][1];
}
Customized version of an earlier answer.