Проблемы при открытии .dat файла в c ++ - PullRequest
0 голосов
/ 13 марта 2019

так что в основном я пытался сохранить класс в файле .dat, но в моем коде, но он говорит об этой ошибке Нет соответствующей функции-члена для вызова open, но я поместил заголовок fstream. Я не знаю, пишу ли я что-то не так. Я использую Xcode 10.

class memberinformation
{
    string name; //name
    long int phonenumber; // phone number
    int memberid; // member id
    public :
    memberinformation()
    { name="not assigned" ;
        phonenumber=0;
        memberid=0;
    }
    int option3();
    int option2();
    int option1();
    int option4();
};



void wrt_file() //file function
{
    memberinformation k;
    fstream f;
    f.open ("information.dat",ios::app,ios::binary) //this is where I get the error. 
            f.write((char*)&k,sizeof(k));




}

Ответы [ 4 ]

3 голосов
/ 13 марта 2019

Вам повезло, что вас остановила простая ошибка. @ Alex44 уже показал, как избавиться от ошибки:

f.open ("information.dat",ios::app|ios::binary); //this is where I get the error. 

Но следующая строка еще хуже:

f.write((char*)&k,sizeof(k));

, поскольку компилятор не будет отображать никаких ошибок, а содержимое строки не будет сохранено в файле. std::string не является тривиально копируемым, и поэтому класс memberinformation также не является копируемым. Поэтому не следует пытаться записать его в файл в виде необработанных байтов.

Вместо этого вы должны написать функцию сериализации, которая записывает в двоичный поток (просто возможный способ сериализации):

  • phonenumber как long int (нет проблем)
  • memberid как int (нет проблем)
  • name.size как size_t
  • name.data как name.size байтов
2 голосов
/ 13 марта 2019

Ответили два других ответа:

  1. Почему не компилируется .
  2. Почему плохая идея писать двоичные объекты .

Я бы посоветовал вам сериализовать объект с помощью стандартной техники C ++ с использованием операторов потока.Это делает запись / чтение объектов тривиальным и, как правило, облегчает проблемы с отладкой.

Используя формат, предложенный @ serge-ballesta в его посте:

class memberinformation
{
    string    name; //name
    long int  phonenumber; // phone number
    int       memberid; // member id
    public :
      // OLD STUFF GOES HERE

    void swap(memberinformation& other) noexcept
    {
         using std::swap;
         swap(name,        other.name);
         swap(phonenumber, other.phonenumber);
         swap(memberid,    other.memberid);
    }
    friend std::ostream& operator<<(std::ostream& str, memberinformation const& data)
    {
         return str << data.phonenumber << " "
                    << data.memberid    << " "
                    << data.name.size() << " "
                    << data.name        << " ";
    }
    friend std::istream& operator<<(std::istream& str, memberinformation& data)
    {
         memberinformation tmp;
         std::size_t       nameSize
         if (str >> tmp.phonenumber >> tmp.memberid >> nameSize) {
             // All sizes were read correctly.
             tmp.name.resize(nameSize);
             if (str.ignore(1).read(&tmp.name[0], nameSize)) {
                 // ignored the space and read the name correctly.
                 // So now we update the "data" object
                 tmp.swap(data);
             }
         }
         return str;
    }
};

Сейчасв вашем коде:

int main()
{
    memberinformation   object;

    std::cout << object;
    std::cin  >> object;

    std::ofstream  file("Data.dat");
    file << object;
}
1 голос
/ 13 марта 2019

Вы пропустили точку с запятой, и вам нужно «поразрядно» или свои флаги:

void wrt_file() //file function
{
    memberinformation k;
    fstream f;
    f.open ("information.dat",ios::app|ios::binary); //this is where I get the error. 
    ...
}
0 голосов
/ 13 марта 2019

Ответы выше относятся к вашей первоначальной проблеме.Я собираюсь поговорить еще о двух.

Во-первых, вам, вероятно, следует использовать f.close () в конце вашего метода.Может быть, было бы прекрасно, если бы он выпал из области видимости и очистился оттуда, но я лично считаю, что это некрасиво, и я бы на это не рассчитывал.

Во-вторых, я бы не стал хранить данные вбинарный, если нет действительно веской причины сделать это.Это не будет портативным.Серж выше предлагает метод сериализации.Я бы рассмотрел альтернативный подход.Я написал бы в файл в удобочитаемой форме, такой как JSON.Да, это немного больше работы, но ...

- Если вы измените свой класс, ваши старые файлы будут по-прежнему читаемы. - Они переносимы в любой среде. - Вы можете посмотреть на них и легко понять, что онисодержать

Так что приведенные выше предложения Сержа не ужасны, но я бы выбрал более современный стиль сериализации / десериализации.

Обратите внимание, что ваш f.write не будет работать, потому что ваш объект содержит другиеобъекты, вы не знаете, как они работают под капотом.Эта строка, например, почти наверняка не может быть сброшена так, как вы пытаетесь это сделать.Кроме того, вы не только сбрасываете свои данные.

Кроме того, вы должны напечатать sizeof (k).Вы можете найти интересную информацию.Попробуйте учесть каждый байт.Вы могли бы напечатать sizeof (k.name), чтобы помочь вам разобраться с некоторыми из них.

Я почти уверен, что такая информация удивит вас, но на самом деле я сам этого не делал, потому что яникогда не будет пытаться скопировать в память объекты C ++, и это то, что вы пытаетесь сделать.

...