I copy/paste this console application, which is a banking record keeping system, and I get an error for the ">" operator not having operands; if (infile.read(reinterpret_cast<char*>(this), sizeof(*this)) > 0)
Does it have something to do with types? I read vaguely somewhere about the int needing to be overloaded or something. Anyways, idk.
Here is part of the code:
void account_query::read_rec()
{
ifstream infile;
infile.open("record.bank", ios::binary);
if (!infile)
{
cout << "Error in Opening! File Not Found!!" << endl;
return;
}
cout << "\n****Data from file****" << endl;
while (!infile.eof())
{
if (infile.read(reinterpret_cast<char*>(this), sizeof(*this)) > 0)
{
show_data();
}
}
infile.close();
ifstream::read() does not return the number of characters read. It returns a reference to itself.
Also, dont use while (!infile.eof()): Why is iostream::eof() inside a loop condition (i.e. while (!stream.eof())) considered wrong?
Instead, test if the ifstream is in a good state after reading from it. This can done with:
if(infile) { ... }
Since infile.read(...) returns a reference to infile, this could be a possible fix:
cout << "\n****Data from file****" << endl;
while (infile.read(reinterpret_cast<char*>(this), sizeof(*this)))
show_data();
}
Related
I'm trying to write a program that replaces a specific number with an 'x' character. The task requires every number to be in its own line, but it seems like '\n' is causing the read/write pointers to behave out of this world. Here's a picture of the output.
My questions are:
why are the pointers behaving this way?
How far do I need to move the write pointer backwards to overwrite a line to make this work?
is there an easier workaround?
Here's my code:
void input(int n)
{
fstream file;
file.open("numbers.txt", ios::out);
while(n --> 0)
{
file << n;
file << '\n';
}
file.close();
}
void read()
{
fstream file;
string tmp;
file.open("numbers.txt", ios::in);
while(true)
{
getline(file,tmp);
if(file.eof())
break;
cout << tmp << endl;
cout << "tellg: " << file.tellg() << " tellp: " << file.tellp() << endl;
}
file.close();
}
void replace()
{
fstream file;
string tmp;
file.open("numbers.txt", ios::in | ios::out);
while(true)
{
file >> tmp;
if(tmp == "6")
{
//cout << file.tellg() << endl;
file.seekp(file.tellg() - tmp.length()-1);
file << "x";
}
if(file.eof())
break;
}
file.close();
}
int main()
{
input(10);
replace();
read();
return 0;
}
Since you open your file in text mode, you need to account for the potential that the underlying stream may use a line end sequence (\r\n) rather than just a \n. I guess, this is the primary problem. The easiest remedy is probaly to open the file in binary mode:
file.open("numbers.txt", std::ios_base::binary | std::ios_base::in | std::ios_base::out);
That said, since you switch from writing to reading without intervening seek, your code is undefined behavior, i.e., anything can happen. You should seek to the current location between writing and reading.
Personally, I'd refrain from rewriting files in-place. It generally gets unnecessary trick. If I were to rewrite files in place, I'd use seekg() to get the current position before a read, saving the position and restoring it prior to the write (I essentially never use the seek operations, i.e., I may have got the signatures wrong):
for (std::streampos pos = (in >> std::ws).tellg();
in >> tmp; pos = (in >> ws).tellg()) {
if (need_to_overwrite) {
in.seekp(pos);
// ...
in.seekg(0, std::ios_base::cur);
}
}
The use of in >> std::ws is to make sure that whitespace is skipped before storing the position.
Also note that your check for file.eof() is wrong: the last line is processed twice. When reading from a file the result shall be tested before using the read string, e.g.:
while (in >> tmp) {
// ...
}
I'm trying to write a function that automatically formats XML-Strings; but I'm already failing when I try to read text from a file and write it into another one.
When I use my function sortXMLString()
bool FormatXML::sortXMLString()
{
string XMLString;
ifstream fin("input.txt");
fin.open("input.txt", ios::in);
ofstream fout("output.txt");
fout.open("output.txt", ios::out);
if (fin.is_open() && fout.is_open())
{
if (fin.good()) cout << "good" << endl;
if (fin.fail()) cout << "fail" << endl;
if (fin.bad()) cout << "bad" << endl;
while (getline(fin, XMLString))
{
//TODO: Formatting
fout << &XMLString << endl;
}
fin.close();
fout.close();
}
else return false;
return true;
}
I will get the output "fail", but the function never enters the while-loop. The function returns true.
It doesn't matter what I write into my input.txt (a single letter, a single number, multiple lines of text or even nothing), the failbit will always be set before getline can even be reached.
Why is this/ how can I properly read out of my file?
ifstream fin("input.txt"); will open the file with fin as stream object why calling open member function again ? same goes for fout object too.
Calling open on an already open stream fails, meaning the failbit flag is set to true.
Just open once
ifstream fin("input.txt");
ofstream fout("output.txt");
void getBookData(bookType books[], int& noOfBooks)
{
ifstream infile;
string file = "bookData.txt";
infile.open(file.c_str());
if (infile.fail()) {
cout << "No file found!" << endl;
infile.clear();
}
while (true) {
string line;
getline(infile, line, '\r');
if (infile.fail()) {
break;
}
cout << "Line: " << line << endl;
}
infile.close();
}
I've tried putting the file in every location I can think of, but somehow it's not loading in. Or, more likely, I'm doing something else wrong. This isn't anything like what the end result of my code is supposed to be like, right now I'm just trying to read out my file line by line.
I guess you really need help debugging why this is happening to you.
Try adding some more code to your routine to help you determine what is going on. One thing to try is to call getcwd.
#include <unistd.h>
...
char buf[PATH_MAX];
std::cout << "cwd: " << getcwd(buf, sizeof(buf)) << std::endl;
...
This should report to you where your program thinks it is running from.
Start with that first, and I am guessing the next steps will become obvious to you.
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;
}
I am trying to read from file:
The file is multiline and basically i need to go over each "word". Word being anything non space.
Sample input file would be:
Sample file:
test 2d
word 3.5
input
{
test 13.5 12.3
another {
testing 145.4
}
}
So I tried something like this:
ifstream inFile(fajl.c_str(), ifstream::in);
if(!inFile)
{
cout << "Cannot open " << fajl << endl;
exit(0);
}
string curr_str;
char curr_ch;
int curr_int;
float curr_float;
cout << "HERE\n";
inFile >> curr_str;
cout << "Read " << curr_str << endl;
The problem is when it reads new line it just hangs. I read everything before test 13.5
but once it reaches that line it doesnt do anything.
Anyone can tell me what I am doing wrong?
Any better suggestion on how to do this???
I essentially need to go through file and go one "word" (non white char) at the time.
I
Thanks
You open a file 'inFile' but are reading from the 'std::cin' any particular reason?
/*
* Open the file.
*/
std::ifstream inFile(fajl.c_str()); // use input file stream don't.
// Then you don't need explicitly specify
// that input flag in second parameter
if (!inFile) // Test for error.
{
std::cerr << "Error opening file:\n";
exit(1);
}
std::string word;
while(inFile >> word) // while reading a word succeeds. Note >> operator with string
{ // Will read 1 space separated word.
std::cout << "Word(" << word << ")\n";
}
Not sure how "in the spirit" of the iostream library this is, but you could do it with unformatted input. Something like:
char tempCharacter;
std::string currentWord;
while (file.get(tempCharacter))
{
if (tempCharacter == '\t' || tempCharacter == '\n' || tempCharacter == '\r' || tempCharacter == ' ')
{
std::cout << "Current Word: " << currentWord << std::endl;
currentWord.clear();
continue;
}
currentWord.push_back(tempCharacter);
}
Does that work?