Descomponer un numero entero en lenguaje C.

Iniciado por NOB2014, 31 Marzo 2014, 16:00 PM

0 Miembros y 1 Visitante están viendo este tema.

NOB2014

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..........................:

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

int verifica(char ingreso[], int ok, int longitud, int maxDescartar);

int main(){
unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
char digitos[12] = {'\0'}, cualDescartar[2] = {'\0'};
printf("\n ---------- Programa que descompone un numero entero sin signo ----------");
do{
ok=0;
printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
fgets(digitos, longitud, stdin);
ok = verifica(digitos, ok, longitud, i);
}while(ok);

printf("\n\n");
for(; digitos[i] != NULL; i++){
printf(" [%d] = %c \n", i, digitos[i]);
}

do{
longitud=2;
ok=0;
printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
fgets(cualDescartar, longitud, stdin);
ok = verifica(cualDescartar, ok, longitud, i);
}while(ok);

descartar = atoi(cualDescartar);
//En este lugar va lo que me falta...

printf("\n\n");
return 0;
}


int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
long long temp=0, auxiliar=0;
int ch=0, i=0, ingresoInt=0;
char *p=NULL;

if((p=strchr(ingreso, '\n'))){
*p='\0';
}
else{
ingreso[longitud] = '\0';
while((ch = getchar()) !='\n' && ch!=EOF);
}

for(; ingreso[i] != NULL; i++){
if(ingreso[i] <= 47 || ingreso[i] >= 58){
ok=1;
return ok;
}
}

if(longitud == 11){
for(i=0; ingreso[i] != NULL; i++){
auxiliar = ingreso[i] - 48;
temp=10*temp+auxiliar;
}

if(temp <= 99 || temp > UINT_MAX){
ok=1;
return ok;
}
}
else{
ingresoInt = atoi(ingreso);
if(ingresoInt > maxDescartar){
ok=1;
return ok;
}
}
return ok;
}

/*
sprintf(digitos, "%d", 56789);
*/


Saludos y muchas pero muchas gracias por el tiempo dedicado a este tema.-
Daniel
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

eferion

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.

NOB2014

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.-
     
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

int verifica(char ingreso[], int ok, int longitud, int maxDescartar);

int main(){
unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
char digitos[12] = {'\0'}, _digitos[12] = {'\0'}, cualDescartar[2] = {'\0'};

printf("\n ---------- Programa que descompone un numero entero sin signo ----------");

do{
ok=0;
printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
fgets(digitos, longitud, stdin);
ok = verifica(digitos, ok, longitud, i);
}while(ok);

printf("\n\n");

for(; digitos[i] != NULL; i++){
printf(" [%d] = %c \n", i, digitos[i]);
}

do{
longitud=2;
ok=0;
printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
fgets(cualDescartar, longitud, stdin);
ok = verifica(cualDescartar, ok, longitud, i);
}while(ok);

descartar = atoi(cualDescartar);

for(i=descartar; digitos[i] != NULL; i++){
digitos[i] = digitos[i+1];
}
numeroFinal = atoi(digitos);
printf("\n\n El numero final es = %d", numeroFinal);

printf("\n\n");
return 0;
}


int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
long long temp=0, auxiliar=0;
int ch=0, i=0, ingresoInt=0;
char *p=NULL;

if((p=strchr(ingreso, '\n'))){
*p='\0';
}
else{
ingreso[longitud] = '\0';
while((ch = getchar()) !='\n' && ch!=EOF);
}

for(; ingreso[i] != NULL; i++){
if(ingreso[i] <= 47 || ingreso[i] >= 58){
ok=1;
return ok;
}
}

if(longitud == 11){
for(i=0; ingreso[i] != NULL; i++){
auxiliar = ingreso[i] - 48;
temp=10*temp+auxiliar;
}

if(temp <= 99 || temp > UINT_MAX){
ok=1;
return ok;
}
}
else{
ingresoInt = atoi(ingreso);
if(ingresoInt > maxDescartar){
ok=1;
return ok;
}
}

return ok;
}
   

Saludos.
Daniel
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

leosansan

#3
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 (cpp) [Seleccionar]
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 (cpp) [Seleccionar]
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include <string.h>

int verifica(char ingreso[], int ok, int longitud, int maxDescartar);

int main(){
unsigned int descartar=0, i=0, ok=0, longitud=11;
char digitos[12], cualDescartar[2] ;
printf("\n ---------- Programa que descompone un numero entero sin signo ----------");
do{
ok=0;
printf("\n\n Ingrece un numero entero sin signo [minimo 100 maximo %u].........: ", UINT_MAX);
fgets(digitos, longitud, stdin);
ok = verifica(digitos, ok, longitud, i);
}while(ok);

printf("\n\n");
for(i=0; digitos[i]; i++){
printf(" [%d] = %c \n", i, digitos[i]);
}
digitos[i]='\0';
 printf("\n [0] = %c \n",  digitos[0]);/* <==AQUI SI ESTA */

do{
longitud=2;
ok=0;
printf("\n\n Indique con un entero sin signo del [0] al [%d] que numero desea descartar..: ", i-1);
fgets(cualDescartar, longitud, stdin);
ok = verifica(cualDescartar, ok, longitud, i);
}while(ok);

 printf("\n [0] = %c \n",  digitos[0]); /* <==AQUI DESAPARECE ...... */

descartar = atoi(cualDescartar);
printf(" descartar = %d \n",  descartar);
system("pause");
//En este lugar va lo que me falta...

 for (i=descartar;digitos[i] ;i++){ /* <==IMPRIME BIEN PORQUE NO EMPIEZA EN CERO */
   digitos[i]=digitos[i+1];
   printf(" [%d] = %c \n", i, digitos[i]);
 }

 for (i=0;digitos[i];i++){
   printf(" [%d] = %c \n", i, digitos[i]);/* <==NO IMPRIME  PORQUE  EMPIEZA EN CERO */
 }

printf("\n\n");
return 0;
}


int verifica(char ingreso[], int ok, int longitud, int maxDescartar){
long long temp=0, auxiliar=0;
int ch=0, i=0, ingresoInt=0;
char *p=NULL;

if((p=strchr(ingreso, '\n'))){
*p='\0';
}
else{
ingreso[longitud] = '\0';
while((ch = getchar()) !='\n' && ch!=EOF);
}

for(i=0; ingreso[i] ; i++){
if(ingreso[i] <= 47 || ingreso[i] >= 58){
ok=1;
return ok;
}
}

if(longitud == 11){
for(i=0; ingreso[i] ; i++){
auxiliar = ingreso[i] - 48;
temp=10*temp+auxiliar;
}

if(temp <= 99 || temp > UINT_MAX){
ok=1;
return ok;
}
}
else{
ingresoInt = atoi(ingreso);
if(ingresoInt > maxDescartar){
ok=1;
return ok;
}
}
return ok;
}



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



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

Código (cpp) [Seleccionar]
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] .


ivancea96

¿Qué decíis que "desaparece"?

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

NOB2014

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
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

leosansan

#6
Cita de: 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.

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

Código (cpp) [Seleccionar]

---------- Programa que descompone un numero entero sin signo ----------

Ingrece un numero entero sin signo [minimo 100 maximo 4294967295].........: 123456


[0] = 1
[1] = 2
[2] = 3
[3] = 4
[4] = 5
[5] = 6

[0] = 1  <== AQUI SALE O.K


Indique con un entero sin signo del [0] al [5] que numero desea descartar..: 2

[0] =     <== FIJATE AQUI, DESAPARECE EL VALOR QUE TENIA
descartar = 2
Presione una tecla para continuar . . .


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


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



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,

NOB2014

Hola Ivancea99.-
Bueno no tengo nada para agregar es tal cual como dice leo, me pasa exactamente lo mismo.
CitarEDITO: 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
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-

eferion

#8

char digitos[12], cualDescartar[2];

// ...

do
{
   longitud=2;
   // ...
   ok = verifica(cualDescartar, ok, longitud, i);
}while(ok);

// ...

if((p=strchr(ingreso, '\n'))){
 *p='\0';
}
else{
 ingreso[longitud] = '\0'; // <=========== AQUI!!!!!!
 while((ch = getchar()) !='\n' && ch!=EOF);
}


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

NOB2014

Hola a todos.

Citarfgets - 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.-

unsigned int descartar=0, numeroFinal=0, i=0, ok=0, longitud=11;
char digitos[12] = {'\0'}, cualDescartar[3] = {'\0'};



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
abraza las cosas y personas malas como si fueran tu mas preciada joya,Son tus mas grandes maestros de paciencia sabiduría y amor y cuando lo abrazas dejan de causar dolor.-