Click to See Complete Forum and Search --> : File I/O help


JasonBB
July 5th, 2008, 11:31 AM
Hey everone,

I recently decided to try programming in C++, and so far I have been doing very well on my own. However, I ran into a massive wall in the program I am trying to build: C++ file I/O functions. After weeks of experimenting and searching, I still can't figure out what I am doing. Hopefully someone can help.

I need to read in 350 characters from file1 as a string, pass it to a function I created to modify the string (it takes in a string and returns a string), and then output the string to file2. This loops until file1 has been completely read in. Then, file2 needs to be read in the same way and output to file3.

In psuedocode:

file1 = open "test.txt";
file2 = open "test2.txt";

string mystring

while(!EOF file1){
mystring = read 350 chars from file1;
mystring = my_function(mystring);
write mystring to file2;
}

close file1;
close file2;

file1 = open "test2.txt";
file2 = open "test3.txt";

while(!EOF file1){
mystring = read 350 chars from file1;
mystring = another_my_function(mystring);
write mystring to file2;
}

close file1;
close file2;

Does that make sense?

I can't use the getline function, because there are few new lines if any in the 100 MB file to be read in and changed, and I only want 350 characters at a time. Also, newlines and spaces need to be preserved.

Thanks for your time,
Jason

Bluefox815
July 5th, 2008, 02:00 PM
you should be able to use the get() function to get a single character
(char ch = in.get())



// recommendations, file1 and file2 aren't the best of names for different streams (in and out)
ifstream file1; // rename this to in, or input
ofstream file2; // rename this to out, or output

// int main(int argc, char** argv) {

file1.open("test.txt");
file2.open("test2.txt");

string mystring;

char* buffer;
while(!file1.eof()) {
for (int i = 0; i < 350; i++) {
buffer[i] = file1.get();
}
delete[] buffer;
mystring = buffer;
mystring = my_function(mystring);
file2 << mystring;
}

file1.close();
file2.close();

file1.open("test2.txt");
file2.open("test3.txt");

while(!file1.eof()) {
for (int i = 0; i < 350; i++) {
buffer[i] = file1.get();
}
delete[] buffer;
mystring = buffer;
mystring = another_my_function(mystring);
file2 << mystring;
}

file1.close();
file2.close();

// }


I haven't tested the code, but I don't see why it wouldn't work. (also, I think it would be helpful to know that file1.open(char*) works but not file1.open(string) and double quotes in C++ makes a char* not a string, I had a hard time debugging that one time.)

Duoas
July 5th, 2008, 06:37 PM
You can also use the STL

#include <algorithm>
#include <fstream>
#include <string>

...

std::string mystring;

...

file1 >> noskipws;
while (file1)
{
mystring.clear();
copy_n(
back_inserter( mystring ),
350,
istream_iterator <char> ( file1 )
);
mystring = my_function( mystring );
file2 << mystring;
}

If you are working with binary data, make sure to open the file with ios::binary mode.

You may not have the copy_n() template function. (Apparently it wasn't part of the last standard, alas.) Here it is:

template <
typename InputIterator,
typename SizeType,
typename OutputIterator
>
inline OutputIterator copy_n(
InputIterator first,
SizeType count,
OutputIterator result
) {
for (; count > 0; --count)
*result++ = *first++;
return result;
}

Hope this helps.

[edit] Yeah, that fstream doesn't take std::string thing always gets me too... But you can always say:
ifstream foo( filename.c_str() );
Heh...

JasonBB
July 5th, 2008, 07:52 PM
Thanks guys. That give me more information than I have been able to find in weeks of searching! I went with Bluefox815 code (it looks closer to some of my previous attempts), but I get this error when I run the program:

Run-Time Check Failure #3 - The variable 'buffer' is being used without being initialized.
I am not sure how to go about fixing it. There are no compiling errors.

BTW: what does the asteric ("*") do? i.e. char* buffer? I guess it creates an array of chars?

And, I know this sounds stupid, but how would I know if I am dealing with binary data?

Paul McKenzie
July 5th, 2008, 08:11 PM
I get this error when I run the program:The error means what it says. You're using a variable that has not been initialized.
I am not sure how to go about fixing it. You fix it by initializing the variable before you use it.
BTW: what does the asteric ("*") do? i.e. char* buffer?The * means pointer. I suggest you get a basic book or tutorial on C++, as this is a very basic topic (pointers). I guess it creates an array of chars?No it doesn't.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 08:15 PM
Er, I figured that much about the error message. But how do I initialize the variable?

And, yes, I probably should a more serious look at a tutorial, but for now I just want to finish the program.

Paul McKenzie
July 5th, 2008, 08:32 PM
Er, I figured that much about the error message. But how do I initialize the variable?Where is the code?

And, yes, I probably should a more serious look at a tutorial, but for now I just want to finish the program.If you're not aware that char* does not create a buffer, your program will have more problems than you believe it will.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 08:38 PM
Where is the code?
. . . It's the same code Bluefox815 posted, just with different file names, and as suggested I changed file1 to file_in and file2 to file_out.

If you're not aware that char* does not create a buffer, your program will have more problems than you believe it will.
You sound like a happy, optimistic guy. I am looking for answers, not criticism.

Paul McKenzie
July 5th, 2008, 09:06 PM
You sound like a happy, optimistic guy. I am looking for answers, not criticism.No, I'm being realistic.

If you are not familiar with C++ enough to know the basics, you will have problems with your program, if not now, then later. This is especially the case with pointers (which a char * is), and dynamic memory allocation.

Regards,

Paul McKenzie

Paul McKenzie
July 5th, 2008, 09:10 PM
. . . It's the same code Bluefox815 posted, just with different file names, and as suggested I changed file1 to file_in and file2 to file_out.And that code is incomplete and buggy. Please post the actual code you're using.

char* buffer;
while(!file1.eof()) {
for (int i = 0; i < 350; i++) {
buffer[i] = file1.get();
}
delete[] buffer;

This is wrong, as buffer was never allocated. If you could get this program to compile, you would more than likely get a crash when you run it.

You can't just take a random post, not know what it really does, and try to make it do something. You cannot program C++ this way -- you must know each and every step that you're doing.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 09:25 PM
Then help me understand. What should the code be? So far I have gotten no information from you in four posts.

Paul McKenzie
July 5th, 2008, 09:38 PM
Then help me understand. What should the code be?So far I have gotten no information from you in four posts.So I wasted my time pointing out to you that the code you copied is not correct, and showed you why it isn't correct, that char* is a pointer, your code will crash, etc.??

delete [] buffer;
This requires that

1) buffer is a pointer AND

2) The pointer was initialized using operator new[]

The code did not do 2).

All of this is discussed in any C++ book or tutorial (management of the C++ free-store). And as I mentioned in my other posts, managing the free-store is not a trivial task -- it requires that you know every step of what you're doing.

Also, where is the code that you wrote? You still haven't posted it. Once you post it, then and only then can it be commented on. You stated you have syntax errors and all kind of other errors, so post the code so that you get a proper assessment of what needs to be done.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 09:57 PM
So I wasted my time pointing out to you that the code you copied is not correct, and showed you why it isn't correct, that char* is a pointer, your code will crash, etc.??

*sigh*
I figured the code wasn't correct because it didn't run. I still don't know why, so I don't see what your talking about on that point. What is a pointer? I tried googling it and can't figure it out. Telling me that my code will crash isn't at all helpful unless I know why. I am used to forum posts where users say "here is the problem, here is what is causing it, here is a suggestion on fixing it." To me (keeping in mind that I am very new to C++), it just sounds like "here is the problem."

I don't want to argue, I just want some answers. I have been working on this for program for a month, and this is all I need to do to finish it. If you are getting annoyed, then it might be better to let someone else answer instead.



delete [] buffer;
This requires that

1) buffer is a pointer AND

2) The pointer was initialized using operator new[]

The code did not do 2).


Now we may be getting somewhere. How would that fit into the code that Bluefox815 provided?


All of this is discussed in any C++ book or tutorial (management of the C++ free-store). And as I mentioned in my other posts, managing the free-store is not a trivial task -- it requires that you know every step of what you're doing.


I will look into that stuff more when I finish this program. I will be leaving town soon, so I don't have much time.


Also, where is the code that you wrote? You still haven't posted it. Once you post it, then and only then can it be commented on. You stated you have syntax errors and all kind of other errors, so post the code so that you get a proper assessment of what needs to be done.


I told you, my code is only what Bluefox815 posted. If it makes you happy, then here:


#include <string>

#include <iostream>

#include <fstream>

#include <stdio.h>

using namespace std;

/*More stuff here*/

int main(int arg_num, char* args[]){
ifstream file_in;

ofstream file_out;

file_in.open("test.txt");

file_in.open("enc.txt");

string mystring;

char* buffer;

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

delete[] buffer;

mystring = buffer;

mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

file_in.open("enc.txt");

file_out.open("unenc.txt");

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

delete[] buffer;

mystring = buffer;

mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

return 0;

}

Paul McKenzie
July 5th, 2008, 10:12 PM
*sigh*
I figured the code wasn't correct because it didn't run. I still don't know why, so I don't see what your talking about on that point. What is a pointer? I tried googling it and can't figure it out.A pointer is a variable that holds a memory location. This is a basic C++ topic -- pointers.
I am used to forum posts where users say "here is the problem, here is what is causing it, here is a suggestion on fixing it." To me (keeping in mind that I am very new to C++), it just sounds like "here is the problem."If you don't understand the problem, what good is the fix? Also, if you're told what the problem is, it isn't difficult to research the fix yourself. You also (up until now) didn't post the code that *you* wrote. No one can work with an incomplete post by someone else.
I told you, my code is only what Bluefox815 posted.The code you posted is *not* the same code as what Bluefox815 posted. I already mentioned to you that the code that Bluefox815 posted was incomplete, and complete code is what needs to be posted. Notice that your code has headers and a main() program. All of this needs to be present to diagnose compiler and runtime errors.

May I suggest you read the C++ FAQ here:

http://www.parashift.com
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8


char * buffer = new char [350];
//...
delete [] buffer;

That is how you properly use new[] and delete[]. But this is only the surface, as mismanaging the memory that is returned will cause other issues.

The code also calls delete[] on a buffer that was already deleted. This is incorrect.

Instead of all of this, use std::vector<>

#include <vector>
//...
std::vector<char> buffer(350);
//...
mystring = &buffer[0];

Then there is no need for delete[] (or new[]).

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 10:32 PM
A pointer is a variable that holds a memory location. This is a basic C++ topic -- pointers.

Vague, but thank you.

If you don't understand the problem, what good is the fix? Also, if you're told what the problem is, it isn't difficult to research the fix yourself.

. . . Isn't the point of a forum to help you learn? I understand that one needs to learn to find answers, but at the stage I am at right now, I need someone to help me find answers.

I am not new to programming, only to compiled languages. Starting is the hardest, slowest part, and it helps a lot when people can show you solutions and how they arrived at them. Don't asume that I haven't looked myself.

You also (up until now) didn't post the code that *you* wrote. No one can work with an incomplete post by someone else.
The code you posted is *not* the same code as what Bluefox815 posted. I already mentioned to you that the code that Bluefox815 posted was incomplete, and complete code is what needs to be posted. Notice that your code has headers and a main() program. All of this needs to be present to diagnose compiler and runtime errors.

Unless you though that I forgot headers and the main method, I don't see why you needed my version of the code.

May I suggest you read the C++ FAQ here:

http://www.parashift.com (http://www.parashift.com/)
http://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.8

Slightly insulting, but okay.


char * buffer = new char [350];
//...
delete [] buffer;

That is how you properly use new[] and delete[]. But this is only the surface, as mismanaging the memory that is returned will cause other issues.

The code also calls delete[] on a buffer that was already deleted. This is incorrect.

Instead of all of this, use std::vector<>

#include <vector>
//...
std::vector<char> buffer(350);

Then there is no need for delete[] (or new[]).

Thank you! :) Now that is helpful! However, I get the following error:
error C2679: binary '=' : no operator found which takes a right-hand operand of type 'std::vector<_Ty>' (or there is no acceptable conversion)

#include<string>

#include<iostream>

#include<fstream>

#include<stdio.h>
#include<vector>



usingnamespace std;

/*More stuff here*/

int main(int arg_num, char* args[]){
ifstream file_in;

ofstream file_out;

file_in.open("test.txt");

file_in.open("enc.txt");

string mystring;

std::vector<char> buffer(350);


while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = buffer;

mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

file_in.open("enc.txt");

file_out.open("unenc.txt");

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = buffer;

mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

return 0;

}


The line in question is:

mystring = buffer;

Paul McKenzie
July 5th, 2008, 10:45 PM
Vague, but thank you.

. . . Isn't the point of a forum to help you learn?A line has to be drawn somewhere. A forum is not the place to learn basic C++ language concepts. That is the domain for books, and if available on-line sites dedicated to teaching the language.
Unless you though that I forgot headers and the main method, I don't see why you needed my version of the code.Again, and I won't repeat it -- we need to see what you wrote, not what someone else wrote. We have no idea if you may have changed something, missed a line, added a line, etc. Too many times, we're guessing as to what someone wrote, and then 20 posts later, lo and behold it isn't what they claim they wrote. To circumvent all of these problems, take the time to post the code you wrote so that this doesn't occur.
Slightly insulting, but okay.And what is insulting about it? It is one of the best FAQ's out there for C++ on the internet.

Note that this is the C++ FAQ that is maintained by comp.lang.c++. It is *the* newsgroup forum for asking C++ questions. They have a protocol, and a darn good one, when someone asks a question concerning code that doesn't work. It is also the FAQ that others here point others to when asking more specific C++ questions.

This is one fix you must do:

mystring = &buffer[0];

A std::string requires a char* for it to be initialized, and a pointer to the first element of a vector<T> is a T*.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 11:33 PM
The FAQ itself is not insulting, this link is:
http://www.parashift.com/c++-faq-li...st.html#faq-5.8
Anyway. . .
Now there are no errors, but nothing is happening. The console is just blank and sits there. :confused: My guess is that there is an infinate loop in there somehow. It looked like the files are not being created, either. (possibly the reason for the infinate loop?)

Paul McKenzie
July 5th, 2008, 11:46 PM
The FAQ itself is not insulting, this link is:
http://www.parashift.com/c++-faq-li...st.html#faq-5.8
And that is insulting how? It merely describes what should be done if code does not work. What objection do you have to it?
Now there are no errors, but nothing is happening. The console is just blank and sits there. :confused: My guess is that there is an infinate loop in there somehow. It looked like the files are not being created, either. (possibly the reason for the infinate loop?)Then it's time to learn to use the debugger that should be available with your compiler suite. Learning to use the debugger is part and parcel of learning C++ programming.

You should be single-stepping through your program, watching the variables, checking the flow, etc. and seeing what values are being set where.

Regards,

Paul McKenzie

JasonBB
July 5th, 2008, 11:54 PM
I've been using the debugger-- that is what brought up the runtime errors earlier. I tried adding this right after the file_in.open() statement, and it still went throught the loop:
if(!file_in.is_open()){return 0;}
So I asume the file is open, however when I added a cout to the loop, it echo's out blanks in the for statement and nonsense in the rest of the loop.

JasonBB
July 6th, 2008, 12:02 AM
Woah! I put this at the end of the loop:
cout << file_in.eof() << "|" << file_in.tellg();
and it is printing 0|-1 over and over.

Here is an update on the code:


#include<string>

#include<iostream>

#include<fstream>

#include<stdio.h>

#include<vector>

usingnamespace std;

/*functions */

int main(int arg_num, char* args[]){
ifstream file_in;
ofstream file_out;

file_in.open("test.txt");

file_in.open("enc.txt");

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = my_function(mystring);

file_out << mystring;

cout << file_in.eof() << "|" << file_in.tellg();

}

file_in.close();

file_out.close();

file_in.open("enc.txt");

file_out.open("unenc.txt");

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

return 0;

Paul McKenzie
July 6th, 2008, 12:17 AM
I've been using the debugger-- that is what brought up the runtime errors earlier. I tried adding this right after the file_in.open() statement, and it still went throught the loop:
if(!file_in.is_open()){return 0;}
So I asume the file is open, however when I added a cout to the loop, it echo's out blanks in the for statement and nonsense in the rest of the loop.
Instead of trying to read 350 characters, read the whole file into a buffer. Then process 350 characters at a time from the buffer. This is much easier than what you are doing now:

#include<iostream>
#include<fstream>
#include<cstdio>
#include<vector>

using namespace std;

int main()
{
ifstream file_in;
file_in.open("test.txt");

std::vector<char> buffer;
char c;
while(file_in.get(c))
{
buffer.push_back(c);
cout << c;
}
}

What gets outputted? Is it the file contents? If not, work on getting this program to work first.

Once you get it to work, then you have a buffer that has all of the characters. Then you write a additional code to process 350 characters at a time from the buffer, instead of trying to do this processing while reading a file.

Regards,

Paul McKenzie

Duoas
July 6th, 2008, 06:38 AM
You have opened file_in twice (lines 20 and 22). Be careful there.

JasonBB
July 6th, 2008, 08:40 AM
Duoas was right, file_in was opened twice. That got the code kind of working.

Two things now:
1) file2 (the first file_out) has extra characters at the end.
ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýýý««««««««îþîþîþ
I imagine that it is taking all 350 chars from buffer, regardless of whether or not they have a value, and placing it in the string.

2) file3 (the second file_out) is created but empty for some reason.

@Paul McKenzie: I don't think I can do what you suggest, because the file is 100 MB.

JasonBB
July 6th, 2008, 08:52 AM
I think I solved problem 2:

#include<fstream>

#include<stdio.h>

#include<vector>

usingnamespace std;

/*functions */

int main(int arg_num, char* args[]){
ifstream file_in;

ofstream file_out;

file_in.open("test.txt", ios_base::in);

file_out.open("enc.txt", ios_base::out);

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

file_in.open("enc.txt", ios_base::in);

file_out.open("unenc.txt", ios_base::out);

file_in.seekg(0,ios_base::beg);

while(!file_in.eof()) {

for (int i = 0; i < 350; i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = my_function(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

return 0;

}

Paul McKenzie
July 6th, 2008, 08:53 AM
There are logic issues with your code that have nothing to do with syntax.

For example, how do you know that the file size is an exact multiple of 350 bytes?

while(!file1.eof())
{
for (int i = 0; i < 350; i++)
{
buffer[i] = file_in.get();
}
}What if there are only 100 bytes left when you hit that for loop()? You will read an "extra", non-existant 250 bytes. You cannot hardcode 350 in that for loop. The loop must
terminate when the EOF has been reached, or 350 bytes have been read, whichever comes first.

Second, your string is not null-terminated, or you can't assume it's null-terminated. Therefore the proper way to assign to a std::string is using the append() function:

mystring.append(&buffer[0], total_number_of_characters_read_in);

That is more than likely the reason for the extra characters. You're using functions that require NULL terminated strings, and there is no guarantee that buffer is NULL terminated.

Regards,

Paul McKenzie

JasonBB
July 6th, 2008, 09:03 AM
Thanks, Paul. I did this:


#include<fstream>

#include<stdio.h>

#include<vector>

usingnamespace std;

/*functions */

int main(int arg_num, char* args[]){

ifstream file_in;

ofstream file_out;

file_in.open("test.txt", ios_base::in);

file_out.open("enc.txt", ios_base::out);

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

for (int i = 0; i < 350 && !file_in.eof(); i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = e.encrypt(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

file_in.open("enc.txt", ios_base::in);

file_out.open("unenc.txt", ios_base::out);

file_in.seekg(0,ios_base::beg);

while(!file_in.eof()) {

for (int i = 0; i < 350 && !file_in.eof(); i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = e.unencrypt(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();

return 0;
}


But there is still 1 extra char on the end. :confused: I tried to use the append function as well, but that didn't solve it either, so I took it out again.

Paul McKenzie
July 6th, 2008, 09:19 AM
You may just want to keep a counter and increment it for each character read in. Or do this:

while(!file_in.eof())
{
unsigned int totalBytes = 0;
for (int i = 0; i < 350 && !file_in.eof(); i++)
{
buffer[i] = file_in.get();
++totalBytes;
}
//...
mystring.append(&buffer[0], totalBytes);
}

The cout << mystring, should be replaced with cout.write() since you are not writing a NULL terminated string.

cout.write(&buffer[0], totalBytes);

Passing just a std::string to cout using << is not going to work if the string is not NULL terminated.

Also, it's very hard to read your code, since it's not indented, double spaced, and frankly, uses too many colors so it's very difficult to edit. Make it very simple by using the simplest of code tags.

Regards,

Paul McKenzie

JasonBB
July 6th, 2008, 09:27 AM
You may just want to keep a counter and increment it for each character read in. Or do this:

while(!file_in.eof())
{
unsigned int totalBytes = 0;
for (int i = 0; i < 350 && !file_in.eof(); i++)
{
buffer[i] = file_in.get();
++totalBytes;
}
//...
mystring.append(&buffer[0], totalBytes);
}



Ahead of you on that. Tried it and it didn't help. I am getting an extra char on each loop, it seems, so even if it reads in 350 chars, it outputs an extra char.

I am poking around to see if I can find the problem.


The cout << mystring, should be replaced with cout.write() since you are not writing a NULL terminated string.

cout.write(&buffer[0], totalBytes);

Passing just a std::string to cout using << is not going to work if the string is not NULL terminated.


I'll try playing around with that.


Also, it's very hard to read your code, since it's not indented, double spaced, and frankly, uses too many colors so it's very difficult to edit. Make it very simple by using the simplest of code tags.


I agree, but that is what happens when I paste in the code. It removes the indenting and adds some odd colors. It annoys me as well.

JasonBB
July 6th, 2008, 09:34 AM
The cout << mystring, should be replaced with cout.write() since you are not writing a NULL terminated string.


Code:
cout.write(&buffer[0], totalBytes);


Passing just a std::string to cout using << is not going to work if the string is not NULL terminated.



Wait, then how do I modify the string with my function?

Paul McKenzie
July 6th, 2008, 11:08 AM
Ahead of you on that. Tried it and it didn't help. I am getting an extra char on each loopYou need to inspect the data with the debugger and verify if the data is correct, regardless of what you're trying to output. You need to establish what is wrong -- the reading of the data, or the outputing of the data.

Regards,

Paul McKenzie

Paul McKenzie
July 6th, 2008, 11:29 AM
Wait, then how do I modify the string with my function?I think the real problem is that you took code that IMO was written off the top of someone's head and untested, and now trying to get it to work.

Let's start from the beginning:

What does your input file look like? Does it contain carriage-return/line feeds? If so, how do you handle this if you encounter one before you've read in 350 characters?

If you want to handle CR/LF yourself, the file should be opened in binary mode, not text mode -- then you can use the gcount() member function to determine the actual number of characters read in.

The correct way to set up this type of a program is to break it down into functions, and not try to do everything in main(). This way, you have some sort of a plan as to how to write the program.

#include <fstream>
#include <vector>

const int numBytes = 350;

int ReadBytes(std::ifstream& theStream, std::vector<char>& thedata)
{
// reads in 350 (or less bytes) and stores in data
// returns the number of bytes read. If 0, then no bytes
// were read in.
//...
//
}

void ProcessData( std::vector<char>& theData )
{
}

int main()
{
std::vector<char> myBuffer;

std::ifstream instream;
instream.open("whatever.txt");
while (ReadBytes(instream, myBuffer) )
{
ProcessData( myBuffer );
// now process the characters in myBuffer
}
}

Regards,

Paul McKenzie

JasonBB
July 6th, 2008, 01:28 PM
It appears to be the buffer. It reads in all of the character alright, but somehow some extra things are added to it.

If you do this:
cout << buffer[i] << endl;
in the for loop, it looks fine. But, if you do this after the loop for:
cout << &buffer[0] << endl;
You get the string and some extra stuff.

It looks like the stuff gets added on the second go around, as well. The first 350 chars look fine, but the second don't.

JasonBB
July 6th, 2008, 01:32 PM
Sorry, I didn't see your last post. Yes, I agree that I need to set this up better. Give me a few minutes and I'll rework this a bit before we dive in further.

JasonBB
July 6th, 2008, 01:44 PM
Okay, forgive me but this will be a long post. The test.txt file looks like this for now (later on the real file will not have many line breaks-- if any-- and it will be much longer).

Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good.

When I run the code, enc.txt looks like this:
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encrysýýýý««««««««îþîþîþt works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking goodýýýý««««««««îþîþîþ. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encýýýý««««««««îþîþîþryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking gýýýý««««««««îþîþîþood.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if ýýýý««««««««îþîþîþencryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not lookinýýýý««««««««îþîþîþg good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see ýýýý««««««««îþîþîþif encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not loýýýý««««««««îþîþîþoking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to ýýýý««««««««îþîþîþsee if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's noýýýý««««««««îþîþîþt looking good.ÿorks. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good. Hello! this is a test to see if encryst works. So far, it's not looking good.
Hello! this is a test to see if encryst works. So far, it's noýýýý««««««««îþîþîþ


Here is an update on the code so far:

#include <string>

#include <iostream>

#include <fstream>

#include <stdio.h>

#include <vector>

using namespace std;

/* other functions here */
int processFile(char* fin, char* fout, int type = 1){

ifstream file_in;

ofstream file_out;

file_in.open(fin, ios_base::in);

file_out.open(fout, ios_base::out);

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

for (int i = 0; i < 350 && !file_in.eof(); i++) {

buffer[i] = file_in.get();

}

mystring = &buffer[0];

//mystring = my_functio(mystring);

file_out << mystring;

}

file_in.close();

file_out.close();



return 1;

}

int main(int arg_num, char* args[]){



processFile("test.txt","enc.txt");

system("pause");

return 0;
}

Paul McKenzie
July 6th, 2008, 01:54 PM
It appears to be the buffer. It reads in all of the character alright, but somehow some extra things are added to it.

But, if you do this after the loop for:
cout << &buffer[0] << endl;
You get the string and some extra stuff.
Which is why I stated to drop doing this and use cout.write().

The operator << for cout when a char* is encountered expects the data to be null terminated -- your data is not null-terminated.

Regards,

Paul McKenzie

JasonBB
July 6th, 2008, 02:14 PM
I'm sorry. You are correct. I changed that, and now it almost works. It is sooo close. It adds one extra character to the end of the file.

here is the updated function:

int processFile(char* fin, char* fout, int type = 1){

ifstream file_in;

ofstream file_out;

file_in.open(fin, ios_base::in);

file_out.open(fout, ios_base::out);

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

unsignedint x = 0;

for (int i = 0; i < 350 && !file_in.eof(); i++) {

buffer[i] = file_in.get();

++x;

}

mystring = &buffer[0];

//mystring = my_function(mystring);

file_out.write(&buffer[0], x);

}

file_in.close();

file_out.close();



return 1;

}



Also, how do I rework this:
mystring = my_function(mystring);
?

EDIT: What is up with the editor, here? It removes random spaces, like "unsigned int" to "unsignedint" and "#include <iostream>" to "#include<iostream>". :confused:

JasonBB
July 6th, 2008, 02:28 PM
So, I added this:
if(file_in.eof()){x = x-1;}
after the for loop, and it seems to do the trick, but I don't know if that is a good option. What do you think?
I still can't figure out how to implement my_function(), though.

Joeman
July 6th, 2008, 03:45 PM
I wrote a function that should do what you want. I put comments on all lines to help let you understand what is going on.

EDIT:
Fixed errors in code. Thanks to Paul McKenzie for pointing them out and telling me about using vectors with chars :D
I did add more to it aswell.


#include <iostream>
#include <fstream>
#include <vector>

#include <windows.h>

using namespace std;

bool GrabFileData(const string& FilePath, vector<char>& SBuffer){ // my little function{ // my little function

ifstream MyFile( FilePath.c_str(), ios::binary | ios::ate ); // open the file as binary and goto end
if(MyFile.is_open() == false) return false; // looks like the file didn't exist

SBuffer.resize( MyFile.tellg() ); // read our cursor pos which would be the total of characters since we are at the end our file and resize the vector to hold all of the file
MyFile.seekg(0); // goto the beginning
MyFile.read(&SBuffer[0], SBuffer.size()); // read it into the buffer
MyFile.close(); // close the file

return true; // success
}

bool GrabFileData(const string& FilePath, string& SBuffer){ // my little function{ // my little function

vector<char> Data; // to hold our data from file
bool Success = GrabFileData(FilePath, Data); // call the vector type GrabFileData function
SBuffer.assign(Data.begin(), Data.end()); // copy the vector info to the string

return Success; // return if it worked or not
}

int main()
{

string Data; // to hold our data from file
if( GrabFileData( "c:/test.txt", Data) ){ // put context of the file to data

for(unsigned int I = 0; I < Data.length(); I++){ // simple loop on string

cout << Data[I];

}

cout << endl << endl;
cout << "The length of the file in characters is: " << Data.length() << endl;

}else{

cout << "Does that file exist?" << endl;

}

return 0;
}


This code compiles without any errors or warnings for me.

Paul McKenzie
July 6th, 2008, 05:41 PM
1) delete CBuffer; // delete what we created or it will be stuck in
That is the wrong form of delete. Correction:

delete [] CBuffer;

2) Pass things as strings as either references or const references, not by value:

bool GrabFileData(const string& FilePath, string& SBuffer){ // my little function

3) char* CBuffer; // dim a pointer for creation of an array later
Usage of std::vector<char> eliminates the need for new[]/delete[].

std::vector<char> CBuffer;
//...
CBuffer.resize(Length);
MyFile.read(&CBuffer[0], Length); // read it into the buffer
//...
SBuffer.append(&CBuffer[0], Length ); // append the char array to

Although I do recommend you making sure the new operator can create enough room in the memory for the file.Operator new[] throws an exception (std::bad_alloc) if there is no memory. So it is impossible to not check, since the check is done automatically.

Regards,

Paul McKenzie

JasonBB
July 6th, 2008, 06:43 PM
Thanks for the the code, Joeman. I will be taking a closer look at that later to hopefully help me learn more about file I/O. But for now, the code I have is working, I just need to know how to change this:
mystring = my_function(mystring);
so that it works with the code I have. Buffer is the var being read in and written to a file, but I need to pass a string into the function, and the function returns a string. Once I solve that, it should be done :)

Paul McKenzie
July 6th, 2008, 07:49 PM
I just need to know how to change this:
mystring = my_function(mystring);Show us the function.

Regards,

Paul McKenzie

Joeman
July 6th, 2008, 07:57 PM
Thanks Paul McKenzie for clearing some problems up with my code. I edited my post with your corrections and made more adjustments to it. Can you make sure I didn't do anything wrong to it?

JasonBB
July 6th, 2008, 09:46 PM
#include<string>

#include<iostream>

#include<fstream>

#include<stdio.h>

#include<vector>

usingnamespace std;

/* functions */

int processFile(char* fin, char* fout, int type = 1){
ifstream file_in;

ofstream file_out;

file_in.open(fin, ios_base::in);

file_out.open(fout, ios_base::out);

string mystring;

std::vector<char> buffer(350);

while(!file_in.eof()) {

unsigned int x = 0;

for (int i = 0; i < 350 && !file_in.eof(); i++) {

buffer[i] = file_in.get();

++x;

}

mystring = &buffer[0];

if(type == 1){

mystring = my_function(mystring);

}else{

mystring = my_function(mystring);

}

if(file_in.eof()){x = x-1;}

file_out.write(&buffer[0], x);

}

file_in.close();

file_out.close();



return 1;

}

int main(int arg_num, char* args[]){
processFile("test.txt","enc.txt");
system("pause");

return 0;
}

Paul McKenzie
July 6th, 2008, 11:07 PM
You didn't post the my_function() function.

Regards,

Paul McKenzie

JasonBB
July 7th, 2008, 12:23 PM
I can't for security reasons (the software is for website security). Basically, though, it's:

string my_function(string mystring){

//changes
//send to another function
//changes
//send to yet another function

return mystring;
}

That's really all I can show you. Basically, I just need to put the string back into the buffer, if that's possible.

laserlight
July 7th, 2008, 01:12 PM
I can't for security reasons (the software is for website security).
However, if the security depends on the secrecy of the algorithm rather than on the secrecy of the key, perhaps it is broken to begin with.

JasonBB
July 7th, 2008, 07:13 PM
Point taken, but I would rather protect both.

JasonBB
July 8th, 2008, 07:24 PM
. . . Anyone?

VladimirF
July 8th, 2008, 07:55 PM
. . . Anyone?What's the question now? How to copy a string to a buffer?
Basically, I just need to put the string back into the buffer, if that's possible.Is that it?

JasonBB
July 8th, 2008, 09:12 PM
Basically, in this line:

file_out.write(&buffer[0], x);

I need to use a string instead of the vector<char>, somehow, but the function cannot take a string. i.e. If you look at the code posted on the previous page, I need a way to do this:

file_out.write(mystring, x);
I was thinking perhaps there was a way to put the string back into the buffer variable, but I don't know.

Philip Nicoletti
July 8th, 2008, 10:15 PM
write() takes a const char * as the first parameter ... use std::c_str()
member function:


file_out.write(mystring.c_str(), x);

JasonBB
July 10th, 2008, 10:08 AM
I truly thank you guys for helping me out on this. The function seem to be working great-- I am just making some small tweaks to the code to make it fit in better with the rest of the program.

Once again, thank you.