Need help converting c to C ++ (simple error, but not fix)

I have a C ++ homework. Homework asks to convert a c-program to C ++. Below is the question:

You are asked to convert the next C function to C ++ and then embed it in a full program and test it. Note that this function copies the binary file of integers, not the text file. The program should accept the arguments (the file to copy and the file to be copied) from the command line.

/* ==================== cpyFile ===================== This function copies the contents of a binary file of integers to a second file. Pre fp1 is file pointer to open read file fp2 is file pointer to open write file Post file copied Return 1 is successful or zero if error */ int cpyFile (FILE *fp1, FILE *fp2) { /* Local Definitions */ int data; /* Statements */ fseek (fp1, 0, SEEK_END); if (!ftell (fp1)) { printf ("\n\acpyFile Error : file empty\n\n"); return 0; } /* if open error */ if (fseek (fp1, 0, SEEK_SET)) return 0; if (fseek (fp2, 0, SEEK_SET)) return 0; while (fread (&data, sizeof (int), 1, fp1)) fwrite (&data, sizeof (int), 1, fp2); return 1; } /* cpyFile */ 

I did my best and managed to convert it, but, unfortunately, when I use it, the file that I get after the copy is empty. Below is my answer:

 #include <fstream> #include <cstdlib> #include <iostream> using namespace std; int main(int argc,char* argv[]) { if(argc!=3) {cerr<<"invalid number of arguments. must be 3."<<endl;exit(1);} fstream fp1(argv[1],ios::in); if(!fp1)+{cerr<<argv[1]<<" could not be opened"<<endl;exit(1);} fstream fp2(argv[2],ios::out); if(!fp2)+{cerr<<"file could not be found."<<endl;exit(1);} int data; fp1.seekg (0,ios::end); if (!fp1.tellg ()) { cout<<"\n\acpyFile Error : file empty\n\n"; return 0; } /* if open error */ if (fp1.seekg (0, ios::beg)) return 0; if (fp2.seekg (0, ios::beg)) return 0; while (fp1.read (reinterpret_cast<char*>(&data), sizeof (int))) { fp2.seekp(0); fp2.write (reinterpret_cast<char*>(&data), sizeof (int)); } return 1; } 

I did my best and everything works fine, except that when I copy the binary, the file I get is empty and I have no idea why.

+7
source share
5 answers

You need to open the file in binary mode, as others have said, by doing

 fstream fp1(argv[1], ios::in | ios::binary); // combine ios::in with ios::binary fstream fp2(argv[2], ios::out | ios::binary); // combine ios::out with ios::binary 

Or you can make them ifstream (read-only file stream) and ofstream (file stream, write-only) and remove ios::in and ios::out , because ifstream implies ios::in and ofstream means ios::out :

 ifstream fp1(argv[1], ios::binary); ofstream fp2(argv[2], ios::binary); 

You need to do this because if you do not, the file will be translated when you read or write for it, for example, trim line endings from \r\n or \r only \n , etc. which will corrupt your binary data, which these bytes can have in them.

It:

 if (fp1.seekg (0, ios::beg)) return 0; if (fp2.seekg (0, ios::beg)) return 0; 

It always returns code, because seekg returns the object you call it on. This is not the equivalent of fseek in this regard, because fseek returns 0 on success. Therefore, you never end up in a while . Derive them from if so that they look like this:

 fp1.seekg(0, ios::beg); fp2.seekg(0, ios::beg); 

Or, if you have a check, you want to do

 if (!fp1.seekg (0, ios::beg)) // notice the added ! return 0; if (!fp2.seekg (0, ios::beg)) // notice the added ! return 0; 

In addition, this (inside while ):

 fp2.seekp(0); 

Sets the point at which you are going to write to the beginning of the file. Therefore, you will never write anything except the beginning of the file. Just delete this line completely.

In addition, inside the loop there is return , which returns it to the first iteration. Move return 1; outside the loop, so that you will only return after the loop ends. Disregard this, incorrectly due to the unusual style of the brackets.

+7
source

Each time you read a new block of data from fp1 , you rewind fp2 to the beginning of the stream, substantially discarding what is already written in fp2 . Try moving fp2.seekp(0) from the main loop.

+1
source

You have a few problems. I would start by fixing this bit:

 if (fp1.seekg (0, ios::beg)) return 0; if (fp2.seekg (0, ios::beg)) return 0; 

The seekg method returns a reference to the called istream , so the above is equivalent to this:

 fp1.seekg (0, ios::beg); if (fp1) // ie, if fp1 is in a valid state (as opposed to eg end-of-file) return 0; fp2.seekg (0, ios::beg); if (fp2) // ie, if fp2 is in a valid state (as opposed to eg end-of-file) return 0; 

which is clearly not what you want.

To debug your code, you can use expressions such as std::cout << "Got to line " << __LINE__ << std::endl; to find out which parts of the program are actually running. This would find this problem pretty quickly.

+1
source

Binary files must be opened specifically in binary mode, so when you have fstream fp1(argv[1],ios::in); , you must also add the ios binary to it: fstream fp1(argv[1], ios::in | ios::binary);

0
source

In C ++ code, you are looking for the beginning of the output file before writing each number, and therefore the output file will have a length of no more than 2 bytes.

0
source

All Articles