所以我无法理解 C++ 中的文件 [英] So I'm having trouble understanding files in C++

查看:25
本文介绍了所以我无法理解 C++ 中的文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚开始学习文件,我了解如何设置它并使其工作.我必须编写这个程序,我必须允许用户输入一些信息,并让用户使用二进制更新和调整任何数据.所以我可以一直写到用户可以读写文件的地方.但是我不知道如何让用户调整数据或添加数据.

I just started learning files and I understand how to set it up and get it to work. I have to write this program where I have to allow the user to enter some information and have the user also update and adjust any data, using binary. So I can write up until the point where the user can write to and read from the file. But I don't know how to let the user adjust data or add data.

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

class client {
public:
  string name;
  int balance;
  string id;

};

int main()
{
   int ans;
   int x;
   string nameIn;
   string adjName;
   client client1;
   ofstream out("client1.dat", ios::binary);

   cout << "\nDo you want to add information or update info" << endl;
   cin >> ans;
   if (ans == 1)
   {
     cout << "\nPlease enter the name of your client" << endl;
     cin >> nameIn;
     x = nameIn.length();
     if (x <= 10)
    {
        for (int i; i < 10; i++)
        {
            adjName[i] = nameIn[i];
        }
    }
    else
    {

        for (int i = x; i < 10; i++)
        {
            adjName[i] = ' ';
        }
    }
    client1.name = adjName;
    cout << "\nPlease enter the balance of your client" << endl;
    cin >> client1.balance;
    cout << "\nPlease enter the id of your client" << endl;
    cin >> client1.id;

    cout << "\nThe name of your client is " << endl << client1.name
        << endl << "\nThe balance of your client is " << endl
        << client1.balance << endl << "\nThe id of your client is "
        << endl << client1.id;

    out.write(reinterpret_cast<const char*> (&client1), sizeof(client));

}
/*

else if (ans == 2)
{
    string answer, newName,line;
    cout << "\nWhat name do you want to update? " << endl;
    cin >> answer;
    cout << "\nWhat is the new name?" << endl;
    cin >> newName;

    if (out)


}
*/
system("pause");
return 0;

}

所以名字只需要10个字符长,这样我们就可以调整/更新它.它编译并运行,但每次编译器到达检查名称长度的部分时,它都会吓坏并说调试断言失败"字符串下标超出范围.

so the name needs to be only 10 characters long, so that we can adjust/update it. It compiles and runs, but every time the compiler gets to the part where it checks the name length, it freaks out and says "debug assertion failed" string subscript out of range.

还有一个关于这段代码的事情——如果我在没有将名称调整为特定数组长度的位的情况下运行它,程序就会运行,并很好地存储所有内容.但是当我尝试读回 .dat 时,它会读回它但退出时出现访问冲突,迫使我手动停止调试.我做错了什么?

Also a thing about this code-- if i run it without the bits where you adjust the name to a certain array length, the program runs, and stores everything nicely. But when I try to read back the .dat, it reads it back but exits with an access violation, forcing me to manually stop the debugging. What am I doing wrong?

这是读取文件的代码

#include <iostream>
#include <fstream>
#include <string>
using namespace std;
class client {
public:
 string name;
 int balance;
 string id;
};

int main()
{
  client client1;
  char ans;
  cout << "\nDo you want to view the information about your client?"
     << endl;
  cin >> ans;
  ifstream in("client1.dat", ios::binary);

  if (ans == 'y' || ans == 'Y')
  {
      in.read(reinterpret_cast<char*> (&client1), sizeof(client));
      cout << "The name is " << endl << client1.name << endl
          << "The balance is " << endl << client1.balance << endl
          << "The id is " << endl << client1.id << endl;
 }
   system("pause");
   return 0;
 }

推荐答案

至于第一部分:

 for (int i; i < 10; i++)
       // ^

未将 i 初始化为零.如果输入小于 10 个字符怎么办?您将越界访问 std::string.你应该用简单的

misses to initialize i to zero. Also what if the input was smaller than 10 characters? You're going to access the std::string out of bounds. You should replace the if/else and loops with simply

 adjName = nameIn;
 while(adjName.length() <= 10) {
     adjName += ' ';
 }

摆脱调试断言.

对于问题的第二部分,正如评论中已经提到的,您不能使用包含 std::string 之类的类的结构来做到这一点.

For the 2nd part of the question, as already mentioned in the comments you cannot do this with a structure containing classes like std::string.

reinterpret_cast(&client1) 只是混淆了 std::string 在内部使用指向动态分配的字符数据的指针,并且在稍后读回存储的数据时无法有意义地恢复(因此你得到的访问冲突).

The reinterpret_cast<char*> (&client1) just obfuscates that std::string uses a pointer to the dynamically allocated character data internally, and that cannot be restored meaningfully when reading the stored data back later (hence the access violation you get).

一种可行的方法可能是使用类似的东西

A viable way might be to use something like

struct client {
    char name[11];
    int balance;
    char id[5];
};

我猜你需要在家庭作业练习中这样做,为此目的,这可能就足够了.

As I guess you need to do this for a homework exercise, and for this purpose that would probably be sufficient.

但是您很快就会发现缺点,即字符数据需要固定大小并且不能具有任意长度的字符串.我永远不会将这样的代码用于生产就绪代码.

But you quickly can see the drawbacks, that the character data needs to be fixed in size and you cannot have arbitrary length strings. I never would use such for production ready code.

另一个陷阱(也提到过)是,对于不同的 CPU 架构,int 没有以相同的方式表示(使用的字节顺序,即字节序).所以二进制文件不能在不同的电脑上移植使用.

Another pitfall (as also mentioned) is, that int isn't represented in the same way (order of bytes used, i.e. endianess) in the same way for different CPU architectures. So the binary file can't be used portably with different computers.

最简单的解决方案是不使用二进制文件,而是使用文本格式的文件并重载std::ostream&运算符<<(std::ostream&, const client&)std::istream&运算符>>(std::istream&, client&) 输出/输入运算符.

The simplest solution is not to use a binary file, but a text formatted file and overload the std::ostream& operator<<(std::ostream&, const client&) and std::istream& operator>>(std::istream&, client&) output/input operators.

或者使用一些 3rd 方库,如 boost::serialization 或 google protocol buffers,它们支持二进制文件的反/序列化.

Or use some 3rd party library like boost::serialization or google protocol buffers, that supports de-/serialization to binary files.

这篇关于所以我无法理解 C++ 中的文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆