I'm new to C++ programming and trying to figure out a weird line read behavior when reading a line from a text file. For this specific program, I have to wait for the user to press enter before reading the next line.
If I hard code the file name, the file read starts at line 1 as expected:
#include <iostream>
#include <fstream>
using namespace std;
int main(void) {
ifstream in_file;
in_file.open("test.txt");
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
I compile with g++ -Wall -std=c++14 test1.cpp -o test1 and get:
$ ./test
This is line one.
**user presses enter**
This is line two.
**user presses enter**
This is line three.
etc. etc.
But when I add in the option to have the user type in a file name, the line read starts at line 2:
#include <iostream>
#include <fstream>
using namespace std;
int main(void) {
string filename;
cin >> filename;
ifstream in_file;
in_file.open(filename);
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
The same compile command gives me:
$ ./test2
test.txt
This is line two.
**user presses enter**
This is line three.
**user presses enter**
This is line four.
etc. etc.
Am I missing something here? I have no idea why it starts reading at line 2 when I add in the code to specify a file name. Am I not finishing the cin statement properly or something?
Thanks!
by default cin operator>> reads data up to the first whitespace characte and whitespace characte is not extracted reference. So if you read file name like this cin>>file; file variable will contains only first part of your string without whitespace. So that when reading you do not have such problems use getline
#include <iostream>
#include <fstream>
#include <sstream>
using namespace std;
int main(void) {
string filename;
getline(cin, filename, '\n');
ifstream in_file;
in_file.open(filename);
// read line by line
string line;
while (getline(in_file, line)) {
cout << line;
cin.get();
}
in_file.close();
return 0;
}
This implementation of the code should work. You just needed to add cin.ignore() to ignore the remaining characters on the line until you hit either the end of the line(EOL) or the end of the file(EOF). The function also takes in 2 parameters, which are the maximum number of characters to ignore and the character to ignore. link to the use of cin.ignore(). Hope that this helps :)
#include <iostream>//basic
#include <fstream>//file
using namespace std;
int main(){
//set file name
string file="";
cout<<"file name: ";
cin>>file;
//create/write to file
ofstream out_file;
out_file.open(file);
out_file<<"test 1\ntest 2\ntest 3";
out_file.close();
//read file
ifstream in_file;
in_file.open(file);
string line;
cin.ignore();//clear buffer
while(getline(in_file,line)){
cout<<line;
cin.get();
}
in_file.close();
system("pause");
return 0;
}
Related
How do I remove/replace the last line of a file in C++? I looked at these questions:
Deleting specific line from file, Read and remove first (or last) line from txt file without copying
. I thought about iterating to the end of the file and then replacing the last line but I'm not sure how to do that.
Find the position of the last occurrence of '\n' in the file content. If the file ends with '\n', i.e there is no more data after the last '\n', then find the position of the previous occurrence of '\n'. Use resize_file to truncate files at the found position or just replace the content after the found position.
#include <fstream>
#include <string>
using namespace std;
int main() {
ifstream fin("input.txt");
ofstream fout("output.txt");
while (!fin.eof()) {
string buffer;
getline(fin, buffer);
if (fin.eof()) {
fout << "text to replace last line";
} else {
fout << buffer << '\n';
}
}
fin.close();
fout.close();
}
Also you can read and store all your input file, modify and then write it:
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main() {
// read
ifstream fin("input.txt");
vector<string> lines;
while (!fin.eof()) {
string buffer;
getline(fin, buffer);
lines.push_back(buffer + '\n');
}
fin.close();
// modify
lines[lines.size() - 1] = "text to replace last line";
// write
ofstream fout("output.txt");
for (string line: lines) { // c++11 syntax
fout << line;
}
fout.close();
}
I want to be able to a string that contains certain characters in a file that contains one string per line.
#include <iostream>
#include <fstream>
#include <string>
int main(){
string line;
ifstream infile;
infile.open("words.txt");
while(getline(infile, line,' ')){
if(line.find('z')){
cout << line;
}
}
}
That's my attempt at finding all the string that contains the character z.
The text file contains random strings such as
fhwaofhz
cbnooeht
rhowhrj
perwqreh
dsladsap
zpuaszu
so with my implementation, it should only print out the strings with the character z in it. However, it seems to be reprinting out all the contents from the text file again.
Problem:
In your file the strings aren't separated by a space (' ') which is the end delimiter, they are separated by a end of line ('\n'), that is a different character. As a consequence, in the first getline everything goes to line. line contains all the text in the file, including z's, so all the content is printed. Finally, the code exits the while block after running once because getline reaches the end of the file and fails.
If you run this code
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile, line,' ')){
std::cout << "Hi";
if(line.find('z')){
std::cout << line;
}
}
}
"Hi" will be only printed once. That is because the while block is only executed once.
Additionaly, see that line.find('z') won't return 0 if not match is found, it will return npos. See it running this code (As it says here):
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile,line)){
std::cout << line.find('z');
if(line.find('z')){
std::cout << line << "\n";
}
}
}
Solution:
Use getline(infile,line) that is more suitable for this case and replace if(line.find('z')) with if(line.find('z') != line.npos).
while(getline(infile,line)){
if(line.find('z') != line.npos){
std::cout << line << "\n";
}
}
If you need to put more than one string per line you can use the operator >> of ifstream.
Additional information:
Note that the code you posted won't compile because string, cout and ifstream are in the namespace std. Probably it was a part of a longer file where you were using using namespace std;. If that is the case, consider that it is a bad practice (More info here).
Full code:
#include <iostream>
#include <fstream>
#include <string>
int main(){
std::string line;
std::ifstream infile;
infile.open("words.txt");
while(getline(infile,line)){
if(line.find('z') != line.npos){
std::cout << line << "\n";
}
}
}
getline extracts characters from the source and stores them into the variable line until the delimitation character is found. Your delimiter character is a space (" "), which isn't present in the file, so line will contain the whole file.
Try getline(infile, line, '\n') or simply getline(infile, line) instead.
The method find returns the index of the found character, where 0 is a perfectly valid index. If the character is not found, it returns npos. This is a special value whcih indicates "not found", and it's nonzero to allow 0 to refer to a valid index. So the correct check is:
if (line.find('z') != string::npos)
{
// found
}
I want get from user word and put into place in file where is certian word.
I have problem with getline.
In new file I don't have any new line.
When I add Newline to string which I write to file, this line is read two times and writeto file to times (I think that bcoz I saw this newfile)
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string contain_of_file,bufor,word,empty=" ",new_line="\n";
string conection;
string::size_type position;
cout<<"Give a word";
cin>>word;
ifstream NewFile;
ofstream Nowy1;
Nowy1.open("tekstpa.txt", ios::app);
NewFile.open("plik1.txt");
while(NewFile.good())
{
getline(NewFile, contain_of_file);
cout<<contain_of_file;
position=contain_of_file.find("Zuzia");
if(position!=string::npos)
{
conection=contain_of_file+empty+word+new_line;
Nowy1<<conection;
}
Nowy1<<contain_of_file;
}
Nowy1.close();
NewFile.close();
cin.get();
return 0;
}
The problem here is not your reading. directly, but about your loop.
Do not loop while (stream.good()) or while (!stream.eof()). This is because the eofbit flag is not set until after you try to read from beyond the file. This means that the loop will iterate one extra time, and you try to read from the file but the std::getline call will fails but you don't notice it and just continue as if nothing happened.
Instead do
while (std::getline(NewFile, contain_of_file)) { ... }
And an unrelated tip: The variable conection is not needed, you can instead do just
Nowy1 << contain_of_file << ' ' << word << '\n';
So I am trying to read from a file named input_file till it reaches the end. I've tried using while (!input_file.eof()) but it goes on for an infinite loop. I looked around on the forum and tried using while (getline(input_file, line)) but that just returns an empty line. I'm not using both getline() and the >> operator like other questions were.
How do I get around this? Here's my code:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
// Main program
void CalfFlac(ifstream& input_file) {
string text;
string line;
while (getline(input_file, line)) {
text += line;
}
cout << text << endl;
}
int main() {
ifstream input_file;
input_file.open("calfflac.in");
CalfFlac(input_file);
}
input_file contains a single line Confucius say: Madam, I'm Adam. followed by a carriage return.
Thanks for the help!
PS: I'd prefer if the solution remained simple, as this appears to be a pretty simple problem.
EDIT: Make sure you have the right file name! I tried a bogus file name and it printed a blank line as your describe.
I tried your code with a correct file name and it worked for me
In main add this line:
int main() {
ifstream input_file;
input_file.open("calfflac.in");
if(!input_file)
cout << "File path is wrong!";
CalfFlac(input_file);
}
I am working on a small program that takes a input file and processors the data in the file. With my current code (see below) when you enter a valid file name it just freezes the command line (drops down a line and just shows a flashing _ ) and I have to kill the program to get out. If you enter a invalid file name the if(!file) gets called and runs fine.
Whats really odd is that if I put a debugging cout above that if statement it will not get called if the file name is correct. Hope you can help and if you need more info let me know!
This is my current code:
using namespace std;
#include <iostream>
#include <stdexcept>
#include <string>
#include <fstream>
#include <vector>
#include <cctype>
#include "Student.h"
int main(){
string filename, name;
char *inputfile;
ifstream file;
vector<Student> students;
const int SIZE = 200;
char buffer [SIZE];
int regno, i;
cout << "Enter file name: ";
cin >> filename;
inputfile = const_cast<char*> (filename.c_str());
file.open(inputfile);
if (!file){
cout << "Failed to open " << filename << endl;
exit(1);
}
while (!file.eof()){
file.getline(buffer, SIZE);
i = 0;
regno = 0;
while (isdigit(buffer[i])){
regno = (regno*10)+buffer[i];
}
cout << regno;
}
file.close();
}
Your problems is that you never increase i in the cycle.
Here:
i = 0;
regno = 0;
while (isdigit(buffer[i])){
regno = (regno*10)+buffer[i];
}
You go into infinite cycle as i always stays 0.
Also why do you do the const_cast? You can open using a const char * too. So you can write this:
cin >> filename;
file.open(filename.c_str());
And code will still work.
There's another problem in your code concerning the use of getline() and eof(). The idiomatic way to read a file line-by-line is this:
std::string line;
while(getline(in, line)) {
// handle line here
}
in refers to some input stream like a std::ifstream or std::cin. The point is that reading a line can fail (e.g. due to EOF), which you check in above loop. Your version only checks if EOF was encountered before but not that the subsequent getline() call actually yielded any data.