spiage
Гость
|
|
« : 16-08-2004 02:11 » |
|
Привет! Столкнулся с такой проблемой при побайтном чтении файла: char c; ifstream ifile("foo.dat", ios::in | ios::binary); ifile >> c; Так вот - если код символа > 128, то число получается отрицательным Для преобразования приходится делать так: int i = (int)(unsigned char)c; Если использовать сразу unsigned char, то чтение идет неверное... Есть ли у кого мысли по этому поводу? (Мне действительно необходимо ПОБАЙТНОЕ чтение, работаю напрямую с DBF) И еще вопрос - можно ли на С++ работать при file I/O сразу со структурой, как в Паскале? Или все же нет такой встроеной возможности? ICQ для связи: 127834898Пример: type Rec = record i: byte; s:string[12]; w:word; end; var f: file of Rec; r: Rec; begin ........ read(f, r); ........ end.
|
|
« Последнее редактирование: 30-11-2007 22:26 от Алексей1153++ »
|
Записан
|
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #1 : 16-08-2004 05:03 » |
|
Так вот - если код символа > 128, то число получается отрицательным Для преобразования приходится делать так:
Мне действительно необходимо ПОБАЙТНОЕ чтение
попробуй объявить не char c, а: UCHAR c; или BYTE c; :arrow: И еще вопрос - можно ли на С++ работать при file I/O сразу со структурой, как в Паскале?
может и нет, не знаю. Наверное надо будет самому писать класс, который будет делать то, что нужно
|
|
|
Записан
|
|
|
|
spiage
Гость
|
|
« Ответ #2 : 16-08-2004 07:31 » |
|
У меня было: Если использовать сразу unsigned char, то чтение идет неверное...
Ты посоветовал: попробуй объявить не char c, а:
UCHAR c;
или
BYTE c;
Но я все равно поверил (видно сказывается привычка Windows-пользователя бить в барабаны и устраивать пляски, в надежде, что все получится ) Все равно глючит Проскакивает через байт... А по поводу чтения структур есть у меня мысль, что через указатель с размером, равным структуре, вполне можно проделать такую штуку... Лишь бы компилятор порядок следования элементов в структуре не нарушал...
|
|
|
Записан
|
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #3 : 16-08-2004 07:41 » |
|
spiage, конэчно можно. вот тебе примерчик. #include <fstream> #pragma pack(push,1) struct s { int i; long l; float f; s() i(10), l(20), f(40) {} };
void main() { std::fstream fs( "pr.bin", std::ios::binary | std::ios::out | std::ios::in ); if(!fs.is_open()) return; s ss; fs.write( (char *)&ss, sizeof(ss)); fs.read((char *)&ss, sizeof(ss)); return; } #pragma pack(pop)
|
|
« Последнее редактирование: 30-11-2007 22:28 от Алексей1153++ »
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #4 : 16-08-2004 07:42 » |
|
и вот эти строчки помогут с твоей проблеммкой #pragma pack(push,1) ..... #pragma pack(pop)
|
|
« Последнее редактирование: 30-11-2007 22:29 от Алексей1153++ »
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #5 : 16-08-2004 07:43 » |
|
можешь спросить меня что эта прагма делает
|
|
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
spiage
Гость
|
|
« Ответ #6 : 16-08-2004 08:21 » |
|
А вот так почему? BYTE c; cout << ifile.tellg() << endl; ifile >> c; cout << ifile.tellg() << endl;
Ответ: 46 48
|
|
« Последнее редактирование: 30-11-2007 22:29 от Алексей1153++ »
|
Записан
|
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #7 : 16-08-2004 08:29 » |
|
можно весь пример а не только вом это
BYTE c; cout << ifile.tellg() << endl; ifile >> c; cout << ifile.tellg() << endl;
чем инитится с? где обявление ifile? просто возникают вопросы
|
|
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
spiage
Гость
|
|
« Ответ #8 : 16-08-2004 08:32 » |
|
#ifndef BYTE typedef unsigned char BYTE; #endif ... ifstream ifile(FileName.c_str(), ios::in | ios::binary); BYTE c; ...... (несколько _удачных_ чтений в "с") cout << ifile.tellg() << endl; ifile >> c; cout << ifile.tellg() << endl; ifile.close();
|
|
|
Записан
|
|
|
|
spiage
Гость
|
|
« Ответ #9 : 16-08-2004 09:16 » |
|
Нет, вы представте - я поменял ifile >> с
на ifile.get(c)
только в одном месте (где "пролет над байтом" был), и все нормально стало... Похоже, что это глюк компилятора... (Пользовался С++Builder 6.0 Build 10.155, Windows 2003 Enterprise Server)
|
|
« Последнее редактирование: 30-11-2007 22:30 от Алексей1153++ »
|
Записан
|
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #10 : 16-08-2004 09:27 » |
|
spiage, я тебе и говорил, что от этих новшеств - аля << и >> я давно отказался, мне понятнее работа ifile.get(c), ifile.read(c, sizeof(c)), ifile.write(c, sizeof(c))
|
|
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
Алексей++
глобальный и пушистый
Глобальный модератор
Offline
Сообщений: 13
|
|
« Ответ #11 : 16-08-2004 09:37 » |
|
spiage, , вот такой я невнимательный Pu, а что эта прагма делаетъ?
|
|
|
Записан
|
|
|
|
Pu
Большой босс
Offline
78
|
|
« Ответ #12 : 16-08-2004 09:55 » |
|
Алексей1153, прагма указывает на сколько при операциях чтения записи делать выравнивание. если не указать единичку то char вместо 1 байта считает и запишет 4 байта, тк в виндах по умолчанию выравнивание по двойному слову. Я на эту фигню нарвался еще давненько когда с доса пересел под винду. подробнее ms-help://MS.VSCC.2003/MS.MSDNQTR.2003APR.1033/vclang/html/_PREDIR_pack.htm
|
|
|
Записан
|
Насколько я опытен? Достаточно, чтобы понимать, что дураков нельзя заставить думать по–другому, но недостаточно, чтобы отказаться от попыток это сделать. (с) Артур Джонс
|
|
|
spiage
Гость
|
|
« Ответ #13 : 16-08-2004 10:02 » |
|
А так хотелось по-умному...
|
|
|
Записан
|
|
|
|
npak
|
|
« Ответ #14 : 16-08-2004 13:59 » |
|
spiage, очень странный эффект случился с реализацией istream на MS МЫ 6.0 -- даже при установке режима чтения binary оператор >> перескакивает через байты конца строки. Возможно, это причина твоей проблемы.
Можно сделать вот как: #ifndef BYTE typedef unsigned __int8 BYTE; #endif
BYTE & operator >> (istream & inf, BYTE & b) { inf.read((char *)&b,1); return b; }
При таком задании байта и оператора чтения оператор >> не перескакивает через концы строк.
Этот пример показывает технику чтения-записи структур в потоки. При создании своего класса/структуры надо определить свои операторы << и >> для них. Правда, предложенный Pu способ прямой записи содержимого структуры через read(p, sizeof(*p)) не подходит для структур и классов, содержащих указатели.
|
|
|
Записан
|
|
|
|
spiage
Гость
|
|
« Ответ #15 : 17-08-2004 02:21 » |
|
npak, Твой вариант подошел, работает вполне нормально без pragma pack(1), и даже с установленной в настройках компилятора Data alignment = Quorted Word (если я правильно понял - это аналог pragma pack(8 )) Теперь можно к сказанному тобой добавить, что "странная" реализация istream не только на MS VS 6.0 но и на Borland C++Builder 6.0 У меня есть предположение :idea: , что это из-за того, что в STL::iostream в шаблоне basic_istream реализация operator>> дана только для одного 8-и битного типа - для типа char, который является знаковым по дефолту... А учитывая, что эта ошибка проявляется вполне произвольно, думаю, что глюк где-то в реализации... 8) Если будет время - полезу в кишки STL... :new_shot: А по хорошему лучше бы вставить в стандарт операцию с бесзнаковым символом
|
|
|
Записан
|
|
|
|
|