Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: преобразование числа в строку
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему
sergey sva
Доброй ночи.

такая проблемка нужно преобразовать число unsigned int в символы char ,использую стандартную функцию компилятора sprintf(mass,"%u\n",count); все бы не чего только эта функция преобразует число инт в восьмеричную систему счисления , тоесть если count инкриминируется 1,2,3,4,5,6,7 после идет 10.
что это такое и как его заставить преобразовывать в dec? не пойму
sergeeff Jr.
Ну вот тут в самом низу winbatch например написал пример
http://www.daniweb.com/forums/thread32739.html
zltigo
Цитата(sergey sva @ Jan 12 2008, 00:02) *
что это такое и как его заставить преобразовывать в dec? не пойму

Уверены, что у Вас не %o ? Тогда рекомендую серьезно подумать о НЕ использовании впредь этого компилятора.
Andrеys
не стал создавать новую тему, так будет, наверное, лучше.
у меня в принципе ниче не выводит, а контроллер исполняет программу 1 раз и встает. в бесконечном цикле причем.

так объявляю все в начале:
char* str = "777";
char i=0; это i наращиваю каждый новый цикл.

такой код в бесконечной цикле выводит "777" на дисплей 1 раз, потом исполнение программы прекращается(засекаю по светодиодам специально мигающим на каждый проход)

sprintf(str,"%u\n",i);
print(str[0]);
print(str[1]);
print(str[2]);

никогда не пользовался этой функцией, подскажите в чем неправильность или скажите как надо вообще ей пользоваться?

дисплей символьный 16х2.
ф-ия print моя собственная, просто выводит данные на LCD.
пишу в ИАР 4.12.
AHTOXA
Цитата(Andrеys @ Feb 3 2008, 15:01) *
так объявляю все в начале:
char* str = "777";


Здесь объявлена переменная-указатель на char. И проинициализирована так, что указывает на "777". Эти "777", в зависимости от компилятора, могут располагаться и в ПЗУ.

То есть, надо объявить:
Код
char str[10];
Andrеys
Переобъявил, стало получше) спасибо
но числа пока не конвертирует правильно, выводит всякий мусор, видимо %u здесь не подходит?
AHTOXA
Там в IAR как-то надо подключать нужный вариант printf в xcl-файле.
что-то типа

Код
-e_small_write=_formatted_write


Почитайте в документации поподробнее.
------
Пока отвечал, ситуация изменилась:-)
Andrеys
получилось smile.gif код теперь выглядит так

sprintf(str,"%d\n", i);

причем i переменная типа int.
странная особенность, если переменная инт была объявлена внутри main-функции и там использовалась, то конвертируется корректно, при том что точно такая же переменная, только объявленная ВНЕ функций(а потом внутри как extern int), конвертируется в мусор на экране! sad.gif
AHTOXA
Цитата(Andrеys @ Feb 3 2008, 20:05) *
странная особенность, если переменная инт была объявлена внутри main-функции и там использовалась, то конвертируется корректно, при том что точно такая же переменная, только объявленная ВНЕ функций(а потом внутри как extern int), конвертируется в мусор на экране! sad.gif


Не должно такого быть. Давайте лучше пример кода. Нет ли рядом (в функции) другой переменной с таким же именем?
sergeeff Jr.
Гляньте еще на функции для конвертирования чисел в строки и обратно, такие как atoi и itoa.
Baser
А можно применить и свои, нестандартные функции. Они хоть и обладают урезанной функциональностью, но заточены под свои нужды и имеют компактный код.

Вот пример моих функций преобразования 2-х байтного бинарного в строку с небольшими возможностями форматирования:
- гашение или негашение незначащих нулей;
- задание кол-ва выводимых знаков;
- вывод десятичной точки в нужном месте для чисел с фиксированной точкой.

В примере в main форматирование регистров программного RTC для вывода на LCD по шаблону времени и даты.
aspID
Пожалуй, сюда же добавлюсь. Есть ли у кого идеи, как наиболее оптимально реализовать преобразование 16-ричных данных в строку и обратно? Необходимо в приложении к GSM и кодированию-декодированию текстовых сообщений. На уровне UART ходят текстом 16ричные данные. Вопрос оптимальности стоит довольно строго, поскольку ко всему прочему еще необходимо конвертиться из 8-бит в 7-битовую кодировку (и наоборот, соответственно).
Пока есть только "лобовое" решение, будет прицеплено сюда же часиков через 8 (как только до рабочей машины доберусь)
Baser
Цитата(aspID @ Feb 4 2008, 19:28) *
Есть ли у кого идеи, как наиболее оптимально реализовать преобразование 16-ричных данных в строку и обратно? ... На уровне UART ходят текстом 16ричные данные. ...

Вот, можете использовать, накидал по-быстрому. Тут для байтов, но переделать нетрудно:
Код
//==============================================================//
const char Table[16]={'0','1','2','3','4','5','6','7',
                      '8','9','A','B','C','D','E','F'};

char* BinToHex(unsigned char data, char *ptr)
  {
  *ptr++ = Table[(data>>4)& 0x0f];
  *ptr++ = Table[data & 0x0f];
  return ptr;
  }

//==============================================================//
//    Convert string of two HEX ASCII chars into binary value   //
//==============================================================//
unsigned char HexToBin(char hi_char, char lo_char)
  {
  hi_char -= '0';
  if (hi_char > 9)
      {
      hi_char &= ~0x20;     // Convert lower case to UPPER CASE
      hi_char -= 'A' - '0' - 0x0A;
      }
  lo_char -= '0';
  if (lo_char > 9)
      {
      lo_char &= ~0x20;     // Convert lower case to UPPER CASE
      lo_char -= 'A' - '0' - 0x0A;
      }
  return hi_char<<4 | lo_char;
  }
//==============================================================//
zltigo
Цитата(Baser @ Feb 5 2008, 00:59) *
....накидал по-быстрому.

Торопиться не надо - tolower уже не сработает, да и дважды вычитать тоже никчему - пару лишних команд (если об AVR речь идет).
Цитата
hi_char -= '0';
if (hi_char > 9)
{
hi_char &= ~0x20; // Convert lower case to UPPER CASE
hi_char -= 'A' - '0' - 0x0A;
}

Код
  if (hi_char > '9' )
      {
      hi_char &= ~0x20;     // Convert lower case to UPPER CASE
      hi_char -= ('A' - 10 );
      }
else
hi_char -= '0';
Andrеys
Цитата
Не должно такого быть. Давайте лучше пример кода. Нет ли рядом (в функции) другой переменной с таким же именем?

с собой кода нет, но могу ответственно сказать что больше с таким названием у меня переменных нет. я подозреваю ИАР версии 4.12, т.к. после занялся другой задачей - ШИМ для лампочки, поиграться. У меня была переменная pwm, которую по прерыванию раз в определенное время я заносил в OCR2. Естественно, ее объявил вне функций, и изменял ее в main (где объявил экстерном). Позже приведу код, где явное изменение pwm почему-то не происходит, а если добавить некую левую строку, все замечательно работает! поставлю версию 2.31 и опробую на ней.

для ЛСД пользую sprintf(), а stdlib с функцией itoa я не нашел smile.gif
aspID
Код
#ifndef _HEX_STRINGS_H_
#define _HEX_STRINGS_H_

unsigned char * AsciiToChar ( unsigned char * cAsciiString, unsigned char ucLen )
{
    unsigned char * p_ucBuf;
    unsigned char i;
    p_ucBuf = ( unsigned char * ) calloc ( ucLen / 2 + 1, sizeof ( unsigned char ) );

    //Convert HEX string to data
    for ( i = 0; i < ucLen; i += 2 )
    {
        p_ucBuf[ i / 2 ] = ( cAsciiString[ i ] > '9' ) ? ( cAsciiString[ i ] - 'A' + 10 ) : ( cAsciiString[ i ] - '0' );
        p_ucBuf[ i / 2 ] <<= 4;
        p_ucBuf[ i / 2 ] |= ( cAsciiString[ i + 1 ] > '9' ) ? ( cAsciiString[ i + 1 ] - 'A' + 10 ) : ( cAsciiString[ i + 1 ] - '0' );
    }
    
    p_ucBuf [ ucLen / 2 ] = 0;
    return p_ucBuf;
}

unsigned char * CharToAscii ( unsigned char * cHexData, unsigned char ucLen )
{
    unsigned char * p_ucBuf;
    unsigned char  i;
    p_ucBuf = ( unsigned char * ) calloc ( ucLen * 2 + 1, sizeof ( unsigned char ) );

    //Convert data to HEX string
    for ( i = 0; i < ucLen; i ++ )
    {
        p_ucBuf[ i * 2 + 1 ] = ( ( ( cHexData[ i ] ) & 0x0F ) > 9 ) ? ( ( cHexData[ i ] & 0x0F ) + 'A' - 10 ) : ( ( cHexData[ i ] & 0x0F ) + '0' );
        p_ucBuf[ i * 2 ] = ( ( cHexData [ i ] >> 4 ) > 9 ) ? ( ( cHexData[ i ] >> 4 ) + 'A' - 10 ) : ( ( cHexData[ i ] >> 4 ) + '0' );
    }
    
    p_ucBuf [ ucLen * 2 ] = 0;
    return p_ucBuf;
}

unsigned char * OctToSeptSMS ( unsigned char * p_ucData, unsigned char ucLen )
{
    //Convert octets to septets
    unsigned char * p_ucBuf;
    unsigned char i;
    p_ucBuf = ( unsigned char * ) calloc ( ucLen + ucLen / 7 + 1, sizeof ( unsigned char ) );

    unsigned char k, s;
    
    p_ucBuf[ 0 ] = p_ucData[ 0 ] & ~( 1 << 7 );

    for ( i = 1, k  = 7, s = 0; i < ucLen; i++ )
    {
        p_ucBuf[ i + s ] = ( p_ucData[ i - 1 ] >> k ) | ( p_ucData[ i ] << ( 8 - k ) );
        k--;
        if ( k == 1 )
        {
            s++;
            p_ucBuf[ i + s ] = ( p_ucData[ i - 1  ] >> k );
            k = 7;
        }
    }

    p_ucBuf [ ucLen + ucLen / 7 ] = 0;
    return p_ucBuf;
}

unsigned char * SeptToOctSMS ( unsigned char * p_ucData, unsigned char ucLen )
{
    //Convert octets to septets
    unsigned char * p_ucBuf;
    unsigned char i;
    p_ucBuf = ( unsigned char * ) calloc ( ucLen - ucLen / 8 + 1, sizeof ( unsigned char ) );

    unsigned char k, s;

    for ( i = 0, k = 0, s = 0; i < ucLen - 1; i++ )
    {
        p_ucBuf[ i - s ] = ( p_ucData[ i ] >> k ) | ( p_ucData[ i + 1 ] << ( 6 - k ) );
        k++;
        if ( k == 6 )
        {
            s++;
            i++;
            k = 0;
        }
    }

    p_ucBuf[ i - s ] = p_ucData[ i ] >> k;
    p_ucBuf [ ucLen - ucLen / 8 ] = 0;
    return p_ucBuf;
}

#endif //_HEX_STRINGS_H_


Все это для кодирования-декодирования SMS. На данный момент проблема в кодировании-декодировании кириллических сообщений. Не могу найти описания формата sad.gif

Забыл сказать - освобождение памяти - за "головой". Пример использования:
Код
p_ucBuf = AsciiToChar ( (unsigned char *)argv[2], strlen ( argv[2] ) );
p_ucStr = OctToSeptSMS ( (unsigned char *)p_ucBuf, strlen ( (char *) p_ucBuf ) );
free ( p_ucBuf );
p_ucBuf = p_ucStr;
p_ucStr = CharToAscii ( (unsigned char *)p_ucBuf, strlen ( (char *) p_ucBuf ) );
free ( p_ucBuf );
cout << p_ucStr << endl << flush;
Палыч
Цитата(aspID @ Feb 5 2008, 15:21) *
Все это для кодирования-декодирования SMS. На данный момент проблема в кодировании-декодировании кириллических сообщений. Не могу найти описания формата
Какой формат? Кодировка UCS2? Это - Unicode.
Сергей Борщ
Цитата(Andrеys @ Feb 5 2008, 14:15) *
я подозреваю ИАР версии 4.12
....
Позже приведу код, где явное изменение pwm почему-то не происходит,
А если объявите эту переменную с квалификатором volatile, то снова окажется, что виноват не компилятор, а чьи-то недостаточные знания языка С.
Baser
Цитата(zltigo @ Feb 5 2008, 00:26) *
Торопиться не надо - tolower уже не сработает, да и дважды вычитать тоже никчему - пару лишних команд (если об AVR речь идет).

Торопиться, действительно, не нужно. Но! Это не значит, что функции, которые я предлагаю общественному вниманию, не проверены. Тем более, что я "накидал по-быстрому" только первую функцию, а вторая была взята из рабочего проекта smile.gif
tolower там точно сработать не может, посколько там у меня toupper

А насчет вашего варианта, так его плюсы это более "понимабельный" код, поскольку он копирует человеческий процесс перевода hex в bin и не применяет неочевидных финтов.
И еще у него время обработки меньше зависит от входных данных, но это мало когда важно.

Из минусов отмечу (для AVR с ИАРом) больший на две команды размер кода за счет лишних переходов smile.gif
zltigo
Цитата(Baser @ Feb 6 2008, 14:21) *
Но! Это не значит, что функции, которые я предлагаю общественному вниманию, не проверены.

Да, уж... коррекция после приведеня к бинарному значению превысило мой уровень неочевидности smile.gif
Цитата
..и не применяет неочевидных финтов.

Применяет, но один smile.gif а не два.
Цитата
Из минусов отмечу (для AVR с ИАРом) больший на две команды размер кода за счет лишних переходов smile.gif

А это смотря как приведенный мной кусок smile.gif использовать:
AVR + IAR:
Код
               char tst1( char hi_char )
               {
                   if( hi_char > '9' )
   \   CPI     R16, 58
   \   BRCS    ??tst1_0
                 {   hi_char |= 0x20;    
                       hi_char -= 'A' + 10;
   \   ORI     R16, 0x20
   \   SUBI    R16, 75
   \   RET
                   }
                   else
                       hi_char -= '0';
   \   ??tst1_0:
   \   SUBI    R16, 48
                   return( hi_char );
   \   RET
               }
                



                   char tst2( char hi_char )
                  {
                 hi_char -= '0';
   \   SUBI    R16, 48
                if (hi_char > 9)
   \   CPI     R16, 10
   \   BRCS    ??tst2_0
                    {
                    hi_char &= ~0x20;    
                    hi_char -= 'A' - '0' - 0x0A;
   \   ANDI    R16, 0xDF
   \   SUBI    R16, 7
                   }
                return( hi_char );
   \   ??tst2_0:
   \   RET
              }

Можно и иногда на одну команду короче smile.gif, хотя и на одну больше sad.gif.
Результат - твой код для AVR более оптимален в большем числе случаев.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.