Foro de elhacker.net

Programación => Programación C/C++ => Mensaje iniciado por: Noxware en 30 Octubre 2014, 01:51 am



Título: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 01:51 am
Hola, recién empece a aprender C hace poco y estaba probando unas cosas y encontré un error muy irracional que no comprendo porque es.

Para empezar el código es el siguiente:
Código
  1. #include <stdio.h>
  2.  
  3. void main(){
  4.        char temp[10];
  5.        int a = 5;
  6.  
  7.        while(a == a){
  8.            printf(">>> ");
  9.            scanf("%s", &temp);
  10.  
  11.        }        
  12.    }
  13.  

esto desplega una consola que no hace paracticamente nada y que se ve asi:
Código:
>>>

si yo escribo una sola palabra no hay ningun problema:

Código:
>>> palabra1
y la consola queda:
Código:
>>>

Pero si le ingreso mas de una palabra, por ejemplo si le ingreso 4 palabras:
Código:
>>> palabra1 palabra2 palabra3 palabra4
la consola me queda:
Código:
>>> >>> >>> >>>

Porque sucede esto???


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 02:00 am
le estás diciendo al scanf que lea caracteres, el scanf no asume el espacio un caracter, así que el lee lo que hay antes del primer espacio, lo saca del buffer y termina, entonces se repite tu funcion, pero ahora tienes un buffer cargado, así que el repite la operacion por cada espacio... esto es util cuando vas a sacar datos diferentes como
Código:
hola 1 2.30

puedes sacar hola como string, 1 como int y 2.3 como float :P

si no quieres que suceda ese error debes limpiar el buffer
esta es una linea que sirve para eso
Código
  1. while ( getchar() != '\n' );
lo que hace es leer hasta que consigue el enter

tambien
Código
  1. fseek(stdin,0,SEEK_END);
que usa la busqueda para en el buffer de entrada (stdin) pararse al final


ese es el asunto con C que es de más bajo nivel que casi todos los comunes y al programador le toca hacer las verificaciones que se asumen obvias pero esos huecos son los que dan real control


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 02:15 am
Y como hago para que leea todo el string??? osea si quisiera imprimir todo lo que ingrese como lo haria???? porque al hacerlo asi solo me va a cargar la primera palabra pero no el resto....


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 02:31 am
puedes empezar con c++ que te hace más facil mucho del trabajo...
#include <stdio.h>
 
Código
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4.        char temp[10];
  5.        int a = 5;
  6.  
  7.        while(a == a){
  8.            cout << ">>> ";
  9.            cin >> temp;
  10.        }        
  11.        return 0;
  12. }


o si quieres hacerlo en c puedes hacer esto

Código
  1. fgets(temp, 10, stdin); //capturas 10 caracteres del buffer de entrada
  2. strtok(temp, "\n");//quita el salto de linea
  3.  


por cierto... cuidado con otras cosas como intentar comparar cadenas de variables, ya que si haces

Código
  1. a==b
y son char de 10... recuerda que nunca dejan de ser de 10 y el resto que no escribiste contiene "basura" así que no serán iguales


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 02:42 am
El código en C++ que me pasaste me da el mismo problema que tuve al inicio :(


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 02:51 am
ya! XD cierto que cin tambien lo hace, pero con cin es más simple igual y tambien había olvidado el salto de linea

Código
  1. #include <iostream>
  2. using namespace std;
  3. int main(){
  4.    char temp[10];
  5.    int a = 5;
  6.  
  7.    while(a == a){
  8.        cout << ">>> ";
  9.        cin.getline(temp,10);
  10.        cout << endl;//salto de linea
  11.    }        
  12.    return 0;
  13. }
  14.  


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: leosansan en 30 Octubre 2014, 13:37 pm
Y como hago para que leea todo el string??? osea si quisiera imprimir todo lo que ingrese como lo haria???? porque al hacerlo asi solo me va a cargar la primera palabra pero no el resto....

* Si quisieras seguir usando scanf para captar la cadena con espacios usarías:

Código
  1. scanf("%[^\n]s", temp) ;

* No hace falta el uso de una variable como "a" y hacer luego "a==a" para procvocar un bucle infinito. Más breve sería usar:

Código
  1. while ( 1 )

* Ten en cuenta que "temp" es un array por lo que sobra "& en el scanf.

* La función "main" es de tipo "int" por lo que requiere a su vez un return de entero.

Vamos que podría ser algo como:

Código
  1. #include <stdio.h>
  2.  
  3. int  main ( void ) {
  4.  char temp [100] ;
  5.  while ( 1 ) {
  6.   printf ( ">>> " ) ;
  7.   scanf("%[^\n]s", temp) ;
  8.   printf( "%s\n" , temp ) ;          
  9.   while ( getchar() != '\n' ) ;
  10.  }
  11.  return 0 ;}

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


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


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 14:37 pm
leosansan yo intenté eso pero me dice que ^\n no fue reconocido :s por eso ni lo intenté


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: _Enko en 30 Octubre 2014, 15:09 pm
Soy realmente innepto en Cpp/C pero....

No seria:

Código
  1. #include <stdio.h>
  2. #include <windows.h>
  3. #include <string.h>
  4.  
  5. int  main ( void ) {
  6. char temp [100] ;
  7.   do {
  8.   printf ( ">>> " ) ;
  9.   scanf("%[^\n]s", temp) ;
  10.   printf( "%s\n" , temp ) ;          
  11.   }while ( (getchar() != '\n')  ||  (strcmp(temp, "END")!= 0) ) ;
  12. system("PAUSE");
  13. return 0 ;
  14. }
  15.  

Digo mas que nada porque el bucle infinito me parece como mala práctica.


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: rir3760 en 30 Octubre 2014, 17:26 pm
Algunos comentarios ...

tambien
Código
  1. fseek(stdin,0,SEEK_END);
que usa la busqueda para en el buffer de entrada (stdin) pararse al final
El problema con fseek es que tal vez funcione o tal vez no, mejor utilizar un bucle para descartar el resto de la linea:
Código
  1. {
  2.   int ch;
  3.  
  4.   while ((ch = getchar()) != EOF && ch != '\n')
  5.      ;
  6. }
Se debe comparar contra EOF para evitar el caso donde la función getchar falla, retorna EOF y ello resulta en un bucle infinito.


* Si quisieras seguir usando scanf para captar la cadena con espacios usarías:

Código
  1. scanf("%[^\n]s", temp) ;
Cuando se desea indicar un conjunto de caracteres el especificador de formato es "%[]", la 's' después de este no hace daño pero esta de mas.


leosansan yo intenté eso pero me dice que ^\n no fue reconocido :s por eso ni lo intenté
Si estas compilando el código fuente como C debería reconocerlo, es la forma de indicar que los caracteres validos son los distintos al conjunto indicado.


Digo mas que nada porque el bucle infinito me parece como mala práctica.
Depende del programa si un bucle infinito es valido o no.

Un saludo


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 19:38 pm
leosansan me podrias explicar el siguiente codigo que me pasaste (el cual me funciono):
Código
  1. #include <stdio.h>
  2.  
  3. int  main ( void ) {
  4.  char temp [100] ;
  5.  while ( 1 ) {
  6.   printf ( ">>> " ) ;
  7.   scanf("%[^\n]s", temp) ; ///////////
  8.   printf( "%s\n" , temp ) ;      /////////////  
  9.   while ( getchar() != '\n' ) ; //////////
  10.  }
  11.  return 0 ;}
  12.  

como dije soy nuevo en C y no se mucho de C, hasta ahora solo habia programado en Python y en Java (muy poco)...... explicame especialmente los que te marque con barras de comentarios... las expresiones regulares...... porque no usate "&" para almacenar los datos en una parte de la memoria....... que es getchar....... y que es ese while al final..... gracias


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: BloodSharp en 30 Octubre 2014, 20:17 pm
No erá más facil usar gets() en lugar de getchar(), fxxxx() o scanf() y hacerse tanto lío con esas funciones?

Código
  1. #include <stdio.h>
  2.  
  3. int main()
  4. {
  5.     char temp[256];
  6.     while(1)
  7.          printf(">>> "),
  8.          gets(temp);
  9.     return 0;
  10. }


Pero si le ingreso mas de una palabra, por ejemplo si le ingreso 4 palabras:
Código:
>>> palabra1 palabra2 palabra3 palabra4
la consola me queda:
Código:
>>> >>> >>> >>>

Porque sucede esto???


Considerá que tenés un buffer de 10 bytes (char temp[10];) y no podés agregar más de 9 letras, si querés ingresar más texto tenés que tener un buffer mayor... (Ejemplo char temp[256];)


B#
 


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 20:50 pm
el ejemplo de leosansan me fue mas util aunque como dije recien estoy aprendiendo C y no entiendo mucho su ejemplo


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 21:53 pm
leosansan me podrias explicar el siguiente codigo que me pasaste (el cual me funciono):
Código
  1. #include <stdio.h>
  2.  
  3. int  main ( void ) {
  4.  char temp [100] ;
  5.  while ( 1 ) {
  6.   printf ( ">>> " ) ;
  7.   scanf("%[^\n]s", temp) ; ///////////
  8.   printf( "%s\n" , temp ) ;      /////////////  
  9.   while ( getchar() != '\n' ) ; //////////
  10.  }
  11.  return 0 ;}
  12.  

como dije soy nuevo en C y no se mucho de C, hasta ahora solo habia programado en Python y en Java (muy poco)...... explicame especialmente los que te marque con barras de comentarios... las expresiones regulares...... porque no usate "&" para almacenar los datos en una parte de la memoria....... que es getchar....... y que es ese while al final..... gracias

las 3 lineas que marcaste

1- escanf a una expresion regular (regex)
2- printf de el string y \n que es salto de linea
3- va a leer caracteres hasta que getchar sea \n (el enter)


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 22:04 pm
y ese while al final y simple??? porque no tiene nada adentro???


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 22:13 pm
si el while no tiene llaves (al igual que el if y el for) corren la siguiente linea o hasta conseguir ";"

el getchar tiene un apuntador automatico interno, cada vez que se usa se mueve un paso hacia adelante, así que se le hace "caminar" hasta que consiga el salto de linea, para así sacarlo del buffer


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: Noxware en 30 Octubre 2014, 22:51 pm
gracias por toda la ayuda, seguire leyendo sobre C y tarde o temprano sobre C++

algun manual corto para pasar de C a C++ luego???


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: engel lex en 30 Octubre 2014, 23:01 pm
de c a c++ las diferencias no son muchas, muchos (por no decir casi todos) los programas de c son comptaibles con c++, lo que agrega c++ principalmente es la orientacion a objetos...


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: leosansan en 31 Octubre 2014, 04:39 am
y ese while al final y simple??? porque no tiene nada adentro???

Para aclarar eso antes indicarte que cuando escribes del teclado para introducir datos estos no los coge directamente el scanf o función similar, sino que van a lo que se llama buffer o memoria intermedia y es de ahí de donde el scanf toma los datos. pueden ocurrir dos cosas:

* El número de caracteres introducidos es inferior al tamaño del array o dato. En este caso el scanf tomará todos los caracteres del buffer "excepto" el caracter retorno de línea que se quedará en el buffer. Eso hace que al ejecutarse el ciclo al encontrarse el retorno de línea en el buffer se salte el scanf y entre en un bucle infinito. Por lo tanto hay que eliminar el retorno de línea del buffer antes de llegar al scanf nuevamente. Una opción sería poner un getchar, que es una función  que lee un caracter del buffer, después del scanf, algo como:

Código
  1. #include <stdio.h>
  2.  
  3. int  main ( void ) {
  4.  char temp [100] ;
  5.  while ( 1 ) {
  6.   printf ( ">>> " ) ;
  7.   scanf ("%[^\n]" , temp) ;
  8.   printf ( "%s\n" , temp ) ;
  9.   getchar ( ) ;            
  10.  }
  11.  return 0 ;
  12. }

O bien, recuerda que he dicho que has introducido menos caracteres que el tamaño del array, hacer que el scanf, al tiempo que lee el dato consuma el retorno de línea del buffer, cosa que podemos conseguir haciendo:

Código
  1. #include <stdio.h>
  2.  
  3. int  main ( void ) {
  4.  char temp [100] ;
  5.  while ( 1 ) {
  6.   printf ( ">>> " ) ;
  7.   scanf ("%[^\n]%c" , temp) ;
  8.   printf ( "%s\n" , temp ) ;          
  9.  }
  10.  return 0 ;
  11. }

Fíjate que el scanf lee la cadena y otro caracter que sería el retorno de línea y de esa forma eliminamos el mismo del buffer y ya no dará problemas.

* Pero si el total de caracteres que introduces es superior al tamaño máximo que has declarado en el array, ahora hay que eliminar ese exceso. En este caso es cuando es útil el bucle del while con el getchar ya que mientras quede algún caracter en el buffer el getchar los irá consumiendo hasta limpiar el buffer de forma que cuando termina se ejecuta el while principal y el scanf funciona sin problemas al no haber ya nada previo en el buffer, con lo que procede a leer el nuevo dato introducido.

Y así sucesivamente.

Espero no haberte liado más, sino todo lo contrario y no haber metido la pata con la explicación que a fuerza de ser breve puede ocurrir.

Un fuerte saludo francoyo1998 .



Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: rir3760 en 31 Octubre 2014, 16:03 pm
y ese while al final y simple??? porque no tiene nada adentro?
Porque en C es obligatorio indicar el cuerpo de un bucle.

En el caso que comentas:
Código
  1. {
  2.   int ch;
  3.  
  4.   while ((ch = getchar()) != EOF && ch != '\n')
  5.      ; /* sentencia nula ==> ninguna operacion */
  6. }
La operación necesaria (descarte del resto de la linea) se realiza en la condición del bucle, no hay nada mas que hacer pero las reglas del lenguaje imponen indicar el cuerpo si o si. Por ello utilizamos una sentencia nula (nada) la cual se indica con el punto y coma inmediatamente después de la condición.

----

Código
  1. scanf("%[^\n]%c" , temp);

Espero no haberte liado más, sino todo lo contrario y no haber metido la pata con la explicación
Toda la explicación es correcta salvo un detalle en esa llamada a función: al utilizar "%c" se debe indicar mediante un puntero la variable donde se almacenara el carácter, si se desea simplemente descartar al susodicho se debe utilizar "%*c".

Un saludo


Título: Re: [AYUDA] Soy nuevo en C y tengo un problema con un codigo de 12 lineas simple
Publicado por: leosansan en 31 Octubre 2014, 18:26 pm

----
Toda la explicación es correcta salvo un detalle en esa llamada a función: al utilizar "%c" se debe indicar mediante un puntero la variable donde se almacenara el carácter, si se desea simplemente descartar al susodicho se debe utilizar "%*c".

Un saludo

;-) ;-) ;-)

Gracias por el recordatorio amigo rir3760. No sé que haría sin ti...bueno, sí que lo sé ... ;)

Un fuerte saludo de León.