【问题标题】:C++ reading/writing binary modeC++读/写二进制模式
【发布时间】:2013-03-17 09:57:45
【问题描述】:

我在学校学习 C++,在我看来它是一门漂亮的语言,但我遇到了这个烦人的问题。课本上写的是FILE *textscanfprintf,个人不太喜欢;我习惯了cincout<< >> 更好地使用fstream

所以这是我的问题:

  1. 我必须制作一个以二进制模式写入数据的应用程序(我已经完成了一半,但由于某种原因它没有以二进制模式写入)

  2. 在我写下城市 (orasul) 的坐标 (x 和 y) 后,我必须搜索它们并获取这些值。 (这里我尝试使用string.find)但我必须使用seekg 以“二进制模式”进行搜索并将这些值在结构中分开。

如果你们能以某种方式指导我,因为我在这里很迷茫。有没有办法我可以得到 sizeof(struct)

#include <iostream>
#include <conio.h>
#include <fstream>
#include <string>
#include <limits>

using namespace std;

struct oras {
    std::string orasul;
    int x;
    int y;
} ora;


void functiaPrincipala();
void calculator(float coordonate_x1, float coordonate_y1, float coordonate_x2, float coordonate_y2);
void adaugaOras();
void stergeLocatie();
void repetare();

void main() {
    functiaPrincipala();
}

void functiaPrincipala() {
    // variabile
    int obtiune;
    // ofstream fisierOut;
    // ifstream fisierIn;


    cout << "1) Adauga localitate: " << endl;
    cout << "2) Stergerea unei localitati existente: " << endl;
    cout << "3) Stergerea tuturor localitatilor existente: " << endl;
    cout << "4) Afisarea tuturor localitatilor existente: " << endl;
    cout << "5) Calculul distantei a doua localitati: " << endl;
    cout << "Introduceti obtiunea: " << endl;
    cin >> obtiune;

    switch (obtiune) {
        case 1:
            adaugaOras();
            break;
        case 2:
            stergeLocatie();
            break;
        case 3:
            break;
        case 4:
            break;
        case 5:
            break;
    }

    getch();
}

void calculator(float coordonate_x1, float coordonate_y1, float coordonate_x2, float coordonate_y2) {
    float rezultat;


    rezultat = sqrt((coordonate_x2 * coordonate_x1) - (coordonate_x2 * coordonate_x1) + (coordonate_y2 * coordonate_y1) - (coordonate_y2 * coordonate_y1));

    cout << "Distanta de la orasul 1 la orasul 2 este de: " << rezultat;

}

void adaugaOras() {
    int n;
    ofstream fisierOutt("textttt.txt", ios::app | ios::binary);

    //  fisierOutt.open("textttt.txt");
    cout << "Cate orase doresti sa introduci: ";
    cin >> n;
    if (fisierOutt.is_open()) {

        for (int i = 0; i < n; i++) {
            cout << "Introdu numele orasului: ";
            cin >> ora.orasul;
            cout << "Introdu coordonatele x: ";
            cin >> ora.x;
            cout << "Introdu coordonatele y: ";
            cin >> ora.y;
            fisierOutt << ora.orasul << " " << ora.x << " " << ora.y << endl;
            cout << endl << endl;




        }

    } else {
        cout << "Nu am putut deschide fisierul";
    }
    fisierOutt.close();
    cout << endl;
    // repetare();
}

void stergeLocatie() {

}

void repetare() {
    char obtiune;
    cout << "Doriti sa mai adaugati ceva sau sa iesiti?(d/n)";
    cin >> obtiune;
    if (obtiune == 'd') {
        functiaPrincipala();
    } else {
        exit;
    }
}

【问题讨论】:

  • 您不能轻易找到特定的条目,因为这些条目的大小是可变的。如果文件中的所有条目都具有固定大小,那将很容易。
  • "P.S 有没有一种方法可以让我更轻松地输入代码,然后按空格键四次?"是的,只需将其粘贴进去,选择它,然后单击{} 按钮。
  • 非常感谢您的帮助。老师告诉我有一种方法可以让我得到结构体的大小(sizeof(ora),然后我用 seekg 找到它......但问题是我不会写它
  • 首先你不应该在二进制模式下写空格(这是没用的,你必须在阅读时考虑它们)。其次,您应该先写字符串的大小,然后再写字符串。这是必需的,因为字符串具有可变长度,当您读回它们时,您应该知道何时停止以及 x、y 何时开始(具有恒定长度)。 Si salutari de la un concetatian :D
  • 您无法将结构写入磁盘,因为它包含std::string。要么在写入之前必须将其 marshall 到另一个结构,要么将字符串存储为固定大小的 char 数组。

标签: c++ struct binary seekg


【解决方案1】:

就像我在评论中所说的那样,您不能真正寻找特定的条目,因为所有条目的大小都不同。

这可以通过拥有一个单独的索引文件来解决,其中每个索引条目都包含该条目在真实文件中的位置。这样,当您需要条目 X 时,您首先在索引文件中寻找正确的位置,读取该位置,然后使用该位置在实际数据文件中寻找。

这是有多少 DBM 数据库管理员处理他们的数据。

索引文件中的条目必须是固定大小的,例如索引中的每个条目的类型为std::ostream::pos_type,您使用write 写入索引,使用read 读取它。

【讨论】:

  • 是的,我明白这一点。但我想做的是当我搜索一个城市时。我用坐标 x 和 y 得到了那个城市的大小,我得到了 50 个再见。我在文件上用 seekg(我想)搜索这 50 个字节,当有匹配时返回我这些值:-?
  • 另一种方法是创建文件头。第一个帖子计数,然后发布地址,然后是所有帖子。首先阅读标题,了解要搜索的位置和数量,然后阅读。
  • 或者没有一种方法可以让我使用 fstream 和 fseek 吗?我的意思是一种更快的方法来到达当前行而不去每一行?我知道那是 fseek 或 seekg 但我不知道如何准确
  • @MirceaMihai 如果您知道要读取的元素在哪里,则只能使用搜索,但是由于每行的长度不同,因此无法知道每行的偏移量,例如说第一行一共十个字符,第二行15个字符,你想去第三行,你怎么知道你必须在文件中寻找25个字节,除非你已经有了位置或长度每一行?
  • 好吧,我正在尝试做的事情是这样的。我在结构中输入位置名称 oradea,坐标 x 和 y。之后我得到了 sizeof 结构。让我们说它是 40 个字节(通常这就是所有的时间,让我烦恼,但不知道为什么..)。我将这 40 个字节与文件中的其他字节进行比较。或者我正在考虑 string.find,但我不知道如何分离数据,例如 -> Oradea 22342 42342342 我怎样才能将 Oradea 放入一个字符串中,而另一个 2 放入 int 中。我尝试使用 getline 和单独但没有成功。
【解决方案2】:

检查https://stackoverflow.com/a/15452958/2156678。有提问者想要一种对二进制文件进行搜索(和更新)的方法,我提出了一种实现相同目的的简单方法。

【讨论】:

  • 谢谢,我查过了,但由于某种原因,我无法使用 BinaryFile 访问或制作某些文件,是否有我应该包含的文件? :-S
  • 这是询问者引用的普通普通输出流(所以我使用了相同的名称):ofstream BinaryFile("file_name", ios::binary);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-04-20
  • 2019-09-18
  • 2013-07-10
  • 2020-09-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多