C++ read from file into a vector - c++

I am working on a program that should read from a file and store the contents of that file in a vector. I must read the contents of the .txt file and push the strings back into a vector before it reaches a ' '. If it is a space you will skip that part of the file and continue pushing back the contents after the space. Does anybody know what function to use to read from a file and put the contents into a vector or array? Thanks for your time.
int main()
{
Code mess;
ifstream inFile;
inFile.open("message1.txt");
if (inFile.fail()) {
cerr << "Could not find file" << endl;
}
vector<string> code;
string S;
while (inFile.good()) {
code.push_back(S);
}
cout << mess.decode(code) << endl;
return 0;
}

Basically you can also do it like this :
std::ifstream fh("text.txt");
std::vector<std::string> vs;
std::string s;
while(fh>>s){
vs.push_back(s);
}
for(int i=0; i<vs.size(); i++){
std::cout<<vs[i]<<std::endl;
}

You should change your reading code to
while (inFile >> S) {
code.push_back(S);
}
Your current code doesn't read anything into your S variable.
Regarding loop conditions while (inFile.good()) see this Q&A please:
Why is iostream::eof inside a loop condition considered wrong?
Using std::iostream::good() has more or less the same issues.

Related

Encode a string of characters given a custom code table

I want to programmatically convert a string of characters stored in a file to a string of character codes (encode) by following a code table. The string of binary codes should then go to a file, from which I can revert it back to the string of characters later (decode). The codes in the code table were generated using Huffman algorithm and the code table is stored in a file.
For example, by following a code table where characters and its corresponding codes are single spaced like this:
E 110
H 001
L 11
O 111
encoding "HELLO" should output as "0011101111111"
My C++ code cannot seem to complete the encoded string. Here is my code:
int main
{
string English;
ifstream infile("English.txt");
if (!infile.is_open())
{
cout << "Cannot open file.\n";
exit(1);
}
while (!infile.eof())
{
getline (infile,English);
}
infile.close();
cout<<endl;
cout<<"This is the text in the file:"<<endl<<endl;
cout<<English<<endl<<endl;
ofstream codefile("codefile.txt");
ofstream outfile ("compressed.txt");
ifstream codefile_input("codefile.txt");
char ch;
string st;
for (int i=0; i<English.length();)
{
while(!codefile_input.eof())
{
codefile_input >> ch >> st;
if (English[i] == ch)
{
outfile<<st;
cout<<st;
i++;
}
}
}
return 0;
}
For an input string of "The_Quick_brown_fox_jumps_over_the_lazy_dog", the output string is 011100110, but it should be longer than that!
output image
Please help! Is there anything I have missed?
(n.b. my C++ code has no syntax errors)
Let's take a look at the main loop, you are doing your work in:
for (int i=0; i<English.length();)
{
while(!codefile_input.eof())
{
codefile_input >> ch >> st;
if (English[i] == ch)
{
outfile<<st;
cout<<st;
i++;
}
}
}
Your code, will read through the codefile_input once, and then will get stuck in codefile_input.eof () == true condition, and then, for (int i=0; i<English.length();) will become an infinite loop, due to the fact, that there won't be a code path, in which i is increased, and it will never reach the value equal to English.length ().
As a side note, take a read on Why is iostream::eof inside a loop condition considered wrong?.
To avoid the issue, explained above, consider reading the dictionary file, to a data container (e.g. std::map), and then, use that, while iterating through the string, that you want to encode.
For example:
std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
{
codes[ch] = str;
}
codefile_input.close ();
for (int i=0; i<English.length(); ++i)
{
auto it = codes.find (English[i]);
if (codes.end () != it)
{
outfile << codes->second;
cout << codes->second;
}
}
Note, you will need to #include <map> to use std::map.
In addition to solving the issue, about which, your question, was actually, about, your loop:
while (!infile.eof())
{
getline (infile,English);
}
only reads the last line of the file, while discarding all other lines, that came prior to it. If you want to process all the lines in a file, consider changing that loop to:
while (std::getline (infile, English))
{
/* Line processing goes here */
}
And, since, your dictionary is unlikely to be different for different lines, you can move that logic, to the front of this loop:
std::ifstream codefile_input("codefile.txt");
char ch;
std::string str;
std::map<char, std::string> codes;
while (codefile_input >> ch >> str)
{
codes[ch] = str;
}
codefile_input.close ();
ifstream infile("English.txt");
if (!infile.is_open())
{
cout << "Cannot open file.\n";
exit(1);
}
ofstream outfile ("compressed.txt");
string English;
while (std::getline (infile, English))
{
for (int i=0; i<English.length(); ++i)
{
auto it = codes.find (English[i]);
if (codes.end () != it)
{
outfile << codes->second;
cout << codes->second;
}
}
}
In addition, consider adding error checking for all of the files that you open. You check if you can open file English.txt, and exit if you can't, but you don't check if you could open any other file.
On unrelated note #2, considering reading Why is “using namespace std” considered bad practice? (that's why you see me using std:: explicitly in the code, that I added).

Why won't my cout statements print after opening a textfile?

I am trying to write a program where I read a text file and then take each line in the textfile and store them in a string vector. I think I am able to open the textfile however I noticed that after I open the textfile anything after that point does not execute. For example I have a cout statement at the end of my main function that outputs when I enter the name of a file that doesn't exist. However if I type in a file name does exists I get no output from the last cout statement. Anyone know why this is? Thanks!
int main()
{
vector<string>line;
string fileName = "test.txt";
ifstream myFile(fileName.c_str());
int i = 0;
int count = 0;
vector<string>lines;
cout << "test" << endl;
if (myFile.is_open())
{
cout << "test2" << endl;
while (!myFile.eof())
{
getline(myFile, lines[i],'\n');
i++;
}
myFile.close();
}
if (!myFile.is_open())
{
cout<< "File not open"<< endl;
}
myFile.close();
cout << "Test3" <<endl;
return 0;
}
Try this:
string fileName = "test.txt";
ifstream myFile(fileName); // .c_str() not needed - ifstream can take an actual string
vector<string> lines;
string line; // temporary variable for std::getline
while (getline(myFile, line)) {
lines.push_back(line); // use push_back to add new elements to the vector
}
As pointed out in the comments, the most likely reason that your program seems to "end" prematurely is that it's crashing. std::getline takes a reference-to-string as its second argument. In your code, your vector is empty; therefore lines[i] for any i returns a reference to invalid memory. When getline tries to access that memory, the program crashes.
If you want an exception thrown when you try to access an out-of-bounds index of a vector, use lines.at(i) instead of lines[i].
You need to use push_back() because your initial vector is empty and, you can not use indexes on empty vector. If you do so, it will leads to undefined behavior.
std::ifstream input( "filename.ext" );
std::vector<std::string> lines;
for( std::string line; getline( input, line ); )
{
lines.push_back(line);
}

Reading File in C++ with Member Functions

int DataSource::insertData(char* fileName){
double vel, tireAngle, timeStamp;
string inputLine;
int i=0;
ifstream inFile;
inFile.open(fileName);
if (!inFile.good())
{
cout << "Could not open file " << fileName << endl;
return 0;
}
while(inFile.good())
{
getline(inFile, inputLine);
if(inFile.fail())
{
break;
}
istringstream lineStream(inputLine);
lineStream >> timeStamp >> vel >> tireAngle;
source.push_back(Input(vel, tireAngle, timeStamp));
++i;
}
inFile.close();
return i;
};
I'm trying to pass in the file name, open the file and parse through each line. The Input class holds the three double values, and source is a vector of type Input. I have vector, iostream,fstream,string,sstream,climits #included, along with std namespace.
So my first issue is the file not opening, I know that the right filename is being passed in. The error I'm getting is:
"Could not open file input1.txt
libc++abi.dylib: terminating with uncaught exception of type std::out_of_range: vector"
For the vector, I googled the error and I think I'm accessing a bad vector, which is either because maybe I haven't properly initialized the vector -Input- source (formatting wont let me put the "greater than, less than sign") or I'm using the wrong syntax.
This is my first post so I'm sorry if this is a bad question/formatting, but any help would be appreciated.
I don't think you should be using good() to check if the input is valid. Try changing
if (!inFile.good())
to
if (!inFile.is_open())
and changing
while(inFile.good())
{
getline(inFile, inputLine);
to
while(getline(inFile, inputLine))

find word in a text in C++ and print some next specific lines

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.

C++ file handling, is_open returning bad

If I include the if test in my code the error message is returned and I'm not sure why.
and when it's not used, my program get's stuck in a loop where it never reaches the end of the file. I don't understand what's going wrong.
int countlines()
{
fstream myfile;
myfile.open("questions.txt", ios::in);
string contents;
int linenumber = 0;
//if (myfile.is_open())
// {
while (!myfile.eof())
{
getline( myfile, contents );
if (contents != "")
{
linenumber++;
}
}
cout << "there are " << linenumber << " lines.\n";
//}else {cout<<"Unable to get file.\n";}
myfile.close();
return(linenumber);
}
What's going on is that your file is not being opened. That's why is_open fails.
Then, when you comment out the check, you're breaking your loop because you're iterating incorrectly (see my comment) and not detecting stream failures (.eof() will never be true on that stream).
Make sure that the file is in the right place, and that it is accessible.
The correct idiom for reading a file line-by-line in C++ is using a loop like this:
for (std::string line; std::getline(file,line);)
{
// process line.
}
Inserting this in your example (+fixing indentation and variable names) gives something like this:
int countlines(const std::string& path)
{
// Open the file.
std::ifstream file(path.c_str());
if (!file.is_open()) {
return -1; // or better, throw exception.
}
// Count the lines.
int count = 0;
for (std::string line; std::getline(file,line);)
{
if (!line.empty()) {
++count;
}
}
return count;
}
Note that if you don't intend to process the line contents, you can actually skip processing them using std::streambuf_iterator, which can make your code look like:
int countlines(const std::string& path)
{
// Open the file.
std::ifstream file(path.c_str());
if (!file.is_open()) {
return -1; // or better, throw exception.
}
// Refer to the beginning and end of the file with
// iterators that process the file character by character.
std::istreambuf_iterator<char> current(file);
const std::istreambuf_iterator<char> end;
// Count the number of newline characters.
return std::count(current, end, '\n');
}
The second version will completely bypass copying the file contents and avoid allocating large chunks of memory for long lines.
When using std::istream and std::ostream (whose std::fstream implements), the recommended usage is to directly use the stream in a bool context instead of calling eof() function because it only return true when you managed to read until the last byte of the file. If there was any error before that, the function will still return true.
So, you should have written your code as:
int countlines() {
ifstream myfile;
int linenumber = 0;
string linecontent;
myfile.open("question.txt", ios::in);
while (getline(myfile, linecontent)) {
if (!linecontent.empty()) {
++linenumber;
}
}
return linenumber;
}
Try the following code. It will also (hopefully) give you an idea why the file open is failing...
int countlines()
{
ifstream myfile;
myfile.open("questions.txt");
string contents;
int linenumber = 0;
if (myfile.is_open())
{
while (getline(myfile, contents))
{
if (contents != "")
linenumber++;
}
cout << "there are " << linenumber << " lines." << endl;
myfile.close();
}
else
cout << "Unable to get file (reason: " << strerror(errno) << ")." << endl;
return linenumber;
}