向量返回分段错误的Fwrite和Fread

时间:2013-08-02 10:48:26

标签: c++ vector fwrite fread

我用c ++编写代码,用于加密和解密。第一个代码在向量中创建一个输出,然后使用fwrite将其写入文件,第二个代码通过使用fread从第一个代码读取输出。 以下是我的代码片段:

第一个代码:

.....
string a;
vector<long long int> c;

cout << "message to be encrypted = ";
cin >> a;   
cout << endl;

cout << "Encrypted message : ";
for (i=0;i<a.size();i++) 
{
    x=(int)a.at(i);
    cout << x << " ";
    c.push_back(powerMod(x,e,n));
}

for (i=0;i<c.size();i++) 
{
    //cout << char(c.at(i));
}
cout << endl;

//Write ciphertext c to a file
FILE * pWrite;
pWrite = fopen ("ciphertext", "w");
fwrite (&c , sizeof(c), 1, pWrite);
fclose (pWrite);

输出结果为:

message to be encrypted = test
Encrypted message : 116 101 115 116 

然后是第二个代码:

....
//Read Ciphertext from ciphertext
FILE * pRead2;
pRead2 = fopen ("ciphertext", "r");
fread (&c , sizeof(c), 1, pRead2);
//cout << "ciphertext is " << c << endl;

// Decryption
cout << "Decrypted message : ";
for (i=0;i<c.size();i++) 
{
    cout << powerMod(c.at(i),d,n) << " " ;
}
cout << endl;

但它回归:

Segmentation Fault(Core Dumped)

我感谢任何帮助,因为我不知道问题在哪里,在fwrite或fread中。但我认为问题是在第二次,当它试图读取密文(这是一个向量)时,因为如果我擦除那些行,程序运行完美,但没有解密消息。

感谢。

1 个答案:

答案 0 :(得分:5)

这是因为您编写了一个指向矢量对象实例的指针,而不是实际的矢量数据。使用

fwrite (&c[0], sizeof(vector<long long int>::value_type), c.size(), pWrite);

还要记住sizeof(c)返回矢量对象实例的大小,而不是矢量中的项目数。

阅读矢量时遇到类似的问题。你必须在一个循环中逐个进行,再次将项目推送到向量。


如果您学习使用C++ I/O stream library和一些不错的standard algorithms并使用iterators,那么使用C ++可以采用更简单的方法。

将矢量写入文件:

std::ofstream os{"ciphertext", std::ios::out};

std::copy(std::begin(c), std::end(c),
          std::ostream_iterator<long long int>(os));

并从文件中读取:

std::ifstream is{"ciphertext", std::ios::in};

std::copy(std::istream_iterator<long long int>(is),
          std::istream_iterator<long long int>(),
          std::back_inserter(c));

实际上有一种甚至更简单的方式从文件读取到矢量:

std::ifstream is{"ciphertext", std::ios::in};

std::vector<long long int> c(std::istream_iterator<long long int>(is),
                             std::istream_iterator<long long int>());

这依赖于std::vector constructor将两个迭代器作为参数。


如果您不想使用文本文件,但是不想使用二进制文件,那么您不得不手动循环并写入/读取数据,即您必须手动执行std::copy为您执行的操作。

写这样的数据:

std::ofstream os{"ciphertext", std::ios::out | std::ios::binary};

for (const auto& value : c)
    os.write(reinterpret_cast<const char*>(&value), sizeof(value));

像这样读它:

std::ifstream is{"ciphertext", std::ios::in | std::ios::binary};

long long int value:
while (is.read(reinterpret_cast<char*>(&value), sizeof(value)))
    c.push_back(value);

如果您没有C ++ 11 range-based for loop(在上面的写作示例中使用),请使用正常的经典迭代for循环:

std::vector<long long int>::const_iterator i;
for (i = c.begin(); i != c.end(); ++i)
    os.write(reinterpret_cast<const char*>(&(*i)), sizeof(*i));