关于 c :fprintf、字符串和向量

fprintf, strings and vectors

本问题已经有最佳答案,请猛点这里访问。

Possible Duplicate:
c++ - printf on strings prints gibberish

我想将几个字符串写入文件。字符串是

1
2
3
4
5
6
37 1 0 0 0 0
15 1 0 0 0 0
33 1 0 0 0 0
29 1 0 0 0 0
18 1 0 0 0 0
25 1 0 0 0 0

我首先想将每一行存储为字符串数组的元素,然后调用相同的字符串数组并将其元素写入文件。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <stdio.h>
#include <vector>
#include <string>
using namespace std;

int writeFile() {

  char line[100];
  char* fname_r ="someFile_r.txt"
  char* fname_w ="someFile_w.txt";
  vector<string> vec;

  FILE fp_r = fopen(fname_r,"r");
  if(fgets(line, 256,fp_r) != NULL)   {
     vec.push_back(line);
  }

  FILE fp_w = fopen(fname_w,"w");
  for(int j = 0; j< vec.size(); j++) {
    fprintf(fp_w,"%s", vec[j]); // What did I miss? I get funny symbols here. I am expecting an ASCII
  }

  fclose(fp_w);
  fclose(fp_r);
  return 0;
}


格式说明符 "%s" 需要一个 C 风格的以空字符结尾的字符串,而不是 std::string。更改为:

1
fprintf(fp_w,"%s", vec[j].c_str());

因为这是 C ,您应该考虑使用 ofstream 代替它是类型安全的并接受 std::string 作为输入:

1
2
3
4
5
6
7
std::ofstream out(fname_w);
if (out.is_open())
{
    // There are several other ways to code this loop.
    for(int j = 0; j< vec.size(); j++)
        out << vec[j];
}

同样,使用 ifstream 作为输入。发布的代码有潜在的缓冲区溢出:

1
2
3
char line[100];
...
if(fgets(line, 256,fp_r) != NULL)

line 最多可以存储 100 个字符,但 fgets() 声明它可以容纳 256。使用 std::getline() 可以消除这种潜在的危险,因为它会填充 std::string:

1
2
3
std::ifstream in(fname_r);
std::string line;
while (std::getline(in, line)) vec.push_back(line);


在这种情况下 vec[j] 是 std::string 对象。但是 fprintfs 需要 c 风格的空终止字符串。

1
2
3
for(int j = 0; j< vec.size(); j++) {
    fprintf(fp_w,"%s", vec[j]);
}

你只需要从 std::string 获取指向 c 风格字符串的指针。可以使用 c_str 方法:

1
2
3
for(int j = 0; j< vec.size(); j++) {
    fprintf(fp_w,"%s", vec[j].c_str());
}

在任何情况下,您都混合了 C 和 C 代码。它很丑。使用 std::fstream 更好。