That file is my input file for my program. I'm suppose to write a
simple C++ program that read that file and scramble the text with 0xFF
so I could reveall the origin string.
Unfortunatly when I open my output file I got some rubbish charecters
in addition to the wanted string. I think this rubbish charecters
where instead of space or end line.
Here's my code:
string str;
char c;
ifstream in_File(argv[1]); // Binary File
ofstream in_File(argv[2]); // Text File
while(1)
{
in_File >> c;
if(!in_File.eof())
{
char sc = (char)(c^0xFF);
str.append(1,sc);
}
else
break;
}
out_File << str;
out_File.flush();
out_File.close();
in_File.close();
any idea?
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]
Yes. You need to know if just letters were encoded or if punctuation and
numbers were as well. You also need to consider the end of line coding.
IOWs you need to know exactly how the original coding was done and then
write a program that decodes only those parts that were encoded.
I note that you are reading the input file as a binary file. That is
fine but if it was originally created as a text file you may have to
worry about such things as newline characters (and how they were encoded
because those are system dependent.)
This is wrong. Use this idiomatic version:
while(in >> c)
However, this still presents a problem, namely that it will skip whitespace
(spaces, tabs, newlines). Instead, you could use
while(in.get(c))
which will also include whitespace.
> char sc = (char)(c^0xFF);
> str.append(1,sc);
> }
> else
> break;
> }
>
> out_File << str;
> out_File.flush();
> out_File.close();
> in_File.close();
Some further notes:
* You read one file byte by byte, store it in a growing string and then
write that string into the output file. What I would suggest instead is to
read one byte, transform it and then write it again, i.e. without
intermediate storage.
* Flushing and closing the output is unnecessary. If you want, you can
flush it and then test the streamstate to make sure it was successfully
written, but closing is automatically done in the destructor of
std::ofstream.
* Closing the input stream is unnecessary, too. If you want to play safe,
check that the streamstate is 'fail' and 'eof' at the end, without the 'eof'
actual reading failed for some other reason.
* Handling chars as bytes is inconvenient, I would rather use unsigned
char. I'm not sure if std::istream has a get() overload taking an unsigned
char though. The slightly weird behaviour concerning higher bits is also
what could cause some confusion, I'm not 100% sure what problem exactly you
saw.
Uli
When I ran your code I got an output file significantly
shorter than the original. The cause is the use of
operator>> which is a *formatted* getter. I didn't do
a byte-for-byte comparison, but it's probably skipping
end-of-lines and such. Using the unformatted get
function of ifstream fixed the problem.
Also, you should probably look at this wrt your end-of-file
test:
http://www.parashift.com/c++-faq-lite/input-output.html#faq-15.5
If you combine the two changes, you can cut that
while loop down significantly.
--Jonathan
Just commenting it "// Binary file" doesn't make it so.
You need to open with mode ios::binary
The "proper" way to do what you are trying to do is to provide a
custom streambuf - If you do it that way then it doesn't matter
whether you open as text or binary (provided that it is the same for
read and write) because the conversion is done at a lower level.
(You might also want to consider rot13 instead of xor FF just because
there are utilities that use it already)
> I got assignment - I got a binary file that was built by scrambling
> string with XOR 0xFF
>
> That file is my input file for my program. I'm suppose to write a
> simple C++ program that read that file and scramble the text with 0xFF
> so I could reveall the origin string.
>
> Unfortunatly when I open my output file I got some rubbish charecters
> in addition to the wanted string. I think this rubbish charecters
> where instead of space or end line.
>
> Here's my code:
>
> string str;
> char c;
> ifstream in_File(argv[1]); // Binary File
> ofstream in_File(argv[2]); // Text File
[This is obviously not the code you tried. Please post real code;
those who might be willing to respond to you normally don't like to
make guesses about the real code.]
> while(1)
> {
> in_File >> c;
> if(!in_File.eof())
1. The operation
in_File >> c
has a return value which, like other return values, shouldn't be
ignored by the caller.
Among other things, this return value informs the caller about the
success of the input operation. If operator>> is used to iterate over
a stream, its return value is normally a better choice for controlling
the length of the iteration than the return value of eof(). E.g.:
while (inFile >> c)
{
...
}
But:
2. operator>> is dealing with *formatted* ("textual") input, while
your input is unformatted ("binary"). The Standard Library input
streams have different operations for dealing with unformatted input,
which you should use. One difference between formatted and unformatted
input is that the former ignores whitespace characters.
You probably need to open the files in binary mode and instead of using
formatted stream operators << and >> use get() and put():
#include <fstream>
int main(int, char** argv) {
using namespace std;
ifstream in_File(argv[1], ios_base::binary);
ofstream out_File(argv[2], ios_base::binary);
while(1)
{
int byte = in_File.get();
if(in_File.eof())
break;
byte ^= 0xff;
out_File.put(byte);
}
}
--
Max