After while loop exits, contents of the string are being deleted? - c++

Hey everyone this is my first post so if I make any mistakes, such as not enough info etc, please let me know so I do not make them again.
So my issue is I need to take the contents of a file and then input them into a string, which I have working. However after the while loop ends if I try to use that string outside the while loop and manipulate the contents the string. The string is blank and there seems to be no contents. I determined this by using std::cout lines. I believe this to be a scope issue but I am not sure how to fix it. Below is the code pertaining to the question, any tips or help would be greatly appreciated!
std::string str;
std::ifstream file;
while(!file.eof()){
getline(file, str);
std::cout << str << "";
}
file.close();
std::cout << str << "";
std::map<std::string, int> map;
for(int i = 0; i < str.length(); ++i){
std::string sub = str.substr(i, k);
std::cout << sub << std::endl;
map.insert(make_pair(sub, 1));
}
std::cout << "" << std::endl;
Also, I am trying to chop the string up into size k which is a variable defined in a different part of the code, so I used the substr method in C++, and I believe this is working because when I put it in the while loop I can print out the contents of the file but the format is off and I think that is because of the nature of how the while loop runs, but I am not sure, please correct me if I am wrong or have any misconceptions.

Wouldn't it be easier to store the text file into a std::vector and then choose what sentence you'd want to manipulate?
Example:
int main()
{
std::string str;
std::ifstream file{ "file.txt" };
std::vector<std::string> vec;
// Store text file in vector
while (std::getline(file, str)) {
vec.emplace_back(str);
}
// Print out line 2:
std::cout << vec.at(1) << '\n';
// Reverse line 2 and print:
std::string line2 { vec.at(1) };
std::reverse(begin(line2), end(line2));
std::cout << line2 << '\n';
}

You are only storing one line at a time with getline(file, str);. My guess is that the last line of your file is blank, so the last value stored to str is blank.
You can concatenate instead of overwriting:
std::string temp;
std::string str;
std::ifstream file;
while(!file.eof()){
getline(file, temp);
std::cout << str << "";
str = str + temp;
}
Alternatively, add #include <fstream> and use:
std::ifstream inputStream("myfile.txt");
std::string str((std::istreambuf_iterator<char>(inputStream),
(std::istreambuf_iterator<char>()));

Related

Read every line from text file to a vector C++

I have a text file where I need to be able to add or delete certain lines using functions. Everything is read from the file so when I open the file and write something then it deletes everything else in that file. I've understood that this can be done by using vectors. As I am new to C++ and especially vectors, I haven't figured out how I can read every line to a vector and then rewrite the lines to the text file.
Maybe someone can recommend me some kind of web-page or sth where I could learn how to do it.
Function for adding a line so far but it does not add the new line.
It should read the existing lines in the text file to vector<string> lines and then output it to the file while ignoring the first line with lines[i+1] and then add the new contact info to the end outside of the for loop.
void add contact(string filename, string*& names, string*& emails,
string*& numbers, unsigned int& quantity, string name, string email,
string number){
string str;
vector<string> lines;
ifstream input(filename);
while(getline(input, str)){
lines.push_back(str);
}
input.close();
ofstream output("contacts.txt");
output << quantity;
for(unsigned int i = 0; i < quantity; i++){
output << endl << lines[i+1];
}
output << endl << name << " | " << email << " | " << number << endl;
}
It's not that tough. You just have to get each line and push it to the std::vector.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
int main()
{
std::string str ;
std::vector<std::string> file_contents ;
std::fstream file;
file.open("test.txt",std::ios::in);
while(getline(file, str))
{
file_contents.push_back(str) ;
}
// You can access it using vector[i]
}

getLine() returns newline and no data

I have the following code:
const char *fn = fileName.c_str();
std::ifstream file (fn);
std::vector<std::string> value(20000);
int i = 0;
while ( file.good() )
{
getline ( file, value[i] );
i+=1;
std::cout << value[i]<< std::endl;
std::cout << i << std::endl;
}
The program reads the whole file, I know this because the correct number of indexes are printed. However there is no data, just a new line before each printing of "i". This is a file that I have saved from excel in windows and am reading in Linux - Is this my issue? What happened to my data?
there is no data, just a new line before each printing of "i".
Because you increment i before accessing value[i].
Incrementing i just after accessing value[i] solves the problem of missing data.
DEMO
A better way to read in the file:
std::string text_line;
std::vector<string> file_lines;
while (std::getline(file, text_line))
{
file_lines.push_back(text_line);
}
Although not optimal speed-wise, it gets the job done and doesn't have an upper limit (except by the amount of memory your program is allowed).
Edit:
Sorry, I was simply fixing the logic error apparent.
However, here is an ideal version of reading lines of a file:
#include <iostream>
#include <fstream>
#include <vector>
int main() {
std::ifstream file {"test.txt"};
std::vector<std::string> values;
std::string temp;
while (getline(file, temp)) {
values.push_back(temp);
}
for (int i = 0; i < values.size(); ++i) {
std::cout << values[i] << '\n' << i << '\n';
}
}

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);
}

Whats the best way to get text from a .txt file to a vector<string>? C++

I asked a question yesterday but i didn't manage to do anything. I am using visual studio with marmalade and im already studying c++ but i need to get things done here so i asking for i little help and patience of you guys.
I got a few responses like
std::ifstream inp("restrict_words.txt");
std::istream_iterator<std::string> inp_it(inp), inp_eof;
std::vector<std::string> words(inp_it, inp_eof);
// words now has ever whitespace separated string
// from the input file as a vector entry
for (auto s : words)
std::cout << s << '\n';
and
std::ifstream ist("restrict_words.txt");
std::string word;
std::vector<std::string> readWords;
while(ist >> word)
readWords.push_back(word);
//test
for(unsigned i = 0; i != readWords.size(); ++i)
std::cout << readWords.at(i) << '\n';
Its such a easy thing and im not managing to do this.
I have my KingChatFilter.app and a chat folder inside my game folder. Inside this chat folder i have this txt with 160 words in 160 different lines.
All i need to do is read this txt and after putting it on a array checking if some of this string match with the one i want so i can do other stuff.
Please someone make me understand this thanks :)
I wrote a couple of functions to match your requirements:
#include <iostream>
#include <vector>
#include <algorithm>
#include <fstream>
using namespace std;
// Reads the file line by line and put all lines into words vector.
void read_to_vector(const char* file_name, vector<string> &words)
{
ifstream input(file_name);
string line;
while (getline(input, line))
{
words.push_back(line);
}
}
// Returns true if word is in words. False otherwise.
bool find_word(vector<string> &words, string word)
{
vector<string>::iterator it; // In c++11 you can change this to
// auto it;
// Using std::find from algorithm library.
it = find(words.begin(), words.end(), word);
return it != words.end(); // If the end of vector words was reached, then word was NOT found.
}
int main()
{
vector<string> words;
string target = "level";
read_to_vector("data.txt", words);
if (find_word(words, target))
cout << "Word " << target << " found" << endl;
else
cout << "Word " << target << " not found" << endl;
return 0;
}
following is working code i used to read file content line by line. One difference is maybe that u do not check if opening the file did succeed. If it does not, there come at least two main reasons to mind:
the file cannot be found at the specified path
the file is already opened by someone else
;
std::string fileNameWithPath = "..\\myFolder\\myfile.txt";
std::ifstream inputFile;
std::vector< std::string > fileContent;
inputFile.open( fileNameWithPath.c_str(), std::ios::in | std::ios::binary );
if( inputFile.is_open() )
{
std::string line;
while( std::getline( testDataFile, line ) )
{
inputFile.push_back( line );
}
}
inputFile.close();

Reading a file into an array

I would like to read a text file and input its contents into an array. Then I would like to show the contents of the array in the command line.
My idea is to open the file using:
inFile.open("pigData.txt")
And then to get the contents of the file using:
inFile >> myarray [size]
And then show the contents using a for loop.
My problem is that the file I am trying to read contain words and I don't know how to get a whole word as an element in the array. Also, let's say that the words are divided by spaces, thus:
hello goodbye
Could be found on the file. I would like to read the whole line "hello goodbye" into an element of a parallel array. How can I do that?
Should be pretty straightforward.
std::vector<std::string> file_contents;
std::string line;
while ( std::getline(inFile,line) )
file_contents.push_back(line);
std::vector<std::string>::iterator it = file_contents.begin();
for(; it!=file_contents.end() ; ++it)
std::cout << *it << "\n";
Edit:
Your comment about having "hello goodbye" as element zero and element one is slightly confusing to me. The above code snip will read each line of the file and store that as an individual entry in the array 'file_contents'. If you want to read it and split it on spaces that is slightly different.
For context, you could have provided a link to your previous question, about storing two lists of words in different languages. There I provided an example of reading the contents of a text file into an array:
const int MaxWords = 100;
std::string piglatin[MaxWords];
int numWords = 0;
std::ifstream input("piglatin.txt");
std::string line;
while (std::getline(input, line) && numWords < MaxWords) {
piglatin[numWords] = line;
++numWords;
}
if (numWords == MaxWords) {
std::cerr << "Too many words" << std::endl;
}
You can't have one parallel array. For something to be parallel, there must be at least two. For parallel arrays of words, you could use a declarations like this:
std::string piglatin[MaxWords];
std::string english[MaxWords];
Then you have two options for filling the arrays from the file:
Read an entire line, and the split the line into two words based on where the first space is:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
piglatin[numWords] = line.substr(0, space);
english[numWords] = line.substr(space + 1);
++numWords;
}
Read one word at a time, and assume that each line has exactly two words on it. The >> operator will read a word at a time automatically. (If each line doesn't have exactly two words, then you'll have problems. Try it out to see how things go wrong. Really. Getting experience with a bug when you know what the cause is will help you in the future when you don't know what the cause is.)
while (input && numWords < MaxWords) {
input >> piglatin[numWords];
input >> english[numWords];
++numWords;
}
Now, if you really one one array with two elements, then you need to define another data structure because an array can only have one "thing" in each element. Define something that can hold two strings at once:
struct word_pair {
std::string piglatin;
std::string english;
};
Then you'll have just one array:
word_pair words[MaxWords];
You can fill it like this:
while (std::getline(input, line) && numWords < MaxWords) {
std::string::size_type space = line.find(' ');
if (space == std::string::npos)
std::cerr << "Only one word" << std::endl;
words[numWords].piglatin = line.substr(0, space);
words[numWords].english = line.substr(space + 1);
++numWords;
}
Notice how the code indexes into the words array to find the next word_pair object, and then it uses the . operator to get to the piglatin or english field as necessary.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main()
{
// This will store each word (separated by a space)
vector<string> words;
// Temporary variable
string buff;
// Reads the data
fstream inFile("words.txt");
while(!inFile.eof())
{
inFile>>buff;
words.push_back(buff);
}
inFile.close();
// Display
for(size_t i=0;i<words.size();++i) cout<<words[i]<<" ";
return 0;
}
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using namespace std;
int main ()
{
vector<string> fileLines;
string line;
ifstream inFile("pigData.txt");
if ( inFile.is_open() ) {
while ( !inFile.eof() ) {
getline(inFile, line);
fileLines.push_back(line);
}
inFile.close();
} else {
cerr << "Error opening file" << endl;
exit(1);
}
for (int i=0; i<fileLines.size(); ++i) {
cout << fileLines[i] << "\n";
}
cout << endl;
return 0;
}