首页  >  问答  >  正文

visual-studio - 关于c++文件流读取和写入string类出错的问题,求解答

在用vs2015编程学习文件流时出现问题,就是以二进制app方式写入和读取string类型时出现问题,只有第一次输入可以显示,之后增加字符串在此读取输出就会报错,求大神指点

以下是代码:

#include <string>
#include <iostream>
#include<iomanip>
#include<fstream>
using namespace std;
int main()
{
    ofstream outfile("try.dat", ios::app | ios::binary);
    string a;
    cin >> a;
    outfile.write((char*)&a, sizeof(a));

    ifstream infile("try.dat", ios::in | ios::binary);
    if (!infile)
    {
        cout << "weew";
    }
    
    infile.read((char*)&a, sizeof(a));
    
    outfile.close();
    infile.close();
    cout << a << endl;
    return 0;
}

以下是第一次运行情况,是正确的

接下来关闭后重新运行再次输入,会出现错误:

初学者不太明白这是为什么,第一次提问,求大神指点,先谢谢各位啦!

巴扎黑巴扎黑2765 天前626

全部回复(3)我来回复

  • 怪我咯

    怪我咯2017-04-17 14:25:23

    首先要明白,string不是一个简单的数组类型,它是一个类,拥有自己的成员变量和成员函数

    而a是string类型的,故a是一个复杂的对象,执行&a来取得a的地址并没有什么意义,将其强转为char*类型更是说不通,把一个string*强转为char*,是一个指针到指针的转换,指针的值并未改变,只是告诉了编译器一声:同样是这个指针,现在别把我当string*看待了,要当我是char*(这有卵用啊……)

    感觉题主的本意是想把一个string转化为传统的C字符串(就是一个char数组),那么请使用a.c_str()来获取真正的char*(这个是string内部构造好的,而非像题主那样胡乱强转出来的);此外,使用a.len()可以获得这个字符串的长度。

    顺便一提,如果题主实在无法理解为什么sizeof(a)不是字符串的长度,可以看看如下的仿例(我生造出来的):

    class myString{
    private:
        int len_string;
        char *str;
    public:
        myString(char* s){
            len_string=strlen(s);
            str=new char[len_string];
            strcpy(str,s);
        }
        int len(){return len_string;}
        char* c_str(){return str;}
    };
    myString a="12345678901234567890";

    可以看到,sizeof(a)永远都是len_string的长度+str的长度=8字节,并不会变成20字节,所谓的字符串长度动态变化,是通过new以及一个记录长度的变量len_string来实现的。

    回复
    0
  • 高洛峰

    高洛峰2017-04-17 14:25:23

    1、string的实现在各库中有所不同,但是在同一库中相同一点是,无论你的string里放多长的字符串,它的sizeof()都是固定的,字符串所占的空间是从堆中动态分配的,与sizeof()无关。
    so, write 和 read 的第二个参数传的都是错误的。
    2、第二运行出错,是在析构string时出的错
    3、read 那里如果你换一个buffer 来接收,应该是没有数据的, 你可以试试, 也就是说, 你的read出来的a实际上还是原来的a

    回复
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-17 14:25:23

    获取string的C风格的地址要c_str()成员才行,长度是string.len

    回复
    0
  • 取消回复