我有一个c ++作业。作业要求将c程序转换为c ++。 以下是问题:
您需要将以下C函数转换为C ++ 功能,然后将其嵌入一个完整的程序并测试它。注意 该函数复制整数的二进制文件而不是文本 文件。程序必须接受参数(要复制的文件和 要从命令行复制到的文件。
/* ==================== 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 */
我尽了最大努力并设法转换它,但不幸的是,当我使用它时,我在复制后得到的文件是空的。以下是我的回答:
#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;
}
我尽了最大努力,一切正常,但是当我复制二进制文件时,我得到的文件是空的,我不知道为什么。
答案 0 :(得分:7)
正如其他人所说,你需要以二进制模式打开文件
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
或者您可以将它们ifstream
(文件流中的 仅供阅读使用)和ofstream
(输出文件流,仅供写入)并删除ios::in
和ios::out
,因为ifstream
隐含ios::in
而ofstream
隐含ios::out
:
ifstream fp1(argv[1], ios::binary);
ofstream fp2(argv[2], ios::binary);
您需要执行此操作,因为如果您不这样做,则在您阅读或写入文件时会翻译该文件,例如将行结尾从\r\n
或\r
转换为{{{ 1}}等,这会弄乱你的二进制数据,这些数据可能碰巧有这些字节。
此:
\n
将永远使代码返回,因为if (fp1.seekg (0, ios::beg))
return 0;
if (fp2.seekg (0, ios::beg))
return 0;
返回您调用它的对象。在这方面,它不等同于seekg
因为fseek
在成功时返回0。所以你永远不会进入fseek
循环。从while
语句中取出它们,使它看起来像这样:
if
或者如果你必须进行检查,你想做
fp1.seekg(0, ios::beg);
fp2.seekg(0, ios::beg);
此外,这(在if (!fp1.seekg (0, ios::beg)) // notice the added !
return 0;
if (!fp2.seekg (0, ios::beg)) // notice the added !
return 0;
内):
while
将要写入的点设置到文件的开头。因此,除了文件的开头,你永远不会写任何东西。只需完全删除该行。
此外,循环内部有一个没关系,因为不寻常的支撑样式而误读。fp2.seekp(0);
,使其在第一次迭代时返回。将return
移到循环外部,这样您只能在循环结束后返回。
答案 1 :(得分:1)
每当您从fp1
读取新数据块时,您都会将fp2
快退到流的开头,实质上会丢弃您已写入fp2
的内容。尝试将fp2.seekp(0)
移出主循环。
答案 2 :(得分:1)
你有一些问题。我首先要解决这个问题:
if (fp1.seekg (0, ios::beg))
return 0;
if (fp2.seekg (0, ios::beg))
return 0;
seekg
方法返回对其调用的istream
的引用,因此上述内容与此相同:
fp1.seekg (0, ios::beg);
if (fp1) // i.e., if fp1 is in a valid state (as opposed to e.g. end-of-file)
return 0;
fp2.seekg (0, ios::beg);
if (fp2) // i.e., if fp2 is in a valid state (as opposed to e.g. end-of-file)
return 0;
这显然不是你想要的。
要调试代码,可以使用std::cout << "Got to line " << __LINE__ << std::endl;
之类的语句来确定程序的哪些部分实际运行。那很快就会发现上述问题。
答案 3 :(得分:0)
二进制文件需要在二进制模式下专门打开,所以如果你有fstream fp1(argv[1],ios::in);
,你也应该像这样添加一个ios :: binary:fstream fp1(argv[1], ios::in | ios::binary);
答案 4 :(得分:0)
在C ++代码中,在写入每个数字之前,您正在寻找输出文件的开头,因此输出文件最多只能有2个字节。