Нет ли случайно в виндовс апи функции, переводящей строку с десятичным или шестнадцатеричным числом в дворд, например?
msvcrt.dll динамически подгрузи. sscanf и всё-такое. Или в 6 студии компиль c динамическим рантаймом. strtoul тамже.
Код (Text): for(DWORD i=0;i<strlen(hex);i++) { if(hex[i] >= '0' && hex[i] <= '9') { Decoded += (hex[i] - 0x30) * (1 << ( (strlen(hex) - i - 1) * 4) ); } else if(hex[i] >= 'A' && hex[i] <= 'F') { Decoded += (hex[i] - 0x37) * (1 << ( (strlen(hex) - i - 1) * 4) ); } else if(hex[i] >= 'a' && hex[i] <= 'f') { Decoded += (hex[i] - 0x57) * (1 << ( (strlen(hex) - i - 1) * 4) ); } else { ParserError("Can't decode hex value.\n"); } }
Перевод строки из десятеричных цифр в DWORD автор The Svin взято здесь Код (ASM): OPTION PROLOGUE:NONE OPTION EPILOGUE:NONE atodw proc FORCENOFRAME ;---------------------------------------- ; перевод десятеричной строки в число типа dword ; значение возвращается в регистре eax ;---------------------------------------- ; String EQU [esp+4] mov edx, [esp+4] xor eax, eax cmp BYTE PTR [edx], 2Eh sbb [esp+4], edx adc edx, eax jmp @F again: lea eax, [eax+4*eax] inc edx lea eax, [ecx+2*eax-30h] @@: movzx ecx, BYTE PTR [edx] cmp BYTE PTR [edx], 30h jns again add eax, [esp+4] xor eax, [esp+4] retn 4 atodw ENDP OPTION PROLOGUE:DefaultOption OPTION EPILOGUE:DefaultOption1 Перевод строки из шестнадцатеричных цифр в число типа DWORD с использованием MMX автор bitRAKE, взято здесь Код (ASM): StrHex2bin PROC _CONST SEGMENT lpString db "89aBcDeF" _CONST ENDS movq mm0,QWORD PTR [lpString] psubusb mm0,mxc(<30>) ; "0" = 0 movq mm1,mm0 pcmpgtb mm1,mxc(<09>) ; letter? pand mm1,mxc(<07>) psubusb mm0,mm1 ; fix letters movq mm1,mm0 ; 0F0E0D0C0B0A0908 pand mm0,mxc(<0F00>) ; 0E000C000A000800 pand mm1,mxc(<000F>) ; 000F000D000B0009 psrlq mm0,8 ; 000E000C000A0008 packuswb mm1,mm1 ; 0F0D0B09 packuswb mm0,mm0 ; 0E0C0A08 psllq mm1,4 ; F0D0B090 por mm0,mm1 ; FEDCBA98 movd eax,mm0 ; FEDCBA98 bswap eax ; 89ABCDEF ret StrHex2bin ENDP Перевод строки из шестнадцатеричных цифр в число типа DWORD автор The Svin, взято здесь Используются только строчные буквы (ABCDEF) Модуль написан в формате masm32.inc. При использовании описывайте прототип как htodwc proto WORD Код (ASM): ; ######################################################################### ; -------------------------------------- ; This procedure was written by Svin ; -------------------------------------- .386 .model flat, stdcall ; 32 bit memory model option casemap :none ; case sensitive .code ; ######################################################################### OPTION PROLOGUE:NONE OPTION EPILOGUE:NONE htodwc proc FORCENOFRAME push ebx xor eax,eax mov ebx,[esp+8] xor edx,edx @@: mov dl,[ebx] ;1 shl eax,4 ;0 cmp dl,41h ;1 inc ebx ;0 sbb cl,cl ;1 sub dl,'A'-0Ah ;0 and cl,7 ;1 add dl,cl ;1 cmp byte ptr [ebx],0 ;0 lea eax,[eax][edx] ;1 jne @B ;1 pop ebx ret 4 htodwc endp OPTION PROLOGUE:DEFAULTOPTION OPTION EPILOGUE:DEFAULTOPTION end
Бывает что строка не содержит корректный код числа, что тогда делать? Я, вот, решил так. Код (C++): bool Str2Int(LPCSTR str, u32& param) { int size = string_length(str); int a1, a2, digit_capacity; if(size>2 && str[0]=='0' && (str[1]=='x' || str[1]=='X')){ // style C, 0xFFFF a1=2; a2=size-1; digit_capacity=16; } else if(size>1 && str[0]=='$'){ // style Pascal, $FFFF a1=1; a2=size-1; digit_capacity=16; } else if(size>1 && (str[size-1]=='h' || str[size-1]=='H')){ // style Assemler, FFFFh a1=0; a2=size-2; digit_capacity=16; } else if(size>0){ // десятичная система a1=0; a2=size-1; digit_capacity=10; } else // преобразование не удалось! return false; u32 num=0; u32 zzz=1; for(int i=a2; i>=a1; --i) { int digit; char ch=str[i]; if(ch>='0' && ch<='9') digit=ch-'0'; else if (ch>='a' && ch<='f') digit=ch-'a'+10; else if (ch>='A' && ch<='F') digit=ch-'A'+10; else digit=digit_capacity; if (digit>=digit_capacity) // преобразование не удалось! return false; num += digit*zzz; zzz *= digit_capacity; }; param=num; return true; } Получается типа так: Код (C++): if(Str2Int(str1, param)){ a=b+param; }else{ printf("FAIL str1[%s]\n", str1); } Правда С++ отказывается компилить если входящий тип int. Кто подскажет как это пофиксить? Кодирую на плясплясах совсем не давно.
Есть три варианта: 1. Сделать метод шаблонным. Может привести к большому неуместному разрастанию кода везде, где используете шаблонный метод. 2. Сделать свою реализацию для каждого типа данных (перегрузить метод). Приводит к большому дублированию кода. Однако если сделать перегрузку + локализовать вариант 1, то получится, что не придётся повторно писать код. 3. Всегда передавать u32 на вход, дальше кастить уже к int. 4. Вариант 2, но более c-style: сделать реализацию для самого большого числа, остальные перегруженные методы вызывают эту реализацию, но затем делают каст к нужному типу данных.
SadKo, а не сложно слишком? В С++ можно так вроде Str2Int(str1, (int*)param) прочитать как int, я пока не имею опыт работы в великом и ужасном Сплюсплюс или пляспляс. Код изначально написан в паскале, и как мог портировал в С++.
Intro, можно и просто: Код (C): int param; Str2Int (str, (u32)param); Главное помнить, что приводить можно только типы одного размера или из меньшего в больший.
Оптимизированный вариант для МАСМа. Код (ASM): __Str2Int_BIN_QUAT_OCT__ equ <> __Str2Int_MINUS__ equ <> align_proc Str2Int proc uses edi esi ebx str0:LPCSTR, param:dword IFDEF __Str2Int_MINUS__ local minus:byte ENDIF ASSUME esi:ptr byte, edi:ptr byte ; esi - str_begin LPCSTR // указатель на начало строки ; edi - str_end LPCSTR // указатель на конец строки mov esi, str0 test esi, esi jz exit_fail ; (eax)size0=strlen(str0); @STRLEN (esi) lea edi, [esi+eax-1] ;------------------- IFDEF __Str2Int_MINUS__ .if (eax>1 && [esi]=='-') mov minus, true .repeat inc esi dec eax .until ([esi]!=' ' && [esi]!=9) ; минус можно разделять пробелом или табулятором .else mov minus, false .endif ENDIF ;// if (eax==0) goto exit_fail test eax, eax jz exit_fail xor ebx, ebx mov bl, 16 .if ([esi]=='0') inc esi mov al, [esi] or al, 20h .if (al=='x') ; style C, 0xFFFF inc esi .endif .elseif ([esi]=='$') ; style Pascal, $FFFF inc esi .else mov al, [edi] or al, 20h ; Преобразуем в строчную букву. .if (al=='h') ; style Assemler, FFFFh dec edi IFDEF __Str2Int_BIN_QUAT_OCT__ .elseif (al=='o') ; style Assemler, 7777o dec edi mov bl, 8 .elseif (al=='v') ; style Assemler, 3333v quaternary system, четверичная система dec edi mov bl, 4 .elseif (al=='b') ; style Assemler, 1111b dec edi mov bl, 2 ENDIF .else ; десятичная система, 9999 mov bl, 10 .endif .endif .if (esi<=edi) ; если размер число = 0 то exit_fail ; (ecx)num = 0; xor ecx, ecx ; (edx)zzz = 1; xor edx, edx inc edx ; for(; it>=it_end; --it) .while (edi>=esi) ; int eax, al = digit, bt; ; al = *esi++ movzx eax, [edi] sub al, '0' ;'0'=48, '9'=57, 'A'=65, 'F'=70, 'a'=97, 'f'=102 .if (al>9) add al, '0'-1 and al, 11011111b ;0DFh Преобразуем в прописную букву. sub al, 'A'-10-1 .endif .if (eax>=ebx) ;(digit>=digit_capacity) jmp exit_fail .endif ;num += digit*zzz; imul eax, edx add ecx, eax ;zzz *= digit_capacity; imul edx, ebx dec edi .endw IFDEF __Str2Int_MINUS__ .if (minus) neg ecx .endif ENDIF ;*param = num; mov eax, param mov [eax], ecx ; return true ;// успешно mov al, true jmp exit_func .endif exit_fail: ;// преобразование не удалось! ; return false; xor al, al exit_func: ASSUME esi:nothing, edi:nothing ret Str2Int endp В цикле удалось уменьшить количество условных переходов с семи до двух, что хорошо повышает быстродействие. Так же для асма стиля добавлено четверичная система, префикс v, хотел использовать q, но он занят, (v это vier - четыре, немецкий язык). Стиль кода оптимизирован для лёгкого портирования в С код. А сам код оптимизирован на минимальный размер.