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);
}
Related
I am currently trying to learn C++. I am given a .txt file that contains a different individuals data on each line. I want to read that data into an array of strings. I don't see anything wrong with this function and I have done the same thing before, but for some reason I am receiving a segmentation fault.
#include <string>
#include <iostream>
#include <fstream>
void readFile(std::istream&, std::string*);
int lineCount(std::istream&);
int main(){
std::ifstream inFile("input.txt");
int numLines = lineCount(inFile);
std::string data[numLines];
inFile.close();
inFile.open("input.txt");
readFile(inFile, data);
inFile.close();
return 0;
}
int lineCount(std::istream& inFile){
std::string line;
int numLines = 0;
while(std::getline(inFile, line)){
numLines++;
}
return numLines;
}
void readFile(std::istream& inFile, std::string *data){
int i = 0;
while(std::getline(inFile, data[i])){
std::cout << i << "\n"; //testing values
std::cout << data[i] << "\n"; //testing values
i++;
}
}
Here is the output of the above code.
//Output
//Note, these are fictional people
0
Florence,Forrest,1843 Glenview Drive,,Corpus Christi,TX,78401,10/12/1992,5/14/2012,3.215,127/11/1234,2.5,50
1
Casey,Roberta,3668 Thunder Road,,Palo Alto,CA,94306,2/13/1983,5/14/2014,2.978,95
2
Koch,Sandra,2707 Waterview Lane,Apt 302,Las Vegas,NM,87701,6/6/1972,12/14/2015,2.546,69
Segmentation fault //occurs in while condition
Any help would be appreciated
I feel sick that I didn't see this right away.
int numLines = lineCount(inFile);
returns the correct number of lines in the file. Bug's not here, man.
std::string data[numLines];
Is not kosher C++, but will create an array with an element for every line in the file if supported. Your program is running, so it's supported. Still, prefer to use Library Containers.
Meanwhile in readFile...
while(std::getline(inFile, data[i]))
Will try to read a line into data[i]. Whether the read succeeds or not, there must be a data[i] to read into. There won't be for the last try.
The logic goes
read in line 1. Successful, so
read in line 2. Successful, so
read in line 3. Successful, so
read in line 4. Fail. But this does not keep getline from looking off the end of data for a string and going boom (specifically undefined behaviour that manifested as going boom) because there isn't one.
The right solution
int main(){
std::ifstream inFile("input.txt");
// no longer need. Vector keeps track for us
// int numLines = lineCount(inFile);
std::vector<std::string> data;
// read nothing from file. Don't need to rewind
readFile(inFile, data);
// note: files close themselves when they are destroyed.
//inFile.close();
return 0;
}
void readFile(std::istream& inFile, std::vector<std::string> & data){
int i = 0;
std::string line; // line to read into. Always there, so we don't have to worry.
while(std::getline(inFile, line)){
std::cout << i << "\n"; //testing values
std::cout << line << "\n"; //testing values
data.push_back(line); // stuff line into vector.
i++;
}
}
The No vector Allowed Solution
int main(){
std::ifstream inFile("input.txt");
int numLines = lineCount(inFile);
// legal in every C++, but prefer container may want some extra armour
// here to protect from numlines 0.
std::string * data = new std::string[numlines];
// the following is a faster way to rewind a file than closing and re-opening
inFile.clear(); // clear the EOF flag
inFile.seekg(0, ios::beg); // rewind file.
readFile(inFile, data);
inFile.close();
return 0;
}
void readFile(std::istream& inFile, std::string * data){
int i = 0;
std::string line; // same as above. line is here even if data[i] isn't
while(std::getline(inFile, line)){
std::cout << i << "\n"; //testing values
std::cout << line << "\n"; //testing values
data[i] = line; // stuff line into array. Smart compiler may realize it can move
//if not, c++11 adds a formal std::move to force it.
i++;
}
}
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>()));
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.
I have created a file hangman_word_collection.txt and stored all the content of file into the string line.
Now I want to use the line string in my program but line[0] is not having any value into it or I don't know if it have something in it.
I am new to this please help.
Here is the code:
#include <iostream>
#include <fstream>
using namespace std;
int main() {
string line;
ifstream myfile ("hangman_word_collection.txt");
if (myfile.is_open()) {
while (myfile.good()) {
getline (myfile,line);
cout << line << endl;
}
}
for(int i=0; i <= 79; i++) {
cout << "\n" << i;
cout << ":" << line[i];
}
return 0;
}
And the output:
actingraringbackupcampusdacoiteasilyfabricgardenhackediceboxprimeralwaysupload.
0:
1:c
2:t
3:i
4:n
5:g
6:r
7:a
8:r
9:i
10:n
11:g
12:b
13:a
14:c
15:k
Press <RETURN> to close this window...
When getline fails on writing to your target line you are assuming it will not modify what is in that string but it is blanking the string, which internally is replacing character 0 with a null character.
The rest is undefined behaviour as you are reading characters off the end of the logical string.
To fix this issue change your code to;
string line;
ifstream myfile ("hangman_word_collection.txt");
if (myfile.is_open())
{
while (myfile.good())
{
std::string temp;
if( getline( myfile, temp ) )
{
temp.swap( line );
cout <<line<<endl;
}
}
}
Note that it is bad practice to hard-code in magic numbers like 79. If you had put line.size() instead you would have seen what size the string actually is, and there would be no undefined behaviour. You can store this in a variable outside the loop if you are worried about performance, although chances are it makes little difference.
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;
}