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.
Related
I need help, I wrote the code, did the reverse thing but I can't get it written on another file.
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ifstream par2("C:/fajllat/f1.bin", ios::in);
string line;
for (int i = 1; !par2.eof() ; i++)
{
getline(par2, line);
if (i < 5 || i >14) continue;
line = string(line.rbegin(), line.rend());
}
par2.close();
ofstream mbrapsht ("C:/fajllat/f3.bin", ios::out);
mbrapsht << line;
mbrapsht.close();
cin.get();cin.get();
return 0;
}
When I check the files the f3.bin file is empty
You have the right idea. What you're missing is that if you want to write the reversed lines, you need to either write them inside the loop or store them for after. You are doing neither of these things.
Currently what happens is you overwrite line every loop. And whatever is left in that string is what you write afterwards. Turns out that for your case, that's an empty string.
Let's make minimal changes to what you have:
// (*) Open the output file before looping
ofstream mbrapsht("C:/fajllat/f3.bin", ios::out);
for (int i = 1; !par2.eof() ; i++)
{
getline(par2, line);
if (i < 5 || i > 14) continue;
line = string(line.rbegin(), line.rend());
// (*) output the line - you also probably want an end-of-line
mbrapsht << line << std::endl;
}
Now, it's okay-ish. But it does have a problem where if getline fails, your code still runs the loop body one more time. This happens if getline hits the end of file (or some other error state), which your loop doesn't pick up until the next iteration (or possibly never, if the error is not EOF).
So, a somewhat better choice might be:
for(int lineNo = 1; std::getline(par2, line); ++lineNo)
{
if (lineNo >= 5 && lineNo <= 14)
{
std::reverse(line.begin(), line.end()); // (*) requires <algorithm>
mbrapsht << line << std::endl;
}
}
Note that I also inverted your test condition and removed the continue. In general, I avoid continue and break in loops unless not using them results in code that is hard to follow or understand at a glance. It's a style/maintainability thing. Take it or leave it.
See this snippet . For line-by-line reversal, you can use getline() instead and reverse before pushing into vector<string>.
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>
#include <algorithm>
using namespace std;
int main()
{
string str;
ifstream par2("D:\\MyFolder\\try.txt", ios::in);
if (par2.is_open())
{
stringstream strStream;
strStream << par2.rdbuf();
str = strStream.str();
cout << str << endl;
par2.close();
}
cout << "\n\nReversing ...\n\n";
std::reverse(str.begin(), str.end());
cout << str << endl;
ofstream mbrapsht("D:\\MyFolder\\try2.txt", ios::out);
mbrapsht << str;
mbrapsht.close();
return 0;
}
Output:
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);
}
Sometimes I see on the internet programs that read from a file like this:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main () {
string line;
ifstream myfile ("example.txt");
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
cout << line << '\n';
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
I want to know if while ( getline (myfile,line) ) means "as long as the text file has lines that haven't been read keep reading them" and if "while" can accept other conditions that I don't know about.
Also I want to know if there is a method to read a text file character by character not line by line.
In C++ you can read a file char by char as given example
char oneChar;
fstream fin("file", fstream::in);
while (fin >> noskipws >> oneChar)
{
cout << oneChar;
// or do desired operation with oneChar
}
You are correct about the while, it will keep reading until it finds EOF, or End-Of-File. While can accept anything that returns true or false, so any function that returns bool (or even numbers, etc) will work.
I'm pretty sure that this is a common question, but I can't find an example similar to mine, so..
I have a text file called input.txt that has: 0.0001234 1.0005434 0.0005678 1.0023423 0.00063452 1.0001546 0.00074321 1.00017654 in it.
Now I want to write a program to read that into an array, and then quickly check that it worked. So far, I've got:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main ()
{
double PA[8];
int n;
ifstream myfile ("input.txt");
if (myfile.is_open())
{
while (! myfile.eof() )
{
getline (myfile,line);
cout << PA[line]<< endl;
}
myfile.close();
}
else cout << "Unable to open file";
for (n=0; n<8; n++) // to print the array, to check my work
{
cout << " {" << PA[n] << "} ";
}
system("PAUSE");
return 0;
}
My problem so far is that I keep getting the error: line was not declared. And I want to use the array later with floats to calculate new data. I think I'm doing it wrong for that.. Any help? Thanks!
declare line variable
int n, line = 0;
std::string value;
proper load data:
getline (myfile,value);
PA[line] = atof(value.c_str());
cout << PA[line]<< endl;
line++;
the variable line here
cout << PA[line]<< endl;
is not declared. and if you declare it, you also have to give it a value, otherwise it's undefined and the PA[line] is undefined, in other words: will crash.
the entire while block seems suspicious:
while (! myfile.eof() )
{
getline (myfile,line);
cout << PA[line]<< endl;
}
are you sure about the getline call?
I know a getline with this signature:
ssize_t getline(char **lineptr, size_t *n, FILE *stream);
and that does not even match the number of arguments in your version.
if your input file has more than 8 lines on input, than the while loop will have that many interations - and your array has only space for 8 elements.
You need to declare the variable you called 'line' as follows:
int i=0;
while (! myfile.eof() && i<8)
{
std::string line; // this was the missing statement
getline (myfile,line);
double value = atof(line.c_str()); // convert line form char* to double
PA[i++] = value;
cout << value << endl;
}
Note that you need to convert line as double and use increment variable 'i' (for example, as I did. Make sure not overflowing PA capacity by checking i agains the size (currently 8, which should not hard coded, btw).
Also note that you shouldn't print the result if file access failed.
I have the following .txt file:
test.txt
1,2,5,6
Passing into a small C++ program I made through command line as follows:
./test test.txt
Source is as follows:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char **argv)
{
int temp =0;
ifstream file;
file.open(argv[1]);
while(!file.eof())
{
temp=file.get();
file.ignore(1,',');
cout<<temp<<' ';
}
return 0;
}
For some reason my output is not 1 2 5 6 but 49 50 53 54. What gives?
UPDATE:
Also, I noticed there is another implementation of get(). If I define char temp then I can do file.get(temp) and that will also save me converting ASCII representation. However I like using while (file >> temp) so I will be going with that. Thanks.
temp is an int. So you see the encoded ascii values after casting the char to an int.
49 is the ascii code for digit 49-48 = 1.
get() gives you a character (character code).
by the way, eof() only becomes true after a failed read attempt, so the code you show,
while(!file.eof())
{
temp=file.get();
file.ignore(1,',');
cout<<temp<<' ';
}
will possibly display one extraneous character at the end.
the conventional loop is
while( file >> temp )
{
cout << temp << ' ';
}
where the expression file >> temp reads in one number and produces a reference to file, and where that file objected is converted to bool as if you had written
while( !(file >> temp).fail() )
This does not do what you think it does:
while(!file.eof())
This is covered in Why is iostream::eof inside a loop condition considered wrong?, so I won't cover it in this answer.
Try:
char c;
while (file >> c)
{
// [...]
}
...instead. Reading in a char rather than an int will also save you having to convert the ascii representation (ASCII value 49 is 1, etc...).
For the record, and despite this being the nth duplicate, here's how this code might look in idiomatic C++:
for (std::string line; std::getline(file, line); )
{
std::istringstream iss(line);
std::cout << "We read:";
for (std::string n; std::getline(iss, line, ','); )
{
std::cout << " " << n;
// now use e.g. std::stoi(n)
}
std::cout << "\n";
}
If you don't care about lines or just have one line, you can skip the outer loop.