Unable to read new line of a file - c++

I'm quite new to C++ programming, and I'm having trouble reading from an already open file. What I'm doing is writing to a file, reading from it, adding to the end of it, and then trying to read from it again without having to close the original ifstream. The code is as follows:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
ofstream myFile ("example.dat");
// Open and write to file
if (myFile.is_open())
{
myFile << "This is a line." << endl;
myFile << "This is another line." << endl;
myFile.close();
}
else cout << "no";
// Open and read from file
string line;
ifstream myFilein ("example.dat");
if (myFilein.is_open())
{
while (getline(myFilein,line))
{
cout << line << myFilein.tellg() << endl;
}
//myFilein.close();
}
// Open and add to end of file
if (!myFile.is_open())
{
myFile.open("example.dat", ios::app);
myFile << "This is the last line." << endl;
myFile.close();
}
//myFilein.open("example.dat", ios::ate);
// Read from already open file
myFilein.seekg(0, ios::beg);
if (myFilein.is_open())
{
cout << "myFilein is open. " << myFilein.tellg() << endl;
while (!myFilein.eof())
{
getline(myFilein, line);
cout << line << endl;
}
}
myFilein.close();
int holdClose;
cin >> holdClose;
return 0;
}
Obviously, something is going wrong, as tellg() is returning a value of -1 after the initial read (i.e., after it hits the end of the file), but I'm not entirely sure why it's returning -1, since I'm trying to reset the position to the beginning of the file. Is there something I'm missing or misunderstanding about how this works? If I close and re-open the file, then it's fine, but I'm curious if there's a way to keep reading from it without having to close it, if that makes sense. Thank you for your help :)

You didn't clear the state of the stream, thus the seekg call did nothing. You need to add myFilein.clear() before the repositioning.

Related

Empty content in output out from while cycle

I want to load data from .txt file to variable and working with them (like calculate). When I open data, I can read them, but I donĀ“t know to work with data.
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;
int main()
{
fstream newfile;
string file;
newfile.open("zadanie.txt", ios::in);
if (newfile.is_open()) {
while (getline(newfile, file)) {
cout << file << "\n"; //I GET OUTPUT CORRECTLY
}
newfile.close();
}
else
cout << "Error. \n";
cout << file << "\n"; //HERE IS PROBLEM. OUTPUT IS EMPTY
return 0;
}
I tried global variable, but it not solved. What should I do to correct it? Thanks
What you call "PROBLEM" in the comment is not a problem. file never contains more than a single from the file. The last call to getline will not read a line because there is nothing left in the file when you reach its end. So when you call
std::cout << file;
after that loop, it is to be expected that file is empty. If you want to use the lines later you should store them somewhere, eg in a std::vector<std::string>> :
int main()
{
fstream newfile;
std::vector<std::string> data; // vector to hold all lines
newfile.open("zadanie.txt", ios::in);
if (newfile.is_open()) {
string line; // better name (file->line)
while (getline(newfile, line)) {
cout << line << "\n";
data.push_back(line); // add the line to data
}
newfile.close();
}
else
cout << "Error. \n";
for (const auto& l : data) std::cout << l << '\n';
return 0;
}

ifstream + opening random txt file (c_str)

I want to open a random .txt file and put the data into some strings.
It works if I write the path into the code.
I don't get it why this doesn't work.
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
string file;
ifstream filein(file.c_str());
cout << "Insert Path" << endl;
cin >> file;
cout << file << endl;
filein.open(file.c_str(), ios::in);
for (string line; getline(filein, line);) {
cout << line << endl;
}
return 0;
}
Your filename string is empty because std::string defaults to empty.
You are passing an empty string (or the nul string) to the ifstream constructor, which is at best, undefined behavior.
Try writing your code like this:
#include <iostream>
#include <fstream>
int main()
{
std::string file;
std::cout << "Insert Path" << std::endl;
std::getline(std::cin, file);
std::cout << file << std::endl;
std::ifstream filein(file);
for (std::string line; std::getline(filein, line); )
{
std::cout << line << std::endl;
}
return 0;
}
Notable edits include:
We're now constructing the ifstream object only when we need it, after file has had data stored, which means no more undefined behavior, and that we only attempt to open a file after we know what the path is.
We're retrieving a whole line when storing to file, instead of only the first word, which is crucial if your path includes any spaces.
We're just using the file string directly. There's no need to call c_str().
We're no longer using using namespace std;. There are many, many reasons why this is bad practice.
EDIT:
If you have a C++17-compliant compiler, I'm going to propose you write code that looks like this instead:
#include <iostream>
#include <fstream>
//You may need to write #include <experimental/filesystem>
#include <filesystem>
#include <string>
int main()
{
std::string input_line;
std::cout << "Insert Path" << std::endl;
std::getline(std::cin, input_line);
//You may need to write std::experimental::filesystem
std::filesystem::path file_path{input_line};
//This will print the "absolute path", which is more valuable for debugging purposes
std::cout << std::filesystem::absolute(file_path) << std::endl;
std::ifstream filein(file_path);
for (std::string line; std::getline(filein, line); )
{
cout << line << endl;
}
return 0;
}
Explicit use of path objects will make your code more readable and make errors more explicit, as well as grant you access to behavior you otherwise would not be able to access.
first what are you opening? as long as you string doesn't contain anything??
second even if the string contains a valid path and the opening was successfull at the first time but in the second will fail as long as you use the same file stream on multiple files without clearing its buffer and closing the previous file:
string file "C:\\MyProject\\data.txt"; // let's say a valid path
ifstream filein(file.c_str());
if(filein.fail()) // the condition fails as long as the opening was successfull
cout << "failed to open file!" << endl;
cout << "Insert Path" << endl;
cin >> file; // let's say the user enters a valid path again: "C:\\MyProject\\test.txt"
cout << file << endl;
filein.open(file.c_str(), ios::in); // fail to correct it:
filein.close();
filein.clear(); // very important
filein.open(file.c_str(), ios::in); // now it's ok!
for (string line; getline(filein, line);) {
cout << line << endl;
}

Why can't I write to a file if it is located within an if statement?

I am trying to create a very simple program that writes to a file, but can't understand why it won't let me write to a file if I put it within an if statement! Here's the code:
#include "stdafx.h"
#include <iostream>
#include <fstream>
#include <string>
#include <stdlib.h>
using namespace std;
void readFile();
int main()
{
string line;
string today;
string readOrWrite;
cout << "Do you want to write to a file or read a file? " << endl;
cout << "Type \"write\" or \"read\" ";
cin >> readOrWrite;
if (readOrWrite == "read")
{
readFile();
}
else if (readOrWrite == "write")
{
cout << "How are you today? " << endl;
getline(cin, today);
ofstream myJournal;
myJournal.open("Journal.txt", ios::app);
myJournal << today << " ";
myJournal.close();
}
else
{
return 0;
}
return 0;
}
void readFile()
{
ifstream myJournal;
myJournal.open("Journal.txt");
string line;
if (myJournal.is_open())
{
while (getline(myJournal, line))
{
cout << line << endl;
}
myJournal.close();
}
else
{
cerr << "Error opening file ";
exit(1);
}
}
When I move it out of the if statement, it works smoothly and is able to write to the file, but when I place it inside, it opens the program, asks me the "Do you want to write to a file or read a file? ", I type "write", then it says "How are you today? " and then ends the program, printing "Press any key to continue...". Any help?
it says "How are you today? " and then ends the program, printing "Press any key to continue...". Any help?
std::istream::ignore should help in that case you are encountering.
cout << "How are you today? " << endl;
cin.ignore(10, '\n'); // Inserted
getline(cin, today);
Why do we need that in between?
It takes out 10 characters, which is enough amount of length, from the buffer and stops if it encounters a newline, which is '\n'. (Remember that you press the key 'enter' after typing "wrtie")
By doing so you can move on to the next new line, preventing std::cin from any parse failure.
More info : http://www.cplusplus.com/reference/istream/istream/ignore/

regarding: instance of 'std::bad_alloc'

I read other posts but none of them helping at all,
This code have no error still there is bad_alloc error...
#include <iostream>
#include <fstream>
using namespace std;
int main()
{
char super[25];
char name[25],last_name[25];
int length;
char *sym = "#";
char *buffer;
ofstream outfile;
outfile.open("farses.dat",ios::app);
cout << "Writing to the file" << endl;
cout << "Enter your First Name: ";
cin >> name;
outfile << *sym;
outfile << name << endl;
cout << "Enter your Last Name: ";
cin >> last_name;
outfile << *sym;
outfile << last_name << endl;
cout << "Enter The Sentence : ";
cin.getline(super,25);
outfile << super << endl;
outfile.close();
ifstream infile;
infile.open("frases.dat");
infile.seekg(0, ios::end);
length = infile.tellg();
infile.seekg(0,ios::beg);
buffer = new char[length];
infile.read(buffer , length);
cout << "\n\nReading from file \n\n" << endl;
cout << buffer << endl;
infile.close();
return 0;
}
This code is terminating after coming to sentence statement..the getline() function is causing problem i guess but when i tried on other two statements(name and last_name),the getline(), it works perfectly..i even degraded the char limit to 5 too but after sentence statement is throw anyways
Thumb rule, don't fool yourself into thinking that your code has no errors. Especially when you clearly got an error. This kind of mindset will make you unable to find errors because everything you see is correct.
You never checked if your streams were open and you entered the wrong file name in the ofstream.
What happens is that, you write your data into a file name farses.dat and then you try to open a file called frases.dat (which I assume is the correct name, it means sentences).
You are getting the cursor position ifstream::tellg of an inexistent file, and it fails so the function returns -1. This is the value of length before you allocate your buffer.
When you do allocate your buffer you get a bad_alloc exception (bad_array_new_length).
Checking if your file was open would, at the very least, have saved you some debug time.
Something like this,
ifstream infile;
infile.open("frases.dat");
if ( infile.is_open() ) {
// File is open, do stuff (...)
if ( length <= 0 ) {
// Empty file / error, don't create buffer!!!
}
// (...)
infile.close();
}
else {
// Couldn't open file
}
EDIT: Fixed error explanation.

How to write even numbers from sequential access file to a new sequential access files

Can someone with a little time on their hands please compile and run this code and see where I am going wrong?
#include <iostream>
#include <fstream>
using std::cout;
using std::endl;
using std::ifstream;
using std::ofstream;
using std::ios;
int main()
{
int numbers = 0;
//create and open file
ifstream inFile;
ofstream outFile;
inFile.open ("numbers.txt", ios::in);
outFile.open ("evenNumbers.txt", ios::out);
//determine whether the file was opened
if (inFile.is_open() && outFile.is_open())
{
//read numbers file
inFile >> numbers;
while (!inFile.eof())
{
//look for even numbers
if (numbers %2 == 0)
{
outFile << numbers << endl;
//cout << numbers << endl;
}
inFile >> numbers;
}
//end while
//close files
outFile.close();
inFile.close();
cout << "Program successful. File complete." << endl;
}
//if file fails to open, display error message
else
cout << " File could not be opened " << endl;
//end if
system ("pause");
return 0;
} //end of main function
Your code has quite a few problems:
ifstream inFile;
inFile.open("numbers.txt", ios::in);
It's not exactly an error, but ios::in is the default for an ifstream, and you typically supply the file name to the constructor, something like this:
ifstream inFile("numbers.txt");
Then we have this:
getline(inFile, name);
inFile >> num;
while (inFile.eof())
while (inFile.eof()) seems to have the logic backwards -- you want to read until you reach the end of the, then quit. The rest of your loop will work (unusual for one that uses file.eof() as the condition) but is unnecessarily long and difficult to read.
//create file object and open the file
ofstream outFile;
outFile.open("updatedNumbers.txt", ios::out);
As you'd expect from the previous comment, ios::out is the default for an ofstream, and you usually give the file name to the constructor: ofstream outFile("updatedNumbers.txt");
//write the updated numbers to the file
outFile << heading << endl;
outFile << columnHeaders << endl;
outFile << underLines << endl;
heading, columnHeadders and underLines seem to be undefined variables.
for (x=0;x<20; x++)
{
if (int x%2==0)
sample[x] = x+2;
else
sample[x] = x+20;
sample also seems to be undefined.
outFile << num[x] << endl;
num also seems to be undefined. Perhaps you intended it to be the same as sample? Otherwise, you don't seem to have any code to set it to any particular value before you write it out.
Probably worse than any of that is the fact that your heading talks about writing the even numbers from one file to another, but your code doesn't seem to do anything even vaguely similar to that at all.
Well, the heading variable is undeclared, but I guess you already know that....
The error is here:
outFile << heading << endl;
outFile << columnHeaders << endl;
outFile << underLines << endl;
This is the first time you these variables heading, columnHeaders and underLines are mentioned in your program. The compiler complains because they have not been declared anywhere (Should they be int or std::string ore some other type?). Also they won't contain any useful values because nothing has been assigned to them.