I have 2 files, easyp.txt and easyn.txt, were easyp.txt stores points, and easyn.txt stores names. I have code that displays the top score and the players name. It was working fine, then I edited some other lines, and upon running again, it spews out rubbish. The codes look like this:
case 1:
infile.open("easyn.txt", ios::out | ios::app);
ofile.open("easyp.txt", ios::out | ios::app);
while (getline(infile, STRINGT) && getline(ofile, STRINGO))
{
istringstream buffer(STRINGO);
buffer >> value;
if (infile.eof() && ofile.eof()){
printf("The top player for easy is %s with only %i tries!", STRINGD, value);
break;
}
if (value < best)
{
STRINGD = STRINGT;
best = value;
}
}
infile.close();
ofile.close();
_getch();
break;
(lower number of points is better btw)
When I run the program it outputs random ascii characters as the player name, and 1835884884 as the score.
Yes I am using namespace std
The only other time I have file reading/writing is in the following:
ofstream myfile;
myfile.open("easyn.txt", ios::out | ios::app);
if (myfile.is_open())
{
myfile << chName << "\n";
myfile.close();
}
myfile.open("easyp.txt", ios::out | ios::app);
if (myfile.is_open())
{
myfile << iTurns << "\n";
myfile.close();
}
Thanks for the help
The main problem with your program is this:
printf("The top player for easy is %s with only %i tries!", STRINGD, value);
The %s format specifier to printf expects a char *, not a std::string. What you want to do to fix that is replace STRINGD with STRINGD.c_str().
Passing an argument to a varargs function of another type than the function expects to receive invokes undefined behavior. Exactly what happens depends on your architecture and ABI, so I can't really give a detailed explanation about that without such details, but I don't think that matters much anyway. :)
I don't know if this help's but instead of using the .txt extension, use the .dat extension. Maybe it would help?
.dat files are "data files" that can be opened by text editors, so I though this might help >_>
and I'd try not use ios::out | ios::app, even if you do use them, your doing it wrong. check here if you wanna fix that -> fileStreaming C++ tutorial, mostly because you'd use ios::out | ios::in in most cases.
And you could use other things besides while (getline(infile, STRINGT) && getline(ofile, STRINGO)) personally I'd never use that, mostly because it's just my preference.
Related
I am trying to find a way using which I can Edit the contents in a binary file, without reading the whole file.
Suppose this is my file
abdde
And I want to make it
abcde
I tried following:-
Attempt 1)
ofstream f("binfile", ios::binary);
if(f.is_open()){
char d[]={'c'};
f.seekp(2,ios::beg);
f.write(d, 1);
f.close();
}
//the file get erased
Output:
**c
Attempt 2)
ofstream f("binfile", ios::binary | ios::app);
if(f.is_open()){
char d[]={'c'};
f.seekp(2,ios::beg);
f.write(d, 1);
f.close();
}
//the file simple gets append seekp() does nothing
Output:
abddec
Attempt 3)
ofstream f("binfile", ios::binary | ios::app);
if(f.is_open()){
char d[]={'c'};
f.seekp(2);
f.write(d, 1);
f.close();
}
//same as before the file simple gets append seekp() does nothing
Output:
abddec
And if I just try to replace the 1st byte of the file, which is 'a' with 'h'
ofstream f("binfile", ios::binary);
if(f.is_open()){
char d[]={'c'};
f.seekp(ios::beg);
f.write(d, 1);
f.close();
}
//file is erased
Output:
h
What do I do? Is it even possible for the OS to allow a program to edit a file at any point own its own?
std::ios::app means the cursor is put at the end of the file before every write. Seeking has no effect.
Meanwhile, std::ios::binary goes into "truncation" mode by default for an output stream.
You want neither of those.
I suggest std::ios::out | std::ios::in, perhaps by just creating a std::fstream fs(path, std::ios::binary) rather than using an std::ofstream.
Yes, it's a bit confusing.
(Reference)
On your suggestion i have changed the code as you suggested but still problems are there when ios::out is replaced with ios::ate nothing is written in the file(Writing does not work). Is there any way to check that if the next bit is eof rather than reading it and then checking it? as suggested by you.And sometimes when i do file handling it shows the position of file pointer to be -1 what could that mean???
Code:
int main ()
{
char p[80];
fstream file("text1.txt",ios::out|ios::in); //if ios::ate is added here it results into infinite loop
cout<<"Starting position of the file is "<<file.tellg()<<endl;
getch();
if(file.is_open())
cout<<"file is open\n";
else
cout<<"file is not open\n";
getch();
file.seekp(0);
while(file>>p)
{
cout<<p<<endl;
}
file.clear();
cout<<"\nThe current position of the file pointer is "<<file.tellg()<<endl;
file.seekp(0);
if(file.eof())
cout<<"\n the eof\n";
while(file>>p)
{
cout<<p<<endl;
}
file.close();
return 0;
}
Output:
Starting position of the file is 0
file is open
Hello
man
how
are
you
The current position of the file pointer is 21
Hello
man
how
are
you
With this kind of reading from file reaching end-of-file causes setting both eof and failbit. Failbit is setted because creating your read loop with file.eof() condition doesn't indicate that next read will be the end of the stream. It just states that we didn't reach eof yet, so with:
while(file.eof())
{
file >> p;
}
It's possible that last read will be eof only, and we'll work with uninitialised data. IF this happens no characters will be extracted inside p and both eof and fail flags will be set.
When working with c++98 need to reset failbit to false by using:
file.clear();
To avoid bad readings situation you should extract characters from file inside while condition: while(file >> p). I recommend this or this questions on stack overflow.
So proper C++98 code should look like this:
while(file >> p)
{
std::count << p << std::endl;
}
file.clear();
file.seekp(0);
while(file >> p)
{
std::count << p << std::endl;
}
file.close();
I tested it couple of times on Visual Studio 2013 and it worked everytime.
Considering ios::ate mode:
ios::out, ios::in are modifiers that states how do we open file in question. If you want to read something from file you need to use ios::out flag, and for writing you need to use ios::in.
On the other hand ios::ate just tells compiler to open file and immediately go to the end of file. So if you substitute ios::out with ios::ate writing would be impossible, and program will rise failflag on file << "Hello...";.
And if you just want to append data, but read from the beginning of file you should use ios::app instead, because it tells to seek eof before each write.
I am trying to work with a bmp file in linux with g++ compiler. I am using C++ language.
I Need to load a .bmp file from the standard input. for example:
./a.out < test.bmp
So I need a Code to do this job. I think storing the whole .bmp file is good by I don't know how to do this.
I Tried this code but it didn't Work:
vector<int> bitmap;
int b;
while ( cin >> b ) {
bitmap.push_back(b);
cout << "!" << endl;
}
So How should I Do this?
cin >> b reads file in text mode, this is not for binary files. use something like this:
ifstream myFile ("test.bmp", ios::in | ios::binary);
to open stream for file, and then
if (!myFile.read (buffer, 100)) {
// do thomething with data in buffer
}
I Found an answer That Works Correctly.
This Code Reads The bmp_info_header from the *.bmp file from the standard input:
char bmpHeader[54];
cin.get(bmpHeader, 54);
the "54" in cin.get() tells the system to accept the max 54 numbers from the input and ignores the other.
now for example if we want to find the *.bmp size we should use this code:
int filesize = *((int*)(headers + 2));
I would like to know how could I write always to the first line of a file.
I have numbers to share via a text file to another soft, and I want to write those numbers periodically on the first line.
Thanks.
eo
If you want to completely rewrite the file, discarding it's contents then simply use trunc mode. However, if there is any other content that you want to preserve then the easiest way would be to read the file into memory, change the first line and write everything back. I think it wouldn't be possible to change the first line directly unless you are overwriting the same amount of characters.
Look at this two functions:
ostream& seekp ( streampos pos );
ostream& seekp ( streamoff off, ios_bas:seekdir dir );
maybe this solves your problem
ofstream out("foo.txt");
out << "foo";
out << "\r" << "bar";
this will leave a file with only bar in it.
2nd method:
if the file only contains one line you could open it with ofstream::trunc and close it after each write
If the file is not massive then you could write a new new file copying across each line except for the custom first line. Then afterwards replace the original.
void ReplaceFirstLine(string filename)
{
ifstream infile;
ofstream outfile;
infile.open(filename.c_str(), ios_base::in);
outfile.open("tempname.txt", ios_base::out);
bool first = true;
string s;
while (getline(infile, s, '\n'))
{
if (first)
outfile << "my new first line\n";
else
outfile << s << endl;
first = false;
}
infile.close();
outfile.close();
::CopyFileA("tempname.txt", filename.c_str(), FALSE); // or Linux equivalent
}
Is it possible to open an fstream on a file that does not exist with both ios::in & ios::out without getting an error?
To open an fstream on a file that does not exist for input and output (random access) without getting an error, you should provide the flags fstream::in | fstream::out | fstream::trunc in the open (or constructor) call. Since the file does not already exist, truncating the file at zero bytes is no drama.
You may want an error when opening a file that doesn't exist when specifying only ios::in since you'll never be able to read from the stream so failing early in this case will prevent surprise failures later on.
The answer to your question unfortunately is: "No", this is not possible in a single C++ statement.
Yes, many people will answer, that you can use the combined flags fstream::in | fstream::out | fstream::trunc. But that answer is nonsense. fstream::trunc means, that the output file will be truncated to size zero upon opening. But then, why would you like to open an empty file for reading and writing? Except for the rare case, that you need a file as a temporary store for some of your application's data, that you will first write and later read back, there is no use for this flag combination.
Some people recommend to first try to open with fstream::in | fstream::out (and possible further flags like fstream:app or fstream::binary as needed) and then check the file's error status: If the file could not be opened, then re-try the open operation including | fstream::trunc. This solution has several caveats, however. For example, if your file system is mounted via NFS, the first attempt to open the file in read/write-mode might fail due to temporary network issues. If the second attempt (the one including the fstream::trunc flag) then succeeds, there goes your wounderful data, that you have collected so far.
The safe solution is to first open the file for appending only (which will create the file, if it doesn't exist, but will not truncate it) and then close it immediately and open it a second time in read-write mode. This can be achieved with the following code: Note, that an ofstream is first constructed and then immediately discarded.
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ostream::app);
std::fstream file(filename);
Alternatively, if you need further flags, like binary, use:
std::string filename { "test.txt" };
(void) std::ofstream(filename, std::ofstream::app | std::fstream::binary);
std::fstream file(filename, std::fstream::in | std::fstream::out | std::fstream::binary);
I hope, that in C++25 (or whichever standard is next), they finally add a flag std::fstream::create to create non-existant output files, if read-write-mode is requested.
#include <fstream>
ofstream out("test", ios::out);
if(!out)
{
cout << "Error opening file.\n";
return 1;
}
ifstream in("test", ios::in);
if(!in)
{
cout << "Error opening file.\n";
return 1;
}
If an error occurs the message is displayed and one (1) is returned. However it is possible to compile and execute just ofstream out("test", ios::out); and ifstream in("test", ios::in); without any errors. Either way the file test is created.
#include <iostream>
#include <fstream>
using namespace std;
int main () {
fstream f("test.txt", fstream::in | fstream::out);
cout << f.fail() << endl;
f << "hello" << endl;
f.close();
return 0;
}
This code will print 1 and will not create "test.txt" file, if it does not exit. So it is not possible to open and fstream on a file that does not exist without getting an error.
std::fstream f("test.txt", std::ios_base::out);
f.close(); //file now exists always
f.open("test.txt", fstream::in | std::ios_base::out);
//f is open for read and write without error
I haven't checked to guarantee that it will open without error, but I feel pretty confident that it should.