У меня есть этот код для сериализации / десериализации объектов класса в файл, и, похоже, работает.
Однако у меня есть два вопроса.
wstring
‘s (как у меня сейчас) я хочу иметь один wstring
и один string
членs2.product_name_= L"megatex";
если вместо мегатекса я напишу что-нибудь на русском языке, скажем (например, s2.product_name_ = L «логин»), код больше не будет работать так, как задумано.Что может быть не так? Благодарю.
Вот код:
// ConsoleApplication3.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"#include <iostream>
#include <string>
#include <fstream> // std::ifstream
using namespace std;
// product
struct Product
{
double price_;
double product_index_;
wstring product_name_;
wstring other_data_;
friend std::wostream& operator<<(std::wostream& os, const Product& p)
{
return os << p.price_ << endl
<< p.product_index_ << endl
<< p.product_name_ << endl
<< p.other_data_ << endl;
}
friend wistream& operator>>(std::wistream& is, Product& p)
{
is >> p.price_ >> p.product_index_;
is.ignore(std::numeric_limits<streamsize>::max(), '\n');
getline(is,p.product_name_);
getline(is,p.other_data_);
return is;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Product s1,s2;
s1.price_ = 100;
s1.product_index_ = 0;
s1.product_name_= L"flex";
s1.other_data_ = L"dat001";
s2.price_ = 300;
s2.product_index_ = 2;
s2.product_name_= L"megatex";
s2.other_data_ = L"dat003";
// write
wofstream binary_file("c:\\test.dat",ios::out|ios::binary|ios::app);
binary_file << s1 << s2;
binary_file.close();
// read
wifstream binary_file2("c:\\test.dat");
Product p;
while (binary_file2 >> p)
{
if(2 == p.product_index_){
cout<<p.price_<<endl;
cout<<p.product_index_<<endl;
wcout<<p.product_name_<<endl;
wcout<<p.other_data_<<endl;
}
}
if (!binary_file2.eof())
std::cerr << "error during parsing of input file\n";
else
std::cerr << "Ok \n";
return 0;
}
Что если вместо двух wstring (как у меня сейчас) я хочу иметь один
wstring и одна строковая переменная-член в моем классе? (Думаю в такой
если мой код не будет работать?).
Есть определитель, определенный для char *
для любого basic_ostream
(ostream
а также wostream
), так что вы можете использовать результат c_str()
вызов функции-члена для string
член. Например, если string
участник other_data_
:
return os << p.price_ << endl
<< p.product_index_ << endl
<< p.product_name_ << endl
<< p.other_data_.c_str() << endl;
Случай экстрактора является более сложным, так как вам придется читать как wstring
и преобразовать в string
, Самый простой способ сделать это просто читать как wstring
а затем сужение каждого символа:
wstring temp;
getline(is, temp);
p.other_data_ = string(temp.begin(), temp.end());
Я не использую локали в этом примере, я просто преобразовываю последовательность байтов (8 бит) в последовательность слов (16 бит) для вывода и противоположных (усеченных значений) для ввода. Это нормально, если вы используете символы ASCII или однобайтовые символы и вам не требуется определенный формат (например, Unicode) для вывода.
В противном случае вам нужно будет справиться с locale
s. locale предоставляет культурную контекстную информацию для интерпретации строки (помните, что это просто последовательность байтов, а не символов в смысле букв или символов; карта между байтами и символом определяется locale
). locale
не очень простая в использовании концепция (человеческая культура не слишком). Как вы предполагаете, было бы лучше сначала провести небольшое исследование о том, как это работает.
Во всяком случае, идея заключается в следующем:
string
s из оригинальной кодировки в Unicode, используя locale
для вывода.wstring
читать из файла (в Unicode) в string
с помощью locale
,Наконец, ниже, в основном, когда я инициализирую s2.product_name_ =
L «Мегатекс»; если вместо мегатекса я напишу что нибудь по русски скажу
(например.,s2.product_name_= L"логин"
), код больше не работает, так как
предназначена.
Когда вы определяете массив wchar_t
с помощью L""
вы на самом деле не указываете, что строка является Unicode, просто массив состоит из символов, а не wchar_t. Я предполагаю, что предполагаемая работа s2.product_name_
хранить имя в формате Unicode, но компилятор будет принимать все char
в этой строке (как без L
) и преобразовать в wchar_t
просто заполнение нулями самого значимого байта. Юникод не очень хорошо поддерживается в стандарте C ++ до C ++ 11 (и все еще не слишком поддерживается). Это работает только для символов ASCII, потому что они имеют одинаковую кодировку в Unicode (или UTF-8).
Для использования символов Unicode в статической строке вы можете использовать escape-символы: \uXXXX
, Я знаю, что делать это для каждого неанглийского персонажа не очень удобно. Вы можете найти список символов Unicode на нескольких сайтах в Интернете. Например, в Википедии: http://en.wikipedia.org/wiki/List_of_Unicode_characters.
Других решений пока нет …