struct Info{
CString razd;
CString stroka;
};
CArray<Info,Info> nastr;
//и две фуекции - одна создает файл а другая затем его читаетvoid CNastr::CreateFile()
{
Info inf;
CFile file("nastr.nas", CFile::modeWrite | CFile::modeCreate);
CArchive ar(&file, CArchive::store);
int ArSize=nastr.GetSize();
ar.Write(&ArSize,sizeof(int));
for (int i=0;i<ArSize;i++)
{
inf = nastr.GetAt(i);
ar.Write(&inf,sizeof(Info));
}
ar.Close();
file.Close();
}
void CNastr::Init()
{
CFile file("nastr.nas", CFile::modeRead);
CArchive ar(&file, CArchive::load);
int ArSize;
Info inf=new Info;
ar.Read(ArSize,sizeof(int));
for (int i=0;i<ArSize;i++)
{
ar.Read(inf,sizeof(Info));
nastr.Add(inf);
}
ar.Close();
file.Close();
}
При чтении файла вываливается Assertion Failed, File dbgheap.c Line 1011 Expression _CrtlsValidHeapPointer(pUserData)
Чего ему не хватает :???:
Пробовала выделять память динамически, но это не помогает.
Здравствуйте Xenia, Вы писали:
X>Здравствуйте! X>Имеется такой код:
X>
X>struct Info{
X> CString razd;
X> CString stroka;
X>};
X>CArray<Info,Info> nastr;
X>//и две фуекции - одна создает файл а другая затем его читает
X>void CNastr::CreateFile()
X>{
X> Info inf;
X> CFile file("nastr.nas", CFile::modeWrite | CFile::modeCreate);
X> CArchive ar(&file, CArchive::store);
X> int ArSize=nastr.GetSize();
X> ar.Write(&ArSize,sizeof(int));
X> for (int i=0;i<ArSize;i++)
X> {
X> inf = nastr.GetAt(i);
X> ar.Write(&inf,sizeof(Info));
X> }
X> ar.Close();
X> file.Close();
X>}
X>void CNastr::Init()
X>{
X> CFile file("nastr.nas", CFile::modeRead);
X> CArchive ar(&file, CArchive::load);
X> int ArSize;
X> Info inf=new Info;
X> ar.Read(ArSize,sizeof(int));
X> for (int i=0;i<ArSize;i++)
X> {
X> ar.Read(inf,sizeof(Info));
X> nastr.Add(inf);
X> }
X> ar.Close();
X> file.Close();
X>}
X>
X>При чтении файла вываливается Assertion Failed, File dbgheap.c Line 1011 Expression _CrtlsValidHeapPointer(pUserData) X>Чего ему не хватает X>Пробовала выделять память динамически, но это не помогает.
ну ты посмотри, что у тебя происходит:
ты пишешь Info, а в нём 2 строки, которые есть лишь место под вспом. переменные для строки (сами строки динамически получаются, там указатели). Надо сделать типа
clas Info{
CString razd;
CString stroka;
}
CArchive& operator <<( CArchive& ar, const Info& info ){
return ar << info.razd << info.stroka;
};
CArchive& operator >>( CArchive& ar, const Info& info ){
return ar >> info.razd >> info.stroka;
};
//в CNastr::CreateFile()
ar >> inf;
//в CNastr::Init()
ar << inf;
Я поняла в чем проблема... Мы не знаем заранее размер CString. Поэтому я от него отказалась и использую char[9], тем более что у меня длина всегда фиксированная. Так что проблему успешно опборола. Кстати, мой компилятор ругается на переопределение оператора >> — говорит нет соответствующего с правым операндом типа CString.
Здравствуйте Xenia, Вы писали:
X>Я поняла в чем проблема... Мы не знаем заранее размер CString. Поэтому я от него отказалась и использую char[9], тем более что у меня длина всегда фиксированная. Так что проблему успешно опборола. Кстати, мой компилятор ругается на переопределение оператора >> — говорит нет соответствующего с правым операндом типа CString.
Совершенно верно ты поняла
А ругается, потому, что я из ума писал и забыл, что в >> для параметра Info const нафиг не нужен (ну меняется же он!), убери его и всё будет замечательно, хотя если у тебя строки фиксированные, то, конечно, это тебе не очень-то и нужно...
Хорошего тебе настроения !
Здравствуйте Xenia, Вы писали:
X>Я поняла в чем проблема... Мы не знаем заранее размер CString. Поэтому я от него отказалась и использую char[9], тем более что у меня длина всегда фиксированная. Так что проблему успешно опборола. Кстати, мой компилятор ругается на переопределение оператора >> — говорит нет соответствующего с правым операндом типа CString.
Просто для CArchive не определен оператор >> для типа CString, но если очень хочется, то можно определить свой...
Но я хочу сказать несколько о другом — в функции CArchive::Write ты используешь sizeof(Info), а результат sizeof, вообще говоря, зависит от выравнивания. Поэтому теоретически возможна ситуация, когда записывается одно количество байт, а считывется другое, что не есть хорошо.
Поэтому я бы объявил структуру Info так:
#pragma pack(1)//Или не 1, а что-нибудь другое...struct Info
{
char razd[9];
char stroka[9];
};
#pragma pack()
В этом случае sizeof(Info) всегда одно и тоже.
Еще раз повторюсь — вероятность такого рода сбоя не очень велика, но она существует.
В частности, я столкнулся с такой проблемой, когда обрабатывал бинарные файлы, созданные другим приложением (хотя и в том, и в другом приложении использовались одни и те же структуры...)
Здравствуйте Bell, Вы писали:
B>Здравствуйте Xenia, Вы писали:
X>>Я поняла в чем проблема... Мы не знаем заранее размер CString. Поэтому я от него отказалась и использую char[9], тем более что у меня длина всегда фиксированная. Так что проблему успешно опборола. Кстати, мой компилятор ругается на переопределение оператора >> — говорит нет соответствующего с правым операндом типа CString.
B>Просто для CArchive не определен оператор >> для типа CString, но если очень хочется, то можно определить свой...
Не — враки, определён, там проблема в другом была (см. мессагу выше), а за напоминание за прагму спасибки — может тоже когда-нибудь на грабли наступлю...
Привет!
Xenia, если в будующем Вы все же соберетесь использовать CArray со строками (или другими структурами),
надо для структуры написать оператор присваивания, т.к. CArray внутри вызывает его при копировании.
Нечто вроде
Здравствуйте grigsoft, Вы писали:
G>Привет! G>Xenia, если в будующем Вы все же соберетесь использовать CArray со строками (или другими структурами), G>надо для структуры написать оператор присваивания, т.к. CArray внутри вызывает его при копировании. G>Нечто вроде
G>struct Info G>{ G> CString razd; G> CString stroka; G> Info& operator=(const Info&); G>}; G>Info& Info::operator=(const Info& a) G>{ G> razd = a.razd; G> stroka = a.stroka; G> return *this; G>}
G>CArray<Info,Info> nastr;
Спасибо, я это уже поняла. Но по-моему надо определить еще конструктор копий. Или я ошибаюсь?
G>>Привет! G>>Xenia, если в будующем Вы все же соберетесь использовать CArray со строками (или другими структурами), G>>надо для структуры написать оператор присваивания, т.к. CArray внутри вызывает его при копировании.
X>Спасибо, я это уже поняла. Но по-моему надо определить еще конструктор копий. Или я ошибаюсь?
Нет необходимости — CArray его не использует. Разве что для красоты :-)
Кстати, не стесняйтесь заглядывать в исходники CArray и всего MFC — многое становиться понятно именно там.
Уже после своего ответа присмотрелся к Вашему коду и понял, что он (мой ответ) был не в тему — настоящую проблему указал Курилка, так что извините. Уже все работает? А то заполнение массива выделенными new элементами даже компилироваться, по идее, не должно :-)
Вообще, сваливать таким образом данные на диск не очень красиво. Что Вы будете делать когда завтра понадобиться добавить в info еще одно поле? А если Вы просто захотите добавить виртуальные функции к info, тогда измениться размер структуры и file.write(&info, sizeof(info)) потеряет смысл. Хотя, конечно, если это разовая работа, то заморачиваться такими вещами смысла действительно нет. А вот чтобы в "люди выйти" :-) привычка к хорошему стилю может пригодиться.
G>Вообще, сваливать таким образом данные на диск не очень красиво. Что Вы будете делать когда завтра понадобиться добавить в info еще одно поле? А если Вы просто захотите добавить виртуальные функции к info, тогда измениться размер структуры и file.write(&info, sizeof(info)) потеряет смысл. Хотя, конечно, если это разовая работа, то заморачиваться такими вещами смысла действительно нет. А вот чтобы в "люди выйти" привычка к хорошему стилю может пригодиться.
Удачи, G>Игорь
Вообще-то назначение структуры Info у меня это всего-лишь установление соответствия между определнным Edit'ом в моей программе и префиксом строки в текстовом файле, так что в ней не может быть вообще никаких функций. Именно поэтому она struct а не class
Re[6]: Re: Array
От:
Аноним
Дата:
05.04.02 16:32
Оценка:
А по мне так записывать на диск объекты классов вообще, как бы это сказать, не люблю я этого. Лучше определьтся с форматом, и записывать в этом формате, чем надеятся на то, что эта информация будет использоваться только через определенный класс, что этот класс никогда не поменяется, и что он не содержит никаких динамических данных.
А>А по мне так записывать на диск объекты классов вообще, как бы это сказать, не люблю я этого. Лучше > определьтся с форматом, и записывать в этом формате, чем надеятся на то, что эта информация будет > использоваться только через определенный класс, что этот класс никогда не поменяется, и что он не > содержит никаких динамических данных.
Тоже верно, особенно в описанном Xenia случае. И формат уже изобретен — XML :-)
To Xenia: а между class и struct разницы никакой — записи
struct A {int i;};
и
class A{public: int i;};
абсолютно эквивалентны.
Ну да ладно, топик на этом предлагаю считать исчерпаным :-)