Некоррекная работа с шестнадцатиричными числами (по мотивам книги Стефана Р.Дэвиса)

Модератор: Модераторы разделов

Аватара пользователя
Sabivan
Сообщения: 38
ОС: ОффтопXP Xubuntu 9.04

Некоррекная работа с шестнадцатиричными числами

Сообщение Sabivan »

Доброго времени суток.
Балуюсь линуксом всего пару месяцев.
С С++ знаком больше пяти лет, правда весьма поверхностно. Однако для написания курсачей по микроконтроллерам и этого хватало :rolleyes:
Недавно решил изучить книжку Стефана Р.Дэвиса: «С++ для чайников» для более близкого знакомства. Книгу выбрал первую попавшуюся, наверняка есть и по-лучше но это сейчас не по теме.
Работая с примерами, столкнулся с некорректным результатом работы простой программы. Побродил в поиске по форуму, но обсуждения конкретно этой проблемы не нашёл.
код проги:

Код:

// BitTest #include <stdio.h> #include <iostream.h> int main(int nArg, char* pszArgs[]) { //установка вывода в HEX виде cout.setf(ios::hex, ios::hex); int nArg1 = 0x1234; int nArg2 = 0x00ff; //выполнение логических операций cout << "Arg1 = 0x" << nArg1 << "\n"; cout << "Arg2 = 0x" << nArg2 << "\n"; cout << "~nArg1 = 0x" << ~nArg1 << "\n"; cout << "~nArg2 = 0x" << ~nArg2 << "\n"; cout << "nArg1 & nArg2 = 0x" << (nArg1 & nArg2) << "\n"; cout << "nArg1 | nArg2 = 0x" << (nArg1 | nArg2) << "\n"; cout << "nArg1 ^ nArg2 = 0x" << (nArg1 ^ nArg2) << "\n"; return 0; }


Результатом её работы должно быть следующее:
Argl = 0x1234
Arg2 = 0xff
~nArgl = 0xffffedcb
~nArg2 = 0xffffff00
nArgl & nArg2 = 0x34
nArgl | nArg2 = 0x12ff
nArgl ^ nArg2 = 0x12cb

Однако в консоли получаю:
sabivan@sabayonx86 ~/cpp/Bittest $ ./Bittest
Arg1 = 0x2008
Arg2 = 0x1248
~nArg1 = 0x-2009
~nArg2 = 0x-1249
nArg1 $ nArg2 = 0x1216
nArg1 | nArg2 = 0x2040
nArg1 ^ nArg2 = 0x824

Обратите внимание на то что значения Arg1 и Arg2 уже имеют неверное значение еще ДО того как с ними производятся кикае-либо манипуляции (0x2008 и 0x1248 вместо 0x1234 и 0xff соответственно)
Однако под виндами, в Borland C++ 3.1 всё работает как и должно быть.
Пришёл к выводу что некорректно обрабтываются HEX числа, потому что если убрать строку
cout.setf(ios::hex, ios::hex);
а переменным Arg1 и Arg2 присвоить десятичные числа — всё в норме.
Собственно вопрос: почему результат работы с шестнадцатиричными числами отличается от ожидаемого?

P.S. При компиляции получаю ворнинги следующего вида:

Код:

sabivan@sabayonx86 ~/cpp/Bittest $ make In file included from /usr/lib/gcc/i586-pc-linux-gnu/4.1.1/include/g++-v4/backward/iostream.h:31, from bt.cpp:3: /usr/lib/gcc/i586-pc-linux-gnu/4.1.1/include/g++-v4/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated. bt.cpp:5: warning: unused parameter ‘nArg’ bt.cpp:5: warning: unused parameter ‘pszArgs’


Мне остаётся неясным, ЗАЧЕМ автор использует в функции main аргументы int nArg и char* pszArgs[], ведь если просто написать
int main(void) {
программа всеравно успешно компилируется и работает, однако предупреждение относительно iostream.h остаётся.
bcc.exe на iostream.h не ругается.

P.P.S. Система Sabayon 3.3, ядро 2.6.20. компилировал как через qmake (см. Jasmin Blanchette - C++ GUI Programming with Qt 3), так и напрямую в g++ 4.1, результат один и тот же.
Семь бед - RTFM один ответ! =]
Спасибо сказали:
Аватара пользователя
Electronix
Сообщения: 53
ОС: Slackware, Suse, XP

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение Electronix »

Измени хедеры :

Код: Выделить всё

#include <stdio.h>
[b]#include <iostream>[/b]

int main(int nArg, char* pszArgs[])
{
     [b]using namespace std;[/b]

и попробуй еще раз.

Мне остаётся неясным, ЗАЧЕМ автор использует в функции main аргументы int nArg и char* pszArgs[], ведь если просто написать

Копи/паст скорее всего. Это аргументы передаваемые в командой строке, соотвественно если они не нужы их можно и не указывать.

Ну и вообще там проблема в том, что у тебя вывод идет в 10-ом формате, а не в 16-ом.
Вот так все нормально работает :

Код: Выделить всё

#include <stdio.h>
#include <iostream>

int main(int nArg, char* pszArgs[])
{
    using namespace std;
    //установка вывода в HEX виде
    cout<<std::hex;

    int nArg1 = 0x1234;
    int nArg2 = 0x00ff;

    //выполнение логических операций
    cout << "Arg1 = 0x" << nArg1 << "\n";
    cout << "Arg2 = 0x" << nArg2 << "\n";
    cout << "~nArg1 = 0x" << ~nArg1 << "\n";
    cout << "~nArg2 = 0x" << ~nArg2 << "\n";
    cout << "nArg1 & nArg2 = 0x"
         << (nArg1 & nArg2)
         << "\n";
    cout << "nArg1 | nArg2 = 0x"
         << (nArg1 | nArg2)
         << "\n";
    cout << "nArg1 ^ nArg2 = 0x"
                   << (nArg1 ^ nArg2)
         << "\n";
    return 0;
}


ЗЫ Выкинь эту книгу.
We have no beginning, we have no end. We are infinite.
Спасибо сказали:
Аватара пользователя
Sabivan
Сообщения: 38
ОС: ОффтопXP Xubuntu 9.04

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение Sabivan »

Да, действительно, исправилось. Спасибо, Electronix
Следовательно, проблема была в неправильной работе с потоками I/O


ЗЫ Выкинь эту книгу

Если серьзно подсяду на сишник, конечно избавлюсь от неё =)
Семь бед - RTFM один ответ! =]
Спасибо сказали:
Аватара пользователя
chups
Сообщения: 79
ОС: Debian Lenny GNU/Linux

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение chups »

тоже в последнее время подсел на чистый С++, но вот 2-й день не могу понять некоторые моменты:
хочу написать програмку, которая окрывает бинарник и в hex-режиме(не знаю как это правльно сказать:)) его читает

Вот код:

Код: Выделить всё

#include<iostream>
#include<fstream>

using namespace std;

char c, ch[64];
int current_count=0;

int main(int argc, char **argv){

    cout<<"tenmp program for experements with IO\n";
    ifstream in("08-04-12.kdf", ios::binary);

    if(!in.is_open()){
        cerr<<"file not open:(\n";
        return 1;
    }else cout<<"file have opened succsessfull"<<endl;

    cout.setf(ios::uppercase);
    in.seekg(0, ios::beg);
    cout<<"sizeof(ch) - "<<sizeof(ch)<<endl;
    //in.read(ch, sizeof(ch));

    /*for(int i=0; i<(int)strlen(ch); i++){
        current_count++;
        cout<<current_count<<". what read program- "<<hex<<(int)ch[i]<<endl;

    }*/

    in.read(ch, sizeof(ch));
    current_count++;
    cout<<current_count<<". what read program- "<<hex<<(int)(*ch)<<endl;

    while(in.read(ch, sizeof(ch))){
    for(int i=0; i<(int)strlen(ch); i++){
        current_count++;
        cout<<current_count<<". what read program - "<<hex<<(int)ch[i]<<" - "<<i<<endl;

    }
    }

    //cout<<"after operator read\n";

    /*while(in.get(c)){
    cout<<hex<<(int)c;
    }*/

    /*in.get(c);
    cout<<"step 2\treading with get - "<<(int)c<<endl;

    in.get(c);
    cout<<"step 3\treading with get - "<<hex<<(int)c<<endl;*/
    in.close();
return 0;
}


так вот в чем непонятки: мненадо считывать за один раз 64 байта, для этого вроде существует ф-ция read(), пытаюсь ее исользовать - оно то что-то и как-то читает, но не то что находиться в файле. думаю просто что-то не так написал я и выводиться не так как надо.

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

Для начала хотя бы как правильно сделать что бы бинарник правильно распечатовало?
зарание спасибо:)
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
RasenHerz
Сообщения: 1341
ОС: Arch Linux amd64

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение RasenHerz »

попробуй так:

Код: Выделить всё

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>

define BUFF_LEN 128

int main(int argc< char *argv[]){
   int fd, i, len; //файловый дескриптор, счетчик и длина считанных данных
   char buffer[BUFF_LEN]; //буффер в который будем читать

   if (!(fd = open("some_file", O_RDONLY)){
         printf("Error opening file.\n");
         return 0;
   }
   printf("HEX Dump of file: \n\n");
   while((len = read(fd, buffer, BUFF_LEN) > 0){
         for( i = 0; i < len; i++) printf("\t%x\n", (unsigned char)buffer[i]);
   }
   return 0;
}


как видишь программа, по-компактней твоей) ее можно усовершенствовать, распечатывая в строчку по 8-16 байт)

З.Ы. для того что ты делаешь, лучше использовать подход, предложенный мной.
Спасибо сказали:
Аватара пользователя
chups
Сообщения: 79
ОС: Debian Lenny GNU/Linux

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение chups »

извиняюсь за столь поздний ответ:)
RasenHerz, спасибо за примерчик(после некоторых манипуляций я его собрал)))
но вот в чем загвоздка: программа должна быть на чистом С++ и платформонезависимой.
и еще обьясните мне такое: будет ли считаться программа написаная чисто на С++ если в ней используються вызовы С-шних ф-ций?
Спасибо сказали:
Аватара пользователя
whirlwind
Сообщения: 67

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение whirlwind »

Electronix писал(а):
26.06.2008 15:23
Мне остаётся неясным, ЗАЧЕМ автор использует в функции main аргументы int nArg и char* pszArgs[], ведь если просто написать

Копи/паст скорее всего. Это аргументы передаваемые в командой строке, соотвественно если они не нужы их можно и не указывать.
Насколько я помню - это стандарт, именно так писать правильно. Даже если аргументы не используются. Впрочем, обычно переменные назвают по-другому, как в листингах ниже.

chups писал(а):
01.07.2008 11:46
но вот в чем загвоздка: программа должна быть на чистом С++ и платформонезависимой.
и еще обьясните мне такое: будет ли считаться программа написаная чисто на С++ если в ней используються вызовы С-шних ф-ций?
та программа будет платформонезависимой. Будет ли она считаться "написаная чисто на С++ " зависит от того, кто будет считать ;) Во всяком случае, любой компилятор как С, так и С++ ее скомилирует
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали:
Аватара пользователя
Electronix
Сообщения: 53
ОС: Slackware, Suse, XP

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение Electronix »

whirlwind
Насколько я помню - это стандарт, именно так писать правильно. Даже если аргументы не используются. Впрочем, обычно переменные назвают по-другому, как в листингах ниже.

(ISO/IEC 14882:2003(E) ISO/IEC) писал(а):3.6.1 Main function 3 Basic concepts
An implementation shall not predefine the main function. This function shall not be overloaded. It shall
have a return type of type int, but otherwise its type is implementation-defined. All implementations
shall allow both of the following definitions of main:
int main() { /* ... */ }
and
int main(int argc, char* argv[]) { /* ... */ }


Посему если они не используются, и не планируется использовать - их можно и не писать.
We have no beginning, we have no end. We are infinite.
Спасибо сказали:
Аватара пользователя
chups
Сообщения: 79
ОС: Debian Lenny GNU/Linux

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение chups »

всем привет:) спустя некоторое время я опять взялся за нерешеный вопрос. и вот что у меня получилось:
прога открывает любой файл в бинарном режиме чтения, и выводит в строку и на консоль в HEX-виде, но когда в бинарном виде открываються текстовые файлы, то вроде отбражает моя программа все нормально(сверяю с просмотрщиком mc), а вот когда окрываеться бинарник в бин. режиме, то часто появляються лишние ffffff, т.е. -1, а так без этой минус-еденицы все отображаеться нормально. так вот я не могу понять откуда береться этот глюк, как убрать вывод ffffff?
да забыл сказать работаю c бин. файлом с расщирением *.kdf, т.е. запускаю вот так прогу:

Код: Выделить всё

[penelopa@lika_host current_work]$ ./tokenization 08-04-12.kdf


и еще такой вопрос: 1 байт в hex-виде будет отображаться 2-мя символами? я вроде так понимаю, а вот моя прога если комбинация вида "0A", "00" , "0F" отображает соотв. A, 0, F, хотя mc отобр. по нормальному.
как сделать что бы отображалось как в mc?

В общем проектик с make-файлом в аттаче

З.Ы. RasenHerz твой примерчик мне несколько помог, пасиб :rolleyes:
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Спасибо сказали:
Аватара пользователя
Electronix
Сообщения: 53
ОС: Slackware, Suse, XP

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение Electronix »

chups
chups писал(а):
13.07.2008 18:40
и еще такой вопрос: 1 байт в hex-виде будет отображаться 2-мя символами? я вроде так понимаю, а вот моя прога если комбинация вида "0A", "00" , "0F" отображает соотв. A, 0, F, хотя mc отобр. по нормальному.
как сделать что бы отображалось как в mc?

Код: Выделить всё

strm << std::setfill('0') << std::setw(2);

Нужно написать либо перед выводом, например перед цикорм в котором выводится, либо перед каждым выводом в цикле :

Код: Выделить всё

cout << std::setfill('0') << std::setw(2) << std::hex;
for (...)
{
      cout<<HexData;
}

Либо так :

Код: Выделить всё

for (...)
{
     cout << std::setfill('0') << std::setw(2) << std::hex <<HexData;
}


Т.е. устанавливается ширина и заполнитель.

chups писал(а):
13.07.2008 18:40
прога открывает любой файл в бинарном режиме чтения, и выводит в строку и на консоль в HEX-виде, но когда в бинарном виде открываються текстовые файлы, то вроде отбражает моя программа все нормально(сверяю с просмотрщиком mc), а вот когда окрываеться бинарник в бин. режиме, то часто появляються лишние ffffff, т.е. -1, а так без этой минус-еденицы все отображаеться нормально. так вот я не могу понять откуда береться этот глюк, как убрать вывод ffffff?

а вот это я не понял.
We have no beginning, we have no end. We are infinite.
Спасибо сказали:
Аватара пользователя
whirlwind
Сообщения: 67

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение whirlwind »

chups писал(а):
13.07.2008 18:40
прога открывает любой файл в бинарном режиме чтения, и выводит в строку и на консоль в HEX-виде, но когда в бинарном виде открываються текстовые файлы, то вроде отбражает моя программа все нормально(сверяю с просмотрщиком mc), а вот когда окрываеться бинарник в бин. режиме, то часто появляються лишние ffffff, т.е. -1, а так без этой минус-еденицы все отображаеться нормально. так вот я не могу понять откуда береться этот глюк, как убрать вывод ffffff?
там ничего не добавляется, оно просто так и выглядит. Вы преобразуете знаковый (signed) char в знаковый int. В случае char знак хранится в старшем бите, т.е. числа больше 128 считаются отрицательными. С случае int используется так называемый дополнительный код (см. википедию ;) ). В нем число именно так и выглядит - три байта по FF и один - ваш, измененный на единицу. В текстовых файлах на англ языке используются символы нижней половины таблицы кодировки, у них значения меньше 128, поэтому проблема не проявляется.
Как решить - не знаю. Вот так работает, но уж сильно коряво выглядит:

Код: Выделить всё

 str<<setw(3)<<hex<<(unsigned int)(unsigned char)current_buf[i];
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали:
Аватара пользователя
whirlwind
Сообщения: 67

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение whirlwind »

хм, про дополнительный код это я поспешил... похоже, но не оно. Хотя проблема все равно, скорее всего, именно в конвертировании
Добро всегда побеждает зло. Мы победили, значит мы - добро.
Спасибо сказали:
Аватара пользователя
chups
Сообщения: 79
ОС: Debian Lenny GNU/Linux

Re: Некоррекная работа с шестнадцатиричными числами

Сообщение chups »

все равно Electronix, whirlwind спасибо , помогли :rolleyes:
Спасибо сказали: