1

我是这门语言的初学者,我遇到了这个问题。在网上搜索后,它似乎与内存分配,指针等有关。我不太明白......这里我试图通过类将数据添加到二进制文件......所以我想问可能是什么问题-->

void addques()
{
    question abc;
    ofstream fout;
    fout.open("question.txt",ios::app|ios::binary);
    cout<<"Enter Question!\n";
    gets(abc.ques);
    cout<<"Enter Options!\n";
    gets(abc.option1);gets(abc.option2);gets(abc.option3);gets(abc.option4);
    cout<<"Enter correct option number\n";
    cin>>abc.k;
    cout<<"Enter question nummber"; cin>>abc.quesno;
    fout.write((char*)&abc,sizeof(abc));
    fout.close();
    cout<<"File closed";
}

似乎所有具有 ifstream/ofstream 类对象的函数都显示此错误。最后一行“文件已关闭”也正在执行,然后出现错误。会不会是这条线fout.write((char*)&abc,sizeof(abc))—— ???请帮助

这是相关的类-->

class question
{   public:
    char ques[80];
    char option1[50], option2[50], option3[50], option4[50];
    char k;
    char quesno;
};

对于整个程序,我在此处粘贴了我的代码 http://pastebin.com/S7KNby0E 请查看它...因为我无法在这里这样做

4

2 回答 2

2

您输入的问题或答案对您的某个缓冲区来说太长了吗?我敢打赌你是,它超出了班级的界限并破坏了堆栈。此外,混合 cin 和 cout 以及像 gets 这样的 C 风格的 IO 函数是自找麻烦,所以不要。

由于您使用的是 C++,因此您不必将字符串操作作为字符数组进行。有一个 STL 类可以为您处理所有的内存垃圾。我会用以下方式重写你的课程:

class Question
{   public:
    string ques;
    string option1, option2, option3, option4;
    char k;
    char quesno;

    void write(fstream& f)
    {
        f << ques.length() << " " << ques << endl
          << option1.length() << " " << option1 << endl
          << option2.length() << " " << option2 << endl
          << option3.length() << " " << option3 << endl
          << option4.length() << " " << option4 << endl
          << k << " " << quesno << endl;
    }
};

以及您的功能如下:

void addques()
{
    Question abc;
    ofstream fout;
    fout.open("question.txt", ios::app);

    cout << "Enter Question!" << endl;
    getline (cin, abc.ques);

    cout << "Enter Options!\n";
    getline(cin, abc.option1);
    getline(cin, abc.option2);
    getline(cin, abc.option3);
    getline(cin, abc.option4);

    cout << "Enter correct option number: ";
    cin >> abc.k;

    cout << "Enter question number: ";
    cin >> abc.quesno;

    // you will have to change your writing method a bit because you can't just write the string object straight to disk like you were before

    abc.write(fout);
    fout.close();
}

然后,您应该能够以或多或少与 write 相同的方式使用提取运算符将其读入流中。

Ascii 转二进制

由于您必须使用二进制,您可以通过以下方式将整数值存储为二进制值:

int i = ques.length();
fout.write((const char *) &i, sizeof(i));

这会将 32 位整数值直接写入流,而无需先将其转换为字符串。然后,您的字符串将具有以下格式:

+     0x0     0x1     0x2     0x3     0x4     0x5     0x6     0x7     
0x0  [0x00    0x00    0x00    0xC0  ][H       E       L       L
0x8   O       <space> W       O       R       L       D       <null> ]

长度是前 4 个字节,此处显示为 0x0000000C(整数值 12)。该字符串紧随其后,其值为“HELLO WORLD\0”。\0 是空终止符。在我的示例中,此长度包括空终止符。

大小

Sizeof 是一个运算符,它在编译器可以确定的情况下尽可能生成指定类型的内存大小。对于整数类型,例如 int、short、char 等,它将返回该类型使用的字节数。对于数组,您可能会遇到令人困惑的行为。如果在静态声明为固定大小的数组上调用,sizeof 将返回数组的长度 * 一个元素的大小。

int derp[1000];
sizeof(derp); // sizeof(int) * 1000

如果编译器不知道数组有多大,您将得到的是指向第一个元素的指针的大小。所以要小心。您不能在指针上使用 sizeof 来确定数组大小。

int derp2[];
sizeof(derp2); // sizeof(int *), probably 4 or 8
int * derp3 = derp;
sizeof(derp3); // sizeof(int *), probably 4 or 8

要获取 std::string(STL 字符串类)的长度,请使用 length 成员:

string hurr = "hello world";
hurr.length(); // does NOT include the null terminator
               // length of string AND terminator is hurr.length() + 1
于 2012-08-03T18:54:15.627 回答
1

有一个明显的问题,还有许多潜在的问题。您的症状表明一个值被写入了它不应该存在的内存中(缓冲区溢出、浮动指针等)。

关注点

  1. 不要将 C++ 标准流 I/O(std::cout、std:cerr、std:cin、std::ofstream 和许多其他元素)与 C 风格的标准 I/O(gets)混合。选择一个 I/O 库,并坚持下去。

  2. 检查并验证您对边界条件的假设。在这种情况下,您的边界是输入字符数组的大小question。您的输入数据是否接近/接近数组大小(您定义的限制)?您是否在每个 char 数组的末尾为额外的终止 NULL (0) 字符留出了空间?

  3. 预初始化您将要使用的所有内容。您的question构造函数可以做些什么来确保新的中性“空数据”存在question

策略 - 隔离问题

  1. 注释掉整个函数体(所有语句),将函数留空。运行并验证它是否有效 - 这将确定问题是在身体上还是在其他地方。

  2. 开始重新添加位。准确确定触发问题的语句。对于访问违规,人们担心这种类型的代码分类可能无法揭示真正的罪魁祸首。

除了:缓冲区溢出、浮动指针等可能在问题发生后随时随地导致问题。世界上所有的问题隔离可能无法确定问题的根源。您将培养识别常见问题的技能。以上几点旨在成为帮助您发展这些技能的一些入门指南。

风格

  1. 将每个变量声明为尽可能接近它在代码中的首次使用点。考虑将声明fout向下移动。
于 2012-08-03T18:36:44.237 回答