Строка -> число

Тема в разделе "WASM.WIN32", создана пользователем _Juicy, 19 мар 2012.

  1. _Juicy

    _Juicy Active Member

    Публикаций:
    0
    Регистрация:
    12 авг 2003
    Сообщения:
    1.159
    Адрес:
    SPb
    Нет ли случайно в виндовс апи функции, переводящей строку с десятичным или шестнадцатеричным числом в дворд, например?
     
  2. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    drem1lin нравится это.
  3. samuraishowdown

    samuraishowdown New Member

    Публикаций:
    0
    Регистрация:
    6 мар 2011
    Сообщения:
    70
    msvcrt.dll динамически подгрузи. sscanf и всё-такое. Или в 6 студии компиль c динамическим рантаймом. strtoul тамже.
     
  4. Sunzer

    Sunzer Member

    Публикаций:
    0
    Регистрация:
    25 май 2008
    Сообщения:
    256
    Код (Text):
    1. for(DWORD i=0;i<strlen(hex);i++)
    2. {
    3.    if(hex[i] >= '0' && hex[i] <= '9')
    4.    {
    5.        Decoded += (hex[i] - 0x30) * (1 << ( (strlen(hex) - i - 1) * 4) );
    6.    }
    7.     else if(hex[i] >= 'A' && hex[i] <= 'F')
    8.    {
    9.        Decoded += (hex[i] - 0x37) * (1 << ( (strlen(hex) - i - 1) * 4) );
    10.    }
    11.     else if(hex[i] >= 'a' && hex[i] <= 'f')
    12.    {
    13.        Decoded += (hex[i] - 0x57) * (1 << ( (strlen(hex) - i - 1) * 4) );
    14.    }
    15.     else
    16.    {
    17.        ParserError("Can't decode hex value.\n");
    18.    }
    19. }
     
  5. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.709
    Перевод строки из десятеричных цифр в DWORD
    автор The Svin взято здесь
    Код (ASM):
    1. OPTION PROLOGUE:NONE
    2. OPTION EPILOGUE:NONE
    3. atodw proc FORCENOFRAME
    4.     ;----------------------------------------
    5.     ; перевод десятеричной строки в число типа dword
    6.     ; значение возвращается в регистре eax
    7.     ;----------------------------------------
    8.     ;   String EQU [esp+4]
    9.     mov edx, [esp+4]
    10.     xor eax, eax
    11.     cmp BYTE PTR [edx], 2Eh
    12.     sbb [esp+4], edx
    13.     adc edx, eax
    14.     jmp @F
    15. again:
    16.     lea eax, [eax+4*eax]
    17.     inc edx
    18.     lea eax, [ecx+2*eax-30h]
    19. @@: movzx ecx, BYTE PTR [edx]
    20.     cmp BYTE PTR [edx], 30h
    21.     jns again
    22.     add eax, [esp+4]
    23.     xor eax, [esp+4]
    24.     retn 4
    25. atodw ENDP
    26. OPTION PROLOGUE:DefaultOption
    27. OPTION EPILOGUE:DefaultOption1
    Перевод строки
    из шестнадцатеричных цифр
    в число типа DWORD
    с использованием MMX

    автор bitRAKE, взято здесь
    Код (ASM):
    1. StrHex2bin PROC
    2.     _CONST SEGMENT
    3.         lpString db "89aBcDeF"
    4.     _CONST ENDS
    5.     movq mm0,QWORD PTR [lpString]
    6.  
    7.     psubusb  mm0,mxc(<30>) ; "0" = 0
    8.     movq mm1,mm0
    9.  
    10.     pcmpgtb mm1,mxc(<09>) ; letter?
    11.     pand mm1,mxc(<07>)
    12.  
    13.     psubusb mm0,mm1 ; fix letters
    14.  
    15.     movq mm1,mm0         ; 0F0E0D0C0B0A0908
    16.     pand mm0,mxc(<0F00>) ; 0E000C000A000800
    17.     pand mm1,mxc(<000F>) ; 000F000D000B0009
    18.     psrlq mm0,8          ; 000E000C000A0008
    19.  
    20.     packuswb mm1,mm1     ; 0F0D0B09
    21.     packuswb mm0,mm0     ; 0E0C0A08
    22.     psllq mm1,4          ; F0D0B090
    23.     por mm0,mm1          ; FEDCBA98
    24.     movd eax,mm0         ; FEDCBA98
    25.  
    26.     bswap eax            ; 89ABCDEF
    27.     ret
    28. StrHex2bin ENDP
    Перевод строки из шестнадцатеричных цифр
    в число типа DWORD

    автор The Svin, взято здесь
    Используются только строчные буквы (ABCDEF)
    Модуль написан в формате masm32.inc. При использовании описывайте прототип как
    htodwc proto :lol: WORD
    Код (ASM):
    1.  
    2. ; #########################################################################
    3.  
    4.     ; --------------------------------------
    5.     ; This procedure was written by Svin
    6.     ; --------------------------------------
    7.  
    8.       .386
    9.       .model flat, stdcall  ; 32 bit memory model
    10.       option casemap :none  ; case sensitive
    11.  
    12.     .code
    13.  
    14. ; #########################################################################
    15. OPTION PROLOGUE:NONE
    16. OPTION EPILOGUE:NONE
    17.  
    18. htodwc         proc FORCENOFRAME
    19.  
    20.  
    21.     push ebx
    22.     xor eax,eax
    23.     mov ebx,[esp+8]
    24.     xor edx,edx
    25. @@: mov dl,[ebx] ;1
    26.     shl eax,4        ;0
    27.     cmp dl,41h   ;1
    28.     inc ebx         ;0
    29.     sbb cl,cl       ;1
    30.     sub dl,'A'-0Ah ;0
    31.     and cl,7        ;1
    32.     add dl,cl      ;1
    33.     cmp byte ptr [ebx],0 ;0
    34.     lea eax,[eax][edx] ;1
    35.     jne @B  ;1
    36.     pop ebx
    37.     ret 4
    38. htodwc         endp
    39. OPTION PROLOGUE:DEFAULTOPTION
    40. OPTION EPILOGUE:DEFAULTOPTION
    41.  
    42. end
     
    bubu и Коцит нравится это.
  6. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    562
    Бывает что строка не содержит корректный код числа, что тогда делать?
    Я, вот, решил так.
    Код (C++):
    1.  
    2. bool   Str2Int(LPCSTR str, u32& param)
    3. {
    4.    int size = string_length(str);
    5.    int a1, a2, digit_capacity;
    6.    if(size>2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')){   // style C, 0xFFFF
    7.      a1=2; a2=size-1;
    8.      digit_capacity=16;
    9.    }
    10.    else if(size>1 && str[0]=='$'){                             // style Pascal, $FFFF
    11.      a1=1; a2=size-1;
    12.      digit_capacity=16;
    13.    }
    14.    else if(size>1 && (str[size-1]=='h' || str[size-1]=='H')){   // style Assemler, FFFFh
    15.      a1=0; a2=size-2;
    16.      digit_capacity=16;
    17.    }
    18.    else if(size>0){     // десятичная система
    19.      a1=0; a2=size-1;
    20.      digit_capacity=10;
    21.    }
    22.   else
    23.   // преобразование не удалось!
    24.   return false;
    25.    u32   num=0;
    26.    u32   zzz=1;
    27.    for(int i=a2; i>=a1; --i)
    28.    {
    29.      int     digit;
    30.      char   ch=str[i];
    31.      if(ch>='0' && ch<='9')
    32.        digit=ch-'0';
    33.      else if (ch>='a' && ch<='f')
    34.        digit=ch-'a'+10;
    35.      else if (ch>='A' && ch<='F')
    36.        digit=ch-'A'+10;
    37.      else
    38.        digit=digit_capacity;
    39.   if (digit>=digit_capacity)
    40.   // преобразование не удалось!
    41.      return false;
    42.   num += digit*zzz;
    43.   zzz *= digit_capacity;
    44.    };
    45.    param=num;
    46.    return true;
    47. }
    Получается типа так:
    Код (C++):
    1.  
    2. if(Str2Int(str1, param)){
    3.     a=b+param;
    4. }else{
    5.     printf("FAIL str1[%s]\n", str1);
    6. }
    Правда С++ отказывается компилить если входящий тип int.
    Кто подскажет как это пофиксить? Кодирую на плясплясах совсем не давно.
     
  7. SadKo

    SadKo Владимир Садовников

    Публикаций:
    8
    Регистрация:
    4 июн 2007
    Сообщения:
    1.610
    Адрес:
    г. Санкт-Петербург
    Есть три варианта:
    1. Сделать метод шаблонным. Может привести к большому неуместному разрастанию кода везде, где используете шаблонный метод.
    2. Сделать свою реализацию для каждого типа данных (перегрузить метод). Приводит к большому дублированию кода. Однако если сделать перегрузку + локализовать вариант 1, то получится, что не придётся повторно писать код.
    3. Всегда передавать u32 на вход, дальше кастить уже к int.
    4. Вариант 2, но более c-style: сделать реализацию для самого большого числа, остальные перегруженные методы вызывают эту реализацию, но затем делают каст к нужному типу данных.
     
  8. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    562
    SadKo, а не сложно слишком? В С++ можно так вроде Str2Int(str1, (int*)param) прочитать как int, я пока не имею опыт работы в великом и ужасном Сплюсплюс или пляспляс. Код изначально написан в паскале, и как мог портировал в С++.
     
  9. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    562
    Вот как можно:
    Код (C++):
    1. int     param;
    2. Str2Int(str, (*(unsigned*)(&param)))
     
  10. rmn

    rmn Well-Known Member

    Публикаций:
    0
    Регистрация:
    23 ноя 2004
    Сообщения:
    2.329
    Intro,
    можно и просто:
    Код (C):
    1.  
    2. int param;
    3. Str2Int (str, (u32)param);
    4.  
    Главное помнить, что приводить можно только типы одного размера или из меньшего в больший.
     
  11. Intro

    Intro Active Member

    Публикаций:
    0
    Регистрация:
    29 авг 2009
    Сообщения:
    562
    Оптимизированный вариант для МАСМа.
    Код (ASM):
    1. __Str2Int_BIN_QUAT_OCT__     equ <>
    2. __Str2Int_MINUS__         equ <>
    3.  
    4. align_proc
    5. Str2Int proc uses edi esi ebx str0:LPCSTR, param:dword
    6. IFDEF __Str2Int_MINUS__
    7. local minus:byte
    8. ENDIF
    9.    ASSUME   esi:ptr byte, edi:ptr byte
    10.    ; esi - str_begin   LPCSTR   // указатель на начало строки
    11.    ; edi - str_end     LPCSTR   // указатель на конец строки
    12.    mov     esi, str0
    13.    test   esi, esi
    14.    jz     exit_fail
    15.    ; (eax)size0=strlen(str0);
    16.    @STRLEN (esi)
    17.    lea     edi, [esi+eax-1]
    18.    ;-------------------
    19. IFDEF __Str2Int_MINUS__
    20.    .if (eax>1 && [esi]=='-')
    21.      mov     minus, true
    22.      .repeat
    23.        inc     esi
    24.        dec     eax
    25.      .until ([esi]!=' ' && [esi]!=9) ; минус можно разделять пробелом или табулятором
    26.    .else
    27.      mov     minus, false
    28.    .endif
    29. ENDIF
    30.    ;// if (eax==0) goto exit_fail
    31.    test   eax, eax
    32.    jz     exit_fail
    33.    xor     ebx, ebx
    34.    mov     bl, 16
    35.    .if ([esi]=='0')
    36.      inc     esi
    37.      mov     al, [esi]
    38.      or     al, 20h
    39.      .if (al=='x')       ; style C, 0xFFFF
    40.        inc     esi
    41.      .endif
    42.    .elseif ([esi]=='$')     ; style Pascal, $FFFF
    43.      inc     esi
    44.    .else
    45.      mov     al, [edi]
    46.      or     al, 20h     ; Преобразуем в строчную букву.
    47.      .if (al=='h')       ; style Assemler, FFFFh
    48.        dec     edi
    49. IFDEF __Str2Int_BIN_QUAT_OCT__
    50.      .elseif (al=='o')     ; style Assemler, 7777o
    51.        dec     edi
    52.        mov     bl, 8
    53.      .elseif (al=='v')     ; style Assemler, 3333v quaternary system, четверичная система
    54.        dec     edi
    55.        mov     bl, 4  
    56.      .elseif (al=='b')     ; style Assemler, 1111b
    57.        dec     edi
    58.        mov     bl, 2
    59. ENDIF
    60.      .else           ; десятичная система, 9999
    61.        mov     bl, 10
    62.      .endif
    63.    .endif
    64.    .if (esi<=edi)   ; если размер число = 0 то exit_fail
    65.      ; (ecx)num = 0;
    66.      xor     ecx, ecx
    67.      ; (edx)zzz = 1;
    68.      xor     edx, edx
    69.      inc     edx
    70.      ; for(; it>=it_end; --it)
    71.      .while (edi>=esi)
    72.        ; int     eax, al = digit, bt;
    73.        ; al = *esi++
    74.        movzx   eax, [edi]
    75.        sub     al, '0'       ;'0'=48, '9'=57, 'A'=65, 'F'=70, 'a'=97, 'f'=102
    76.        .if (al>9)
    77.          add     al, '0'-1
    78.          and     al, 11011111b     ;0DFh Преобразуем в прописную букву.
    79.          sub     al, 'A'-10-1
    80.        .endif
    81.        .if (eax>=ebx)   ;(digit>=digit_capacity)
    82.          jmp     exit_fail
    83.        .endif
    84.        ;num += digit*zzz;
    85.        imul   eax, edx
    86.        add     ecx, eax
    87.        ;zzz *= digit_capacity;
    88.        imul   edx, ebx
    89.        dec     edi
    90.      .endw
    91. IFDEF __Str2Int_MINUS__
    92.      .if (minus)
    93.        neg     ecx
    94.      .endif
    95. ENDIF
    96.      ;*param = num;
    97.      mov     eax, param
    98.      mov     [eax], ecx
    99.      ; return true     ;// успешно
    100.      mov     al, true
    101.      jmp     exit_func
    102.    .endif
    103. exit_fail:
    104.    ;// преобразование не удалось!
    105.    ; return false;
    106.    xor     al, al
    107. exit_func:
    108.    ASSUME   esi:nothing, edi:nothing
    109.    ret
    110. Str2Int endp
    В цикле удалось уменьшить количество условных переходов с семи до двух, что хорошо повышает быстродействие. Так же для асма стиля добавлено четверичная система, префикс v, хотел использовать q, но он занят, (v это vier - четыре, немецкий язык).
    Стиль кода оптимизирован для лёгкого портирования в С код.
    А сам код оптимизирован на минимальный размер.
     
    Последнее редактирование: 8 апр 2018
  12. HESH

    HESH Active Member

    Публикаций:
    2
    Регистрация:
    20 мар 2008
    Сообщения:
    143
  13. Thetrik

    Thetrik UA6527P

    Публикаций:
    0
    Регистрация:
    25 июл 2011
    Сообщения:
    861