Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: 85 en 22 Febrero 2013, 03:32 am



Título: ATOI + ITOA remake
Publicado por: 85 en 22 Febrero 2013, 03:32 am
EDITADO
SE AGREGARON VERSIONES MEJORADAS PARA NO HACER USO DE TABLAS, NI DE FUNCIONES INNECESARIAS COMO LOG, POW, STRLEN, de CTYPE, de STRING, etc
SIN ASIGNACIONES DINÁMICAS, y USANDO MACROS PARA HACER EL CÓDIGO MÁS LEGIBLE..

//////////////////

Estaba repasando un poco cómo había hecho las implementaciones personales de estas funciones,
http://foro.elhacker.net/programacion_cc/atoi_itoa_personalizadas-t358459.0.html;msg1734670#msg1734670

..pero antes de hacer una implementación lo primero es saber como funciona realmente la original.. en base a esto es que decidí arreglar estas funciones siguiendo la misma lógica de construcción, que por cierto es una que suelo usar seguido.

Empezando por ATOI
Código
  1. /********************************************************************************************************
  2.  
  3. // By 85
  4. // boyscout_arg@hotmail.com
  5. // etalking.com.ar
  6. // David Riedel
  7. // 2013
  8.  
  9. *********************************************************************************************************/
  10.  
  11. #pragma warning (disable:4305)
  12. #pragma warning (disable:4309)
  13. #pragma warning (disable:4244)
  14. #pragma warning (disable:4018)
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18.  
  19. /////
  20.  
  21. // Sin necesidad de llamadas innecesarias a funciones de CTYPE, MATH, STRING, etc
  22. // Sin necesidad de Tablas, solo un array con los números enteros que tampoco es necesario
  23. // pero no hace la gran diferencia ;-D
  24.  
  25. //////////////////////////////////////////////////
  26.  
  27. //Se requiere pasar una cadena terminada en CERO!.
  28. //Si no se le pasa una cadena terminada en CERO, la función va a buscar el
  29. //primer 0 que encuentre y puede terminar en una sección de memoria contigua
  30. //que no pertenece a la cadena pasada como parámetro.
  31. int mi_atoi(const char* str)//Respetar el tipo de parámetro (Sólo cadenas)
  32. {
  33. int len, ocurrencias =0, sig=0;
  34. for(len=0; str[len]; len++);
  35. for(int a=0; a<len;a++) if((str[a]>=48&&str[a]<=57)) ocurrencias++;
  36. if(ocurrencias==0) return 0;
  37. if((sig=str[0]=='+')||(sig=str[0]=='-')) ocurrencias+=1;
  38. if(ocurrencias<len) return 0;//Casos "11f" son 0
  39. if(len==1) return str[0]-'0';
  40. int ac=0, v1, cifras = len,m = 1;
  41. for(int x=0;x<((cifras-1)-sig);x++) m*=10;
  42. for(int i=sig;i<cifras;i++){//Factoriza y acumula
  43. v1=str[i]-'0';
  44. v1*=m;
  45. ac+=v1;
  46. m/=10;
  47. }
  48. if(str[0]=='-') ac*=-1;
  49. return ac;
  50. }
  51.  
  52. ////////////////////
  53.  
  54. int main(){
  55.  
  56. // char str = 'B';
  57. // int entero = mi_atoi(&str);
  58.  
  59. // char* str = "asdasd\0";
  60. // int entero = mi_atoi(str);
  61.  
  62. // char* str = "8a3\0";
  63. // int entero = mi_atoi(str);
  64.  
  65. // char* str = "83312321\0";
  66. // int entero = mi_atoi(str);
  67.  
  68. // char* str = "000000099\0";
  69. // int entero = mi_atoi(str);
  70.  
  71. // char* str = "9\0";
  72. // int entero = mi_atoi(str);
  73.  
  74. // char* str = "20\0";
  75. // int entero = mi_atoi(str);
  76.  
  77. // char* str = "500\0";
  78. // int entero = mi_atoi(str);
  79.  
  80. // char* str = "+500\0";
  81. // int entero = mi_atoi(str);
  82.  
  83. // char* str = "0500\0";
  84. // int entero = mi_atoi(str);
  85.  
  86. // char* str = "0\0";
  87. // int entero = mi_atoi(str);
  88.  
  89. // char* str = "10f\0";
  90. // int entero = mi_atoi(str);
  91.  
  92. // char* str = "01ff\0";
  93. // int entero = mi_atoi(str);
  94.  
  95. // char* str = "0f\0";
  96. // int entero = mi_atoi(str);
  97.  
  98. // char* str = "+12\0";
  99. // int entero = mi_atoi(str);
  100.  
  101. // char* str = "+12\0";
  102. // int entero = mi_atoi(str);
  103.  
  104. // char* str = "03232\0";
  105. // int entero = mi_atoi(str);
  106.  
  107. // printf("%d", entero);
  108.  
  109.  
  110. printf("%d\n",mi_atoi("-110"));
  111. printf("%d\n",mi_atoi("-10"));
  112. printf("%d\n",mi_atoi("0"));
  113. printf("%d\n",mi_atoi("1"));
  114. printf("%d\n",mi_atoi("-1"));
  115. printf("%d\n",mi_atoi("-11"));
  116. printf("%d\n",mi_atoi("-2"));
  117. printf("%d\n",mi_atoi("-200"));
  118. printf("%d\n",mi_atoi("-220"));
  119. printf("%d\n",mi_atoi("+0"));
  120. printf("%d\n",mi_atoi("-0"));
  121. printf("%d\n",mi_atoi("+1"));
  122. printf("%d\n",mi_atoi("+33"));
  123. printf("%d\n",mi_atoi("-330"));
  124. printf("%d\n",mi_atoi("-3000"));
  125. // printf("%d\n",mi_atoi("-1"));
  126. // printf("%d\n",mi_atoi("-200"));
  127. // printf("%d\n",mi_atoi("-220"));
  128. printf("%d\n",mi_atoi("+12"));
  129.  
  130. printf("\n");
  131. system("pause");
  132. return 0;
  133. }
  134.  

El problema que enfrenta esta función es cuando alguien trata de pasarle un parámetro que no es una cadena, por ejemplo un 'char'

Código:
char str = 'B';
int entero = mi_atoi(&str);

se lo hace de esa forma especificando la dirección de la variable, pero en la función original ATOI esto devuelve 0, según mis pruebas.

y al respecto revisaba también unos post en los cuales se hablaba acerca de la utilidad del operador ternario, como se puede observar son muy útiles para usarlos como índices en matrices y vectores.

http://foro.elhacker.net/programacion_cc/calcular_el_maximo_usando_operador-t383707.0.html
http://foro.elhacker.net/programacion_cc/aporte_operador_condicional-t383420.0.html

Código:
int tab1[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
val1 =  tab1[(str[i]=='0' ? 9:(((int)str[i]-48)-1))];

para los principiantes les explico que la evaluación que se hace es que si el caractér es 0 se procede a usar el número 9 como índice, de otra forma se usa otro índice..

Bueno y la implementación de ITOA es esta:
Código
  1. /********************************************************************************************************
  2.  
  3. // By 85
  4. // boyscout_arg@hotmail.com
  5. // etalking.com.ar
  6. // David Riedel
  7. // 2013
  8.  
  9. *********************************************************************************************************/
  10.  
  11. #pragma warning (disable:4305)
  12. #pragma warning (disable:4309)
  13. #pragma warning (disable:4244)
  14. #pragma warning (disable:4018)
  15. #include <windows.h>
  16. #include <stdlib.h>
  17. #include <stdio.h>
  18.  
  19. /////
  20.  
  21. // Sin necesidad de llamadas innecesarias a funciones de CTYPE, MATH, STRING, etc
  22. // Sin necesidad de Tablas, sólo un array con los números enteros que tampoco es necesario
  23. // pero no hace la gran diferencia ;-D
  24.  
  25. //////////////////////////////////////////////////
  26.  
  27. char* mi_itoa(int num, char* str)
  28. {
  29. int sig = -1;
  30. if(num<0){
  31. num*=-1;
  32. if(num<10){
  33. str[0]='-'; str[1]='0'+num; str[2]=0; return str;
  34. } else {
  35. sig=1;
  36. }
  37. }
  38. else if(num==0){
  39. str[0]='0'; str[1]=0; return str;
  40. } else {
  41. if(num<10){
  42. str[0]='0'+num; str[1]=0; return str;
  43. } else {
  44. sig=0;
  45. }
  46. }
  47. if(sig!=-1){
  48. int copia= num, m = 1, cifras = 1;
  49. for(;copia>=10;copia/=10) cifras++;
  50. for(int x=0;x<(cifras-1);x++) m*=10;
  51. float v1=num;
  52. int v2=0, v3=num;
  53. if(sig) str[0]='-';
  54. for(int i=0; i<cifras; i++){//Descompone en factores
  55. v1/=m;
  56. v2=(int)v1*m;
  57. v3-=v2;
  58. m/=10;
  59. str[i+sig]=48+(int)v1;
  60. v1=v3;
  61. }
  62. str[i+sig]=0;//Si str está a 0 no es necesario..
  63. }
  64. return str;
  65. }
  66.  
  67. ///////////////////
  68.  
  69. int main(){
  70.  
  71.  
  72. char str[256];
  73.  
  74. // mi_itoa(321312,str);
  75. // printf(str);
  76.  
  77. // itoa(02321,str,10);
  78. // printf(str);
  79.  
  80. // mi_itoa(02321,str);
  81. // printf(str);
  82.  
  83. // mi_itoa(-12321,str);
  84. // printf(str);
  85.  
  86. // itoa(-012321,str,10);
  87. // printf(str);
  88.  
  89. // mi_itoa(-012321,str,10);
  90. // printf(str);
  91.  
  92. // mi_itoa(555,str);
  93. // printf(str);
  94.  
  95. // mi_itoa(0,str);
  96. // printf(str);
  97.  
  98. // mi_itoa(1,str);
  99. // printf(str);
  100.  
  101. // mi_itoa(500,str);
  102. // printf(str);
  103.  
  104. printf(mi_itoa(+321312,str));printf("\n");
  105. printf(mi_itoa(-321312,str));printf("\n");
  106. printf(mi_itoa(321312,str));printf("\n");
  107. printf(mi_itoa(+0,str));printf("\n");
  108. printf(mi_itoa(0,str));printf("\n");
  109. printf(mi_itoa(-0,str));printf("\n");
  110. printf(mi_itoa(+1,str));printf("\n");
  111. printf(mi_itoa(1,str));printf("\n");
  112. printf(mi_itoa(-1,str));printf("\n");
  113. printf(mi_itoa(10,str));printf("\n");
  114. printf(mi_itoa(+10,str));printf("\n");
  115. printf(mi_itoa(-10,str));printf("\n");
  116. printf(mi_itoa(-110,str));printf("\n");
  117. printf(mi_itoa(-100,str));printf("\n");
  118.  
  119. printf(mi_itoa(-5000,str));printf("\n");
  120. printf(mi_itoa(-55555,str));printf("\n");
  121. printf(mi_itoa(550,str));printf("\n");
  122. printf(mi_itoa(500,str));printf("\n");
  123. printf(mi_itoa(+330,str));printf("\n");
  124.  
  125. printf(mi_itoa(-000,str));printf("\n");
  126. printf(mi_itoa(+000,str));printf("\n");
  127. // printf(mi_itoa(+00009,str));printf("\n");
  128. printf(mi_itoa(+109,str));printf("\n");
  129. printf(mi_itoa(-109,str));printf("\n");
  130. // printf(mi_itoa(-09,str));printf("\n");
  131. // printf(mi_itoa(+09,str));printf("\n");
  132. printf(mi_itoa(-999,str));printf("\n");
  133. // printf(mi_itoa(-00000999,str));printf("\n");
  134.  
  135. printf("\n");
  136. system("pause");
  137. return 0;
  138. }
  139.  
  140. /////
  141.  
  142.  

cualquier problema diganme, sólo trataba de crear un par de funciones que funcionen tal cual las originales, y usando la misma lógica que venía usando.

les dejo el proyecto en MSVC++ 6 ya que es el compilador que tengo para esta clase de minipruebas, tengo el 2010 también..

http://www.mediafire.com/?wbscy4bu2vrq273


Título: Re: ATOI + ITOA remake
Publicado por: rir3760 en 23 Febrero 2013, 18:21 pm
El problema que enfrenta esta función es cuando alguien trata de pasarle un parámetro que no es una cadena, por ejemplo un 'char'
Código:
char str = 'B';
int entero = mi_atoi(&str);
La función atoi no puede conocer a prior si se pasa la dirección de una cadena o un carácter, esta literalmente confía en que sera usada correctamente. En otras palabras no tienes que preocuparte ya que eso es responsabilidad de quien llama a tu función.

se lo hace de esa forma especificando la dirección de la variable, pero en la función original ATOI esto devuelve 0, según mis pruebas.
El comportamiento de atoi es el siguiente:
1) Se descarta el espacio blanco.
2) Se procesa el signo.
3) Se procesan los dígitos hasta encontrar un carácter no valido.

Si por lo menos se procesa un dígito se retorna el numero, caso contrario la función debe retornar cero. No es lo ideal ya que ante una cadena como "123JKL" la función retorna 123 pero bueno, esa es su especificación.

----

En tus funciones no es necesario utilizar tablas. Para obtener el entero o carácter correspondiente solo debes sumar (o restar, dependiendo del caso) el valor '0':
Código:
'0' + Digito == '0', '1', '2', ... /* Digito == 0, 1, 2, ... */
Caracter - '0' == 0, 1, 2, ... /* Caracter == '0', '1', '2', ...*/

----

Una implementación de la función atoi con el comportamiento indicado:
Código
  1. #include <ctype.h>
  2.  
  3. int fn_atoi(const char *p)
  4. {
  5.   int num = 0;
  6.   int sign = 1;
  7.  
  8.   while (isspace(*p))
  9.      p++;
  10.  
  11.   if (*p == '-'){
  12.      sign = -1;
  13.      p++;
  14.   }else if (*p == '+')
  15.      p++;
  16.  
  17.   while (isdigit(*p)){
  18.      num = num * 10 + *p - '0';
  19.      p++;
  20.   }
  21.  
  22.   return sign * num;
  23. }

Y una implementación de itoa (que por cierto no es parte de la biblioteca estándar de C) es:
Código
  1. #include <math.h>
  2.  
  3. char *fn_itoa(int num, char *str)
  4. {
  5.   char *p = str + 1;
  6.  
  7.   if (num < 0){
  8.      *str = '-';
  9.      num = -num;
  10.      p++;
  11.   }
  12.  
  13.   if (num >= 10)
  14.      p += (int) log10(num);
  15.  
  16.   *p = '\0';
  17.   do {
  18.     *--p = '0' + num % 10;
  19.   }while ((num /= 10) > 0);
  20.  
  21.   return str;
  22. }

Un saludo


Título: Re: ATOI + ITOA remake
Publicado por: 85 en 24 Febrero 2013, 00:19 am
Aún se puede cambiar las CTYPE por algo como
Citar
>=48&&<=57
, evitaríamos código extra

la tabla no es realmente necesaria es cierto, viene quedando de anteriores versiones; me gusta la ITOA como quedó

Saludos


Título: Re: ATOI + ITOA remake
Publicado por: rir3760 en 24 Febrero 2013, 01:56 am
Aún se puede cambiar las CTYPE por algo como
Citar
>=48&&<=57
, evitaríamos código extra
No porque sin un motivo de peso se afectaría la claridad en el código fuente. En la misma linea mejor evitar el uso de 48 y 57 sustituyendo estos por '0' y '9', el valor es el mismo con la ventaja de indicar el contexto (proceso de caracteres).

Casi lo olvido, bucles como este:
Código
  1. int copia = num;
  2. int unidades_decimales = 1;// unidad de 1
  3. while(1)
  4. {
  5. if(copia>=10)
  6. {
  7. copia /= 10;
  8. unidades_decimales++;
  9. }
  10. else
  11. {
  12. break;
  13. }
  14. }
Los puedes reducir a:
Código
  1. int unidades_decimales = 1;
  2. int copia;
  3. for (copia = num; copia >= 10; copia /= 10)
  4.   unidades_decimales++;

Por ultimo, ¿Estas aprendiendo C en base a un buen libro? Si todavía no tienes uno de calidad te recomiendo "The C Programming Language" o bien "Pointers on C", puedes obtener mas información sobre ellos mediante el motor de búsqueda de los foros.

Un saludo


Título: Re: ATOI + ITOA remake
Publicado por: 85 en 24 Febrero 2013, 02:14 am
EDITADO: Discusión no objetiva

Amigo te cuento algo,

esto:
Citar
>=48&&<=57


SI, lo deberías usar ya que te vuelvo a decir SI es necesario si te gusta optimizar las cosas.
no es necesario que hagás un salto a una rutina en otra parte para ejecutar un código innecesario,
sabiendo que comparando algo directamente así:

Pseudocódigo
Citar
if(>=48&&<=57);
else NO ES UN ESPACIO NI CUALQUIER OTRA COSA SINO SÓLO NÚMEROS


Esto:
Código:
while(1)
{
if(copia>=10)
{
copia /= 10;
unidades_decimales++;
}
else
{
break;
}
}

Y esto:
Código:
int unidades_decimales = 1;
int copia;
for (copia = num; copia >= 10; copia /= 10)
   unidades_decimales++;

es lo mismo al traducirse a ASM ya que lo que vos plantéas es un cambio al nivel de TEXTO en el código humanizado o de alto nivel (C). Prestá atención que realizan las mismas operaciones y sino lo hicieran, termina siendo lo mismo porque el compilador te cuento que optimiza el código automáticamente, a lo máximo tal REDUCCiÓN termina siendo algo así como un par de instrucciones insignificantes:

Código:
push
push
call
.......
push ebp
mov ebp, esp

mov esp, ebp
pop ebp
retn

add esp, 0x8
y asumiento que no cambiás la convención de llamada a __stdcall o __fastcall, en cuyo caso la pila se limpia automáticamente por el código que hace la llamada (callee)


Título: Re: ATOI + ITOA remake
Publicado por: 0xDani en 24 Febrero 2013, 13:17 pm
@85, te estas equivocando, @rir3760 solo pretende ayudar, ha sido respetuoso y si que ha optimizado bastante tus codigos. Que te parezca que son mas dificiles de entender para una persona solo demuestra que te da mil vueltas codeando.

Si no puedes aceptar que mejoren un aporte que has hecho de forma constructiva, no se porque lo publicas.


Título: Re: ATOI + ITOA remake
Publicado por: Eternal Idol en 24 Febrero 2013, 16:02 pm
¿En que mensaje rir3760 menciono el termino optimizar? En ninguno. ¿Verdad? Eso lo dice todo 85, mejor revee tu postura, tu reaccion estuvo fuera de lugar y deberias agradecer por los datos concretos que te aportaron (vease que uno debe respetar el tipo de los parametros que se le pasan a una funcion).


Título: Re: ATOI + ITOA remake
Publicado por: 85 en 24 Febrero 2013, 17:57 pm

EDITADO: Discusión no objetiva

Dejando la discusión de lado, si vamos a hablar de optimizaciones en serio vayamos directamente al código ensamblador, porque jugar con palabras de código humanizado no representa precisamente una optimización para la PC, sino más bien para REDUCIR líneas de texto que dan la impresión VISUAL de una simplificación.

Encontré una versión en ASM, hecha por sk0r
Código:
__declspec(naked) int __stdcall m_atoi(char* szTarget, unsigned int dwLength)
{
#define SUB_OFFS 48

__asm {
push ebp; //Save old framepointer value
mov ebp, esp; //Copy ESP into EBP -> EBP:[Old-EBP:4][Ret-Addr:4][dwLength:4][szTarget:4]
sub esp, 5; //Allocate 5 bytes [EBP-4]: unsigned int dwResult, [EBP-5]:char cMinusChar
mov dword ptr [ebp-4], 0; //Zero bytes of dwResult value. dwResult holds entire result value
mov byte ptr[ebp-5], 0; //Zero byte of cMinusChar. cMinusChar holds first char @szTarget for '-' check

cmp szTarget, 0; //Check if szTarget is a null pointer
je fEnd; //If so goto function end
cmp dwLength, 0; //Check if string length is zero
je fEnd; //If so goto function end

//Save registers for use
push ebx; //Holds mulitplied value of current positon.
push ecx; //Used for loop cmd
push edx; //For saving temporary stuff
push esi; //Holds start address + length of string
pushf; //For modifying direction flag

mov ebx, 1; //Set to one. The first position is the ones, second tens, third hundrets, etc.
mov ecx, dwLength; //Copy length to ECX for counting

mov esi, szTarget; //Copy string address to ESI
add esi, ecx; //Add string length
dec esi; //Decrement not to go too far (because of zero position)

push eax; //Save EAX temorarly
mov eax, szTarget; //Copy string address to EAX
mov al, byte ptr[eax]; //Copy the first byte to AL
mov byte ptr[ebp-5], al; //Copy it to EBP-5 (cMinusChar)
pop eax; //Restore EAX

cmp byte ptr[ebp-5], '-'; //Check if the char is a minus char
jne fOvr1; //If not goto fOvr1
dec ecx; //Decrement, because we ignore the '-' char to not corrupt the entire number

fOvr1:
std; //Set direction flag to 1 to go from hight to low addresses
fLoop:
xor eax, eax; //Clear bits of EAX
lodsb; //Copy byte at [ESI] to AL and extend ESI (in this case decrement)
sub al, SUB_OFFS; //Substract offset to make from char to real number
mul ebx; //Multiplicate EAX with EBX depending on its current position. Ones with 1, Tens with 10, Hundrets with 100, etc.
mov edx, dword ptr[ebp-4]; //Copy entire result value to EDX
add edx, eax; //Add EAX on it
mov dword ptr [ebp-4], edx; //Copy back to result value

mov eax, ebx; //Copy EBX to EAX
mov ebx, 10; //Copy 10 to EBX
mul ebx; //Multiply with 10 to go to the next positon: 1*10 = 10, 10*10 = 100, 100*10 = 1000, etc
mov ebx, eax; //Copy back to EBX

loop fLoop; //Goto fLoop and decrement ECX if not already zero

cmp byte ptr[ebp-5], '-'; //Check if first char was '-'
jne fOvr2; //If not goto fOvr2
mov eax, [ebp-4]; //Copy result value to EAX
mov ebx, -1; //Copy -1 to EBX
imul ebx; //Make signed multiplication to make a positive value to a negative one
mov [ebp-4], eax //Copy back to result value

fOvr2:
//Restore all used registers
popf;
pop esi;
pop edx;
pop ecx;
pop ebx;

fEnd:
mov eax, dword ptr[ebp-4]; //Copy result value to EAX for result
add esp, 5; //Remove both stack variables
pop ebp; //Restore EBP
ret 8; //Restore Ret-Address and remove the 8 argument bytes
}
}


Título: Re: ATOI + ITOA remake
Publicado por: avesudra en 24 Febrero 2013, 19:04 pm
Hola, que yo sepa atoi ya no se usa pues está obsoleta e itoa no está definida en el estándar de C como decía rir3760 en lugar de todo ello habría que usar:
Código
  1. long int strtol (const char* str, char** endptr, int base);

Referencia: http://www.cplusplus.com/reference/cstdlib/strtol/
Información de atoi obsoleta en la página de la libc: http://www.gnu.org/software/libc/manual/html_node/Parsing-of-Integers.html

Y para itoa se puede usar esto(que lo único que arregla es la portabilidad):
Código
  1. int sprintf ( char * str, const char * format, ... );

En teoría lo de las conversiones de bases debería funcionar con esas funciones.

PD: Digo esto porque tiene poco sentido ponerse a reinventar atoi e itoa ( si es para aprender y practicar si lo tiene ) cuando estas no son usadas o no deberían usarse.

¡Un saludo!


Título: Re: ATOI + ITOA remake
Publicado por: 85 en 24 Febrero 2013, 19:11 pm
Muy cierto, en realidad no debí haber creado el topic XD ya que siempre alguien lo va a hacer de una forma diferente, o arreglando uno existente, habría miles de implementaciones y en muchos lenguajes. Pero aveces está bueno para el aprendizaje


Título: Re: ATOI + ITOA remake
Publicado por: rir3760 en 27 Febrero 2013, 04:07 am
El tema se inicia con el objetivo:
Cita de: 85
antes de hacer una implementación lo primero es saber como funciona realmente la original.. en base a esto es que decidí arreglar estas funciones siguiendo la misma lógica de construcción, que por cierto es una que suelo usar seguido.

Empezando por ATOI
En mi primer mensaje publique el comportamiento de esa funcion, un consejo para reducir las expresiones en tus programas y dos ejemplos. ¿La intencion de estos ultimos? Tener a la vista el codigo fuente de otros realizando la misma operacion, a partir de ahi ya tienes un punto de referencia.

Acabas de publicar dos nuevas versiones de los programas con un comentario que, para decirlo de una forma amable, preocupa:
Cita de: 85
SE AGREGARON VERSIONES MEJORADAS PARA NO HACER USO DE TABLAS, NI DE FUNCIONES INNECESARIAS COMO LOG, POW, STRLEN, de CTYPE, de STRING, etc SIN ASIGNACIONES DINÁMICAS, y USANDO MACROS PARA HACER EL CÓDIGO MÁS LEGIBLE
Si la intencion es desarrollar funciones propias con el mismo comportamiento que atoi (estandar) e itoa (extension) me temo que en el caso de la primera esta continua lejos del comportamiento indicado.

Esto lo puedes comprobar imprimiendo el resultado de atoi y tu version de ella, por ejemplo:
Código
  1. printf("%d, %d\n",  atoi("+123"),  mi_atoi("+123"));
  2. printf("%d, %d\n", atoi(" +123"), mi_atoi(" +123"));
  3. printf("%d, %d\n", atoi("  123"), mi_atoi("  123"));

Y al utilizar un array que para empezar no es necesario complicas las expresiones, un ejemplo de ello se da si la cadena a procesar es "0", la sentencia:
Código
  1. return tab1[((int)str[0]-48)-1];
Resulta en:
Código
  1. return tab1[-1];

Hay que eliminar el uso del array, de las macros y usar expresiones mejores, en el sentido de ser mas claras y con un minino de subexpresiones. Por ejemplo al expandirse una macro terminas con la expresion:
Código
  1. val1 = tab1[(int)(str[i]=='0' ? 9:(((int)str[i]-48)-1))]
Innecesariamente larga ya que se puede sustituir por:
Código
  1. val1 = str[i] - '0'

Por ultimo en el caso de las macros no entiendo porque piensas que hacen el codigo fuente mas legible cuando el efecto es el opuesto.

----

En cuanto a la funcion atoi los problemas aqui son un poco mas complejos. Para empezar las sentencias de retorno (salvo la ultima) estan demas debido a los condicionales.

Tambien debes analizar los dos bloques principales ya que salvo las dos operaciones en el caso de un numero negativo (almacenar el signo en la cadena y cambiarlo a positivo) son identicos. Aqui las dos opciones son restructurar la funcion para tener un solo bloque o bien crear una funcion.

Y como en el caso de la primera funcion hay que eliminar las macros.

Un saludo


Título: Re: ATOI + ITOA remake
Publicado por: 85 en 27 Febrero 2013, 04:14 am
Amí me preocupa que esos códigos que publicaste tengan partes parecidas a esto:
http://foro.elhacker.net/programacion_cc/atoi_itoa_personalizadas-t358459.0.html;msg1735068#msg1735068
A no ser que seas blackzero..

Mis modificaciones recientes no fueron probadas, sólamente se quitaron ciertas cosas que no son necesarias, tablas, funciones std, y otras cosas. La idea era quitar las tablas y los llamados innecesarios a funciones ajenas.
lamentable que no funcionen, si necesitás versiones funcionando usá las originales.

Otra cosa , las macros están hechas para simplificar y hacer el código más legible, entre otras cosas.. no se de qué libro aprendiste que no era así.
Todos sabemos que el código en las macros se copia adonde es invocada, no es en sí resumir código sino para simplificar el entendimiento.
No es lo mismo copiar 2 veces el código de la macro FACTORES, que poner 2 veces una sóla línea que diga FACTORES(). Me extraña que no lo entiendas porque eras el más interesado en resumir líneas de TEXTO..

Se entiende que el que usa la macro FACTORES la conoce, sabe su código, no necesita verlo repetido tantas veces. Si no entendés la macro no la uses porque en ese caso, si tenés razón, el código sería más ilegible.

Mi consejo entonces es que no uses macros que no entiendas..
Saludos.


EDITADO 1

hecha una revisión rápida del código, no estaba funcionando ni como las primeras versiones :/

atoi original ante esta situación:

"5f" o "11www"

devuelve 5 u 11

lo cual aunque parece tener sentido, mi función sólo devuelve 0
porque 11www no es 11.

para que cumpla con lo de pasar parámetros correctamente!

Por otro lado , comprueba el signo y guarda un resultado para usarse posteriormente a la hora de diferenciar entre significados y no:

Código:
int sig=0;
if((sig=str[0]=='+')||(sig=str[0]=='-'))
..

El índice que mostraste fue considerado como otra opción.
ITOA no fue mayormente revisada, sólo hice algunas pruebas generales, las que aparecen en el ENTRY. Tiene dos bloques de código bastante parecidos como muy bien notaste, y no estaría nada mal inventar algo para usar sólo un bloque de entre ambos.

Saludos

EDITADO 2

Decidí seguir tus sugerencias y quité el array y las macros.
Al mismo tiempo, ahora en MI_ITOA se usa 1 sólo bloque de procesamiento por factores.

Saludos




Título: Re: ATOI + ITOA remake
Publicado por: rir3760 en 27 Febrero 2013, 19:45 pm
Amí me preocupa que esos códigos que publicaste tengan partes parecidas a esto:
http://foro.elhacker.net/programacion_cc/atoi_itoa_personalizadas-t358459.0.html;msg1735068#msg1735068
A no ser que seas blackzero.
No, el es otro usuario con quien he tenido el gusto de conversar en algunos temas, por ejemplo [Ayuda] Error con delete[]... algo extraño... (http://foro.elhacker.net/programacion_cc/ayuda_error_con_delete_algo_extrano-t332814.0.html).

¿Que es lo que te preocupa?

Otra cosa , las macros están hechas para simplificar y hacer el código más legible, entre otras cosas.. no se de qué libro aprendiste que no era así.
De uno que te recomendé al principio del tema: "The C Programming Language" de Brian W. Kernighan y Dennis M. Ritchie.

Todos sabemos que el código en las macros se copia adonde es invocada, no es en sí resumir código sino para simplificar el entendimiento.
No es lo mismo copiar 2 veces el código de la macro FACTORES, que poner 2 veces una sóla línea que diga FACTORES(). Me extraña que no lo entiendas porque eras el más interesado en resumir líneas de TEXTO..
No. Yo estoy interesado en reducir el código fuente y eso no se consigue con macros (el numero de sentencias y expresiones es el mismo con o sin ellas). Ejemplos de ello los tienes en este tema, por ejemplo eliminar el array.

Se entiende que el que usa la macro FACTORES la conoce, sabe su código, no necesita verlo repetido tantas veces. Si no entendés la macro no la uses porque en ese caso, si tenés razón, el código sería más ilegible.

Mi consejo entonces es que no uses macros que no entiendas.
Primero me cuestionas con una Falacia del hombre de paja (http://es.wikipedia.org/wiki/Falacia_del_hombre_de_paja) y ahora con un Argumento ad hominem (http://es.wikipedia.org/wiki/Argumento_ad_hominem). Te aclaro: no respondo a ese tipo de comentarios.

Mi argumento es: la mayoría de tus macros no mejoran la claridad del código fuente como tampoco facilitan su desarrollo. Digo "la mayoría" y no "todas" porque haz estado actualizando tus programas.

Bueno, si piensas que mi argumento esta errado podemos discutirlo, no hay problema.

ITOA no fue mayormente revisada, sólo hice algunas pruebas generales, las que aparecen en el ENTRY. Tiene dos bloques de código bastante parecidos como muy bien notaste, y no estaría nada mal inventar algo para usar sólo un bloque de entre ambos.
OK. Solo una recomendación: coloca el código fuente de las funciones en un solo lugar (tu primer mensaje).

Un saludo