Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: NOB2014 en 31 Marzo 2014, 16:00 pm



Título: Descomponer un numero entero en lenguaje C.
Publicado por: NOB2014 en 31 Marzo 2014, 16:00 pm
Hola a todos y que tengan un muy buen dia.

Lenguaje………………....: “C”
Sistema operativo……: Windows XP
Compilador……………...: MinGW
Problema………………...: No puedo concluir el programa porque no logro mover
                                asía la izquierda los dígitos restantes e insertar el ‘\0’.-                                                   
Error………………………...: Ninguno.
Otras Observaciones: Para todo aquellos que tengan mucho tiempo, me
                                podrían indicar que debo cambiar para obtimizarlo .     
Código……………………..:

Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <string.h>
  5.  
  6. int verifica(char ingreso[], int ok, int longitud, int maxDescartar);
  7.  
  8. int main(){
  9. unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
  10. char digitos[12] = {'\0'}, cualDescartar[2] = {'\0'};
  11. printf("\n ---------- Programa que descompone un numero entero sin signo ----------");
  12. do{
  13. ok=0;
  14. printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
  15. fgets(digitos, longitud, stdin);
  16. ok = verifica(digitos, ok, longitud, i);
  17. }while(ok);
  18.  
  19. printf("\n\n");
  20. for(; digitos[i] != NULL; i++){
  21. printf(" [%d] = %c \n", i, digitos[i]);
  22. }
  23.  
  24. do{
  25. longitud=2;
  26. ok=0;
  27. printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
  28. fgets(cualDescartar, longitud, stdin);
  29. ok = verifica(cualDescartar, ok, longitud, i);
  30. }while(ok);
  31.  
  32. descartar = atoi(cualDescartar);
  33. //En este lugar va lo que me falta...
  34.  
  35. printf("\n\n");
  36. return 0;
  37. }
  38.  
  39.  
  40. int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
  41. long long temp=0, auxiliar=0;
  42. int ch=0, i=0, ingresoInt=0;
  43. char *p=NULL;
  44.  
  45. if((p=strchr(ingreso, '\n'))){
  46. *p='\0';
  47. }
  48. else{
  49. ingreso[longitud] = '\0';
  50. while((ch = getchar()) !='\n' && ch!=EOF);
  51. }
  52.  
  53. for(; ingreso[i] != NULL; i++){
  54. if(ingreso[i] <= 47 || ingreso[i] >= 58){
  55. ok=1;
  56. return ok;
  57. }
  58. }
  59.  
  60. if(longitud == 11){
  61. for(i=0; ingreso[i] != NULL; i++){
  62. auxiliar = ingreso[i] - 48;
  63. temp=10*temp+auxiliar;
  64. }
  65.  
  66. if(temp <= 99 || temp > UINT_MAX){
  67. ok=1;
  68. return ok;
  69. }
  70. }
  71. else{
  72. ingresoInt = atoi(ingreso);
  73. if(ingresoInt > maxDescartar){
  74. ok=1;
  75. return ok;
  76. }
  77. }
  78. return ok;
  79. }
  80.  
  81. /*
  82. sprintf(digitos, "%d", 56789);
  83. */

Saludos y muchas pero muchas gracias por el tiempo dedicado a este tema.-
Daniel


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: eferion en 31 Marzo 2014, 16:18 pm
Tienes que desplazar los caracteres desde "descartar"+1 a strlen(digitos) una posición hacia la izquierda y con eso has eliminado el carácter deseado.

La forma de hacerlo... un while, un for... como más te guste.


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: NOB2014 en 1 Abril 2014, 19:23 pm
Hola a todos y que tengan un muy buen día.-
Muchas gracias eferion por la orientación, ahora el caso es que funciona pero me queda una duda que me ha hecho practicar todo un día y tuve que hacer algo muy rebuscado porque de lo contrario me desaparecía el contenido de la variable digitos, si lo desean pueden correrlo sin la variable _digitos y con ella para ver lo que pasa, por favor si alguien encuentra el porqué le agradecería me lo diga para no dar esto por terminado y desconocer el error.-
     
Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <string.h>
  5.  
  6. int verifica(char ingreso[], int ok, int longitud, int maxDescartar);
  7.  
  8. int main(){
  9. unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
  10. char digitos[12] = {'\0'}, _digitos[12] = {'\0'}, cualDescartar[2] = {'\0'};
  11.  
  12. printf("\n ---------- Programa que descompone un numero entero sin signo ----------");
  13.  
  14. do{
  15. ok=0;
  16. printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
  17. fgets(digitos, longitud, stdin);
  18. ok = verifica(digitos, ok, longitud, i);
  19. }while(ok);
  20.  
  21. printf("\n\n");
  22.  
  23. for(; digitos[i] != NULL; i++){
  24. printf(" [%d] = %c \n", i, digitos[i]);
  25. }
  26.  
  27. do{
  28. longitud=2;
  29. ok=0;
  30. printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
  31. fgets(cualDescartar, longitud, stdin);
  32. ok = verifica(cualDescartar, ok, longitud, i);
  33. }while(ok);
  34.  
  35. descartar = atoi(cualDescartar);
  36.  
  37. for(i=descartar; digitos[i] != NULL; i++){
  38. digitos[i] = digitos[i+1];
  39. }
  40. numeroFinal = atoi(digitos);
  41. printf("\n\n El numero final es = %d", numeroFinal);
  42.  
  43. printf("\n\n");
  44. return 0;
  45. }
  46.  
  47.  
  48. int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
  49. long long temp=0, auxiliar=0;
  50. int ch=0, i=0, ingresoInt=0;
  51. char *p=NULL;
  52.  
  53. if((p=strchr(ingreso, '\n'))){
  54. *p='\0';
  55. }
  56. else{
  57. ingreso[longitud] = '\0';
  58. while((ch = getchar()) !='\n' && ch!=EOF);
  59. }
  60.  
  61. for(; ingreso[i] != NULL; i++){
  62. if(ingreso[i] <= 47 || ingreso[i] >= 58){
  63. ok=1;
  64. return ok;
  65. }
  66. }
  67.  
  68. if(longitud == 11){
  69. for(i=0; ingreso[i] != NULL; i++){
  70. auxiliar = ingreso[i] - 48;
  71. temp=10*temp+auxiliar;
  72. }
  73.  
  74. if(temp <= 99 || temp > UINT_MAX){
  75. ok=1;
  76. return ok;
  77. }
  78. }
  79. else{
  80. ingresoInt = atoi(ingreso);
  81. if(ingresoInt > maxDescartar){
  82. ok=1;
  83. return ok;
  84. }
  85. }
  86.  
  87. return ok;
  88. }
   

Saludos.
Daniel


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: leosansan en 1 Abril 2014, 19:40 pm
Efectivamente, tal como lo tenias se "perdía" exactamente el digito[0]. Eso es algo que comprobé tanto en el Code::Blocks como en el DeV-C++ y sospecho que es un bug del compilador ya que también lo probé en el programa PellesC que usa otro compilador y en éste último el programa no perdía al mencionado dígito, funcionaba correctamente.

Otra forma de que te funcione sin añadir _digitos es intercambiando los char, así:


Código
  1. char cualDescartar[2] = {'\0'},digitos[12] = {'\0'} ;

Lo probé de mil y una manera pero tal como lo tenias no había forma, se pierde el primer dígito, así que tranquilo, no te pasa a ti sólo. A ver si algún maestro se digna mirarlo.

Por si acaso eso ocurre le facilito el código donde se imprime digito[0]antes, que está O.K, y después, donde "desaparece":


Código
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <limits.h>
  4. #include <string.h>
  5.  
  6. int verifica(char ingreso[], int ok, int longitud, int maxDescartar);
  7.  
  8. int main(){
  9. unsigned int descartar=0, i=0, ok=0, longitud=11;
  10. char digitos[12], cualDescartar[2] ;
  11. printf("\n ---------- Programa que descompone un numero entero sin signo ----------");
  12. do{
  13. ok=0;
  14. printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
  15. fgets(digitos, longitud, stdin);
  16. ok = verifica(digitos, ok, longitud, i);
  17. }while(ok);
  18.  
  19. printf("\n\n");
  20. for(i=0; digitos[i]; i++){
  21. printf(" [%d] = %c \n", i, digitos[i]);
  22. }
  23. digitos[i]='\0';
  24.  printf("\n [0] = %c \n",  digitos[0]);/* <==AQUI SI ESTA */
  25.  
  26. do{
  27. longitud=2;
  28. ok=0;
  29. printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
  30. fgets(cualDescartar, longitud, stdin);
  31. ok = verifica(cualDescartar, ok, longitud, i);
  32. }while(ok);
  33.  
  34.  printf("\n [0] = %c \n",  digitos[0]); /* <==AQUI DESAPARECE ...... */
  35.  
  36. descartar = atoi(cualDescartar);
  37. printf(" descartar = %d \n",  descartar);
  38. system("pause");
  39. //En este lugar va lo que me falta...
  40.  
  41.  for (i=descartar;digitos[i] ;i++){ /* <==IMPRIME BIEN PORQUE NO EMPIEZA EN CERO */
  42.    digitos[i]=digitos[i+1];
  43.    printf(" [%d] = %c \n", i, digitos[i]);
  44.  }
  45.  
  46.  for (i=0;digitos[i];i++){
  47.    printf(" [%d] = %c \n", i, digitos[i]);/* <==NO IMPRIME  PORQUE  EMPIEZA EN CERO */
  48.  }
  49.  
  50. printf("\n\n");
  51. return 0;
  52. }
  53.  
  54.  
  55. int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
  56. long long temp=0, auxiliar=0;
  57. int ch=0, i=0, ingresoInt=0;
  58. char *p=NULL;
  59.  
  60. if((p=strchr(ingreso, '\n'))){
  61. *p='\0';
  62. }
  63. else{
  64. ingreso[longitud] = '\0';
  65. while((ch = getchar()) !='\n' && ch!=EOF);
  66. }
  67.  
  68. for(i=0; ingreso[i] ; i++){
  69. if(ingreso[i] <= 47 || ingreso[i] >= 58){
  70. ok=1;
  71. return ok;
  72. }
  73. }
  74.  
  75. if(longitud == 11){
  76. for(i=0; ingreso[i] ; i++){
  77. auxiliar = ingreso[i] - 48;
  78. temp=10*temp+auxiliar;
  79. }
  80.  
  81. if(temp <= 99 || temp > UINT_MAX){
  82. ok=1;
  83. return ok;
  84. }
  85. }
  86. else{
  87. ingresoInt = atoi(ingreso);
  88. if(ingresoInt > maxDescartar){
  89. ok=1;
  90. return ok;
  91. }
  92. }
  93. return ok;
  94. }


¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)

EDITO: Sin intercambiar los char, sólo con declarar cualDescartar con dimensión mayor de 2 funciona  :o

Código
  1. char digitos[12] = {'\0'}, cualDescartar[3];

Es como si al hacer uso de la función "verifica" un elemento de la variable "cualDescartar" sobreescribiera a digitos[0] .



Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: ivancea96 en 1 Abril 2014, 19:55 pm
¿Qué decíis que "desaparece"?

Estuve probando con varios números, y no veo ninguna pérdida.


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: NOB2014 en 1 Abril 2014, 19:58 pm
Hola leo.-
Dios mío vaya alegrón al ser vos uno de los que me ayuda, en cuanto al caso en si no puedo creer que esto pase,  no parece tener ninguna lógica.-
         
Saludos.
Daniel


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: leosansan en 1 Abril 2014, 20:02 pm
¿Qué decíis que "desaparece"?

Estuve probando con varios números, y no veo ninguna pérdida.

Usa mi código, que es casi como el original y debería de salirte:

Código
  1. ---------- Programa que descompone un numero entero sin signo ----------
  2.  
  3. Ingrece un numero entero sin signo [minimo 100 maximo 4294967295].........: 123456
  4.  
  5.  
  6. [0] = 1
  7. [1] = 2
  8. [2] = 3
  9. [3] = 4
  10. [4] = 5
  11. [5] = 6
  12.  
  13. [0] = 1  <== AQUI SALE O.K
  14.  
  15.  
  16. Indique con un entero sin signo del [0] al [5] que numero desea descartar..: 2
  17.  
  18. [0] =     <== FIJATE AQUI, DESAPARECE EL VALOR QUE TENIA
  19. descartar = 2
  20. Presione una tecla para continuar . . .
  21.  

Y si te funciona bien es que usas otro compilador diferente del min o NOB2014 y yo estamos embrujados. :laugh: :laugh: :laugh:


¡¡¡¡ Saluditos! ..... !!!!


(http://st.forocoches.com/foro/images/smilies/aaaaa.gif)

EDITO: Creo saber ya la causa. Al declarar cualDescartar[2] con dimensión 2 y usar fgets para captarlo, un primer caracter es el digito, un segundo caracter es el nulo de fin de cadena y "un tercer" caracter es el '\n' que introduce fgets, con lo que se sobreescribe más allça de la dimensión 2 que estaba establecida y da la casualidad de que sobreescribe el primer caracter de la variable digito, por eso el problema se solventa con cualDescartar[3].

Ahora me quedo más tranquilo.


Ahora me quedo más tranquilo,


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: NOB2014 en 1 Abril 2014, 20:09 pm
Hola Ivancea99.-
Bueno no tengo nada para agregar es tal cual como dice leo, me pasa exactamente lo mismo.
Citar
EDITO: Sin intercambiar los char, sólo con declarar cualDescartar con dimensión mayor de 2 funciona
Me gustó, funciona correctamente de esta manera, espero que a alguien más le pase lo mismo para que entre todos encontremos la explicación.-
         
Saludos.
Daniel


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: eferion en 1 Abril 2014, 20:14 pm
Código
  1. char digitos[12], cualDescartar[2];
  2.  
  3. // ...
  4.  
  5. do
  6. {
  7.    longitud=2;
  8.    // ...
  9.    ok = verifica(cualDescartar, ok, longitud, i);
  10. }while(ok);
  11.  
  12. // ...
  13.  
  14. if((p=strchr(ingreso, '\n'))){
  15.  *p='\0';
  16. }
  17. else{
  18.  ingreso[longitud] = '\0'; // <=========== AQUI!!!!!!
  19.  while((ch = getchar()) !='\n' && ch!=EOF);
  20. }

por pasos:

* "cualDescartar" tiene longitud 2 ( posiciones 0 y 1 )
* "longitud" se incializa a valor 2 ( mal vamos )
* ingreso[ longitud ] = '\0' ( toma castaña, escribimos fuera del array ).

El caso es que el compilador está poniendo en la pila primero a "cualDescartar" y despues "digitos", al salirte de "cualDescartar" escribes en "digitos"


Vaya, leosansan hemos puesto la respuesta a la vez XDDDD


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: NOB2014 en 1 Abril 2014, 20:49 pm
Hola a todos.

Citar
fgets - Leerá hasta n-1 caracteres o hasta que lea un retorno de línea (\n).
En este último caso , el carácter de retorno de línea también es leído.-

Código
  1. unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
  2. char digitos[12] = {'\0'}, cualDescartar[3] = {'\0'};


Código
  1. fgets(digitos, longitud, stdin);

Para dejarlo en mi caso del todo claro, ¿esta es la manera correcta de declarar el array y fgets(longitud) para capturar un máximo de 10 dígitos?         

Saludos.
Daniel


Título: Re: Descomponer un numero entero en lenguaje C.
Publicado por: eferion en 1 Abril 2014, 20:59 pm
"digitos" puede tener tamaño 11 perfectamente, con eso podrá almacenar una cadena de 10 caracteres.

Si quieres que el buffer sea capaz de almacenar una cadena de longitud X has de declararlo, al menos, de tamaño X+1, ya que debes reservar un espacio para el carácter nulo.

Esto solo es aplicable a cadenas de caracteres.