[C] Comparación entre el gets y el scanf

Iniciado por niñoAtómico, 11 Octubre 2013, 18:32 PM

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

niñoAtómico

Hola, acabo de recibir mi nota del primer parcial de programación II, y tuve un error muy boludo, ahora que lo entiendo.

No me funcionaba el gets en el siguiente código: (en C):
#include <stdio.h>
#include <stdlib.h>

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void textocrea();
void textolee();
int main() {


//char text [1000];
//char entrada [1000];
int opcion = 0;
printf("Seleccione la opcion:\n");
printf("Opcion 1) crear texto en archivo\nOpcion 2) Leer archivo\n");
scanf("%i", &opcion);
switch(opcion){
case 1:
  textocrea();
break;
case 2://funciona!!!
       textolee();
       break;
default:
   printf("Selecciono una opcion no existente\n");
break;
}

return 0;
}
 void textocrea()
{
FILE *vfile;
char caracter[1000];
vfile = fopen("d:/texto.txt", "w");
if(vfile==NULL){
  printf("Error al crear archivo\n");
 }

printf("Ingrese el texto\n");
gets(caracter);
fputs(caracter, vfile);
fclose(vfile);    

 }
void textolee()
{
FILE *vfile;
char caracter [1000];
vfile = fopen("d:/texto.txt", "r");
if(vfile==NULL){
  printf("Error al crear archivo\n");
 }
 while(!feof(vfile)){
 
  fread(&caracter, sizeof(caracter), 1, vfile);
 
  printf("%s", caracter);
   }

fclose(vfile);




}


Entonces lo resolví poniendo un scanf, pero como sabemos el scanf no lee espacios, y si uno quiere guardar un texto tiene que leer espacios. para esto usé la fórmula:
scanf( " %[^\n]",&caracter );

para que guarde en la variable caracter el texto. Pero no era lo que el profe quería. La respuesta para que funcione el gets es así:
fflush(stdin);
gets(caracter);


Y el código completo que tiene dos opciones, una crear un archivo y la otra leerlo, sería así (sin errores):

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

/* run this program using the console pauser or add your own getch, system("pause") or input loop */

void textocrea();
void textolee();
int main() {


//char text [1000];
//char entrada [1000];
int opcion = 0;
printf("Seleccione la opcion:\n");
printf("Opcion 1) crear texto en archivo\nOpcion 2) Leer archivo\n");
scanf("%i", &opcion);
switch(opcion){
case 1:
  textocrea();
break;
case 2://funciona!!!
       textolee();
       break;
default:
   printf("Selecciono una opcion no existente\n");
break;
}

return 0;
}
 void textocrea()
{
FILE *vfile;
char caracter[1000];
vfile = fopen("d:/texto.txt", "w");
if(vfile==NULL){
  printf("Error al crear archivo\n");
 }

printf("Ingrese el texto\n");
fflush(stdin);
gets(caracter);
fputs(caracter, vfile);
fclose(vfile);    

 }
void textolee()
{
FILE *vfile;
char caracter [1000];
vfile = fopen("d:/texto.txt", "r");
if(vfile==NULL){
  printf("Error al crear archivo\n");
 }
 while(!feof(vfile)){
 
  fread(&caracter, sizeof(caracter), 1, vfile);
 
  printf("%s", caracter);
   }

fclose(vfile);




}


Y si quieren que quede mejor le ponen un system("pause"); para que no se cierre si lo ejecutan individualmente.


Eso es todo, quería compartir esto para que no cometan este error tan bolu, ojalá nunca les pase...  :silbar: :silbar:


Saludos...

"Los genios son idiotas insistentes..."

rir3760

El uso de gets y fflush(stdin) no se recomienda, si apenas estas empezando por favor lee el tema |Lo que no hay que hacer en C/C++. Nivel basico|.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

niñoAtómico

#2
Son puntos de vista, para resolver el ejercicio me sirvió el gets(), veo que sacan mucho de wikipedia tambien, no se guíen tanto por eso. Leí la nota sobre lo que no hay que hacer en C, por ejemplo system ("pause"),  porque no es portable, pero creo que cuando uno abre el IDE pone que va a hacer un programa para MS-DOS, poner un getc() para hacer una pausa me parece medio pelo, obviamente son visiones de gente que está más curtida en este asunto. Depende de lo que uno quiera hacer sirve o no el gets(); hay que saber manejarse con todas las funciones, me parece. Obviamente saben muchísimas cosas, me vino re bien el texto del link del artículo. Que bueno que se copen explicando estas cosas. A veces en la facu algún programa tira un símbolo raro o funciona mal y ni les importa. Gratzie... ;-)

Saludos...
"Los genios son idiotas insistentes..."

mr.blood

Cita de: niñoAtómico en 12 Octubre 2013, 04:17 AM
Son puntos de vista, para resolver el ejercicio me sirvió el gets(), veo que sacan mucho de wikipedia tambien, no se guíen tanto por eso. Leí la nota sobre lo que no hay que hacer en C, por ejemplo system ("pause"),  porque no es portable, pero creo que cuando uno abre el IDE pone que va a hacer un programa para MS-DOS, poner un getc() para hacer una pausa me parece medio pelo, obviamente son visiones de gente que está más curtida en este asunto. Depende de lo que uno quiera hacer sirve o no el gets(); hay que saber manejarse con todas las funciones, me parece. Obviamente saben muchísimas cosas, me vino re bien el texto del link del artículo. Que bueno que se copen explicando estas cosas. A veces en la facu algún programa tira un símbolo raro o funciona mal y ni les importa. Gratzie... ;-)

Saludos...

Flipando ahora mismo...




fflush no se debe usar porque es para flujos de salida y no de entrada. Ya se ha dicho mil veces que es mejor no usar funciones que dejen basura a la entrada que estar limpiandola constantemente.

gets no debe usarse por ser una funcion que no controla la cantidad de caracteres que se introducen dejando la aplicacion vulnerable a un overflow.

Me da igual lo que pongas en el IDE, si el resto del código es portable es una pena que por ese system("pause") la dejes solo para un SO. Utiliza getchar().

Sa1uDoS

rir3760

Cita de: niñoAtómico en 12 Octubre 2013, 04:17 AMpero creo que cuando uno abre el IDE pone que va a hacer un programa para MS-DOS, poner un getc() para hacer una pausa me parece medio pelo
Siendo estrictos ningún programa debería terminar con una "pausa" sea cual sea la forma en que esta se realice porque no es parte del programa, peor todavía, casi todos los IDEs (Lcc-win32, Pelles C, Visual C++, Code::Blocks, la nueva versión de Dev-C++, etc.) generan una pausa de forma automática cuando se ejecuta desde ellos una aplicación de consola.

La pregunta "Mi aplicación aparece y desaparece en un instante ..." se origino cuando hace muchos años una cantidad significativa de principiantes en C y C++ utilizaron Dev-C++ y este no genera la [CENSORED] pausa. En lugar de ejecutar el programa como dios manda desde el interprete de comandos se busco la "solución" mas cómoda.

Cita de: niñoAtómico en 12 Octubre 2013, 04:17 AMDepende de lo que uno quiera hacer sirve o no el gets(); hay que saber manejarse con todas las funciones
El problema con gets y scanf("%s" ...) es que son las únicas funciones donde no se puede garantizar su funcionamiento: si la linea en el caso de la primera o la palabra en el caso de la segunda contienen mas caracteres de los que se pueden almacenar en el array el programa revienta. Con otras funciones como fgets o scanf("%Ns" ...) no tenemos de que preocuparnos.

Un saludo
C retains the basic philosophy that programmers know what they are doing; it only requires that they state their intentions explicitly.
--
Kernighan & Ritchie, The C programming language

niñoAtómico

Hola:
Si, estuve leyendo el post de LittleHorse sobre lo que no hay que hacer,y efectivamente encontré el gets() como una función inestable. Otro tema, ya que veo que está en un nivel más alto que yo:

Necesito pasar a hacer otros programas más compejos. ¿Qué libro o site me recomienda?. Quiero programar algo que vaya más allá de mostrar texto en pantalla, o de resolver equaciones, etc. Mi pregunta es: ¿Cuál es el siguiente paso? ¿Qué me recomienda? Estoy aprendiendo del libro "Cómo programar en C, C++ y Java", de deitel y Deitel (además de la facu), pero como aprendí ahora tiene estos errores como el gets() o poner un system("pause"), y lo que yo quiero es lograr hacer programas que puedan ser utilizados por personas. De lo que hablo es de que nadie me va a comprar un programa que saque por pantalla la serie de Fibonacci, o sume dos matrices, y esas cosas.

Gracias!!! :D
"Los genios son idiotas insistentes..."

vangodp

jejeje ahí esta la cosa compañero jejeje
No basta con aprender a programar, lo que se apremia es la idea.
Si vas a trabajar de programador no necesitas idea, necesitas un trabajo.
Peeeeero, si lo que quieres es crear algo tuyo eso es otro nivel.
Esa pregunta lo siento por que no tiene respuesta. :(
Mira creo que a todos los programadores les toca hacer esta elección.
Piensa  "¿Que es lo que hace falta a la gente?".
Ademas de eso saber tus posibilidades para tal proyecto.
Nadie te va decir lo que tienes que hacer, eso es una cosa que solo tu puedes elegir.
Piensa de esta forma... hay miles de personas con ordenadores moviles y aparatitos XD
¿Que puedo hacer, que les interese tener en sus maquinas?
Algo realmente útil, que valga la pena y tampoco te haga perder el tiempo.
Es una cuestión escabrosa.
¡ Imaginación y muuuucha suerte!
No desanime ni dejes de programar, superar esos retos es lo que realmente hace que valga la pena ;)  ;-)

niñoAtómico

#7
Hola Vangodp:

Lo que yo quería decir es que estuve viendo programas avanzados y no usan las mismas expresiones que uso yo, como switch case, do while, etc. Las usan pero de otra forma. Y no entiendo cómo aprender eso. Sé qué es otro nivel, y no sé con qué empezar para avanzar a esa etapa...

Saludos!!! :)
"Los genios son idiotas insistentes..."

vangodp

te refieres a clases, punteros, referencias...?

niñoAtómico

Claro, me refiero a que lo que ustedes hacen se ve así:

int mostrarMenu(Menu* menu,int modo)
{
   int i=0, opcion=0;

   if(menu->numOpciones)
   {
       do{

          #ifdef WINDOWS
             system("CLS");
          #elif defined UNIX
             system("clear");
          #endif

          if(menu->titulo)
          {
             for(i=0 ; i<80 ; i++)
                 printf("=");

             printf("%*s\n", 40 + strlen(menu->titulo) / 2, , menu->titulo);

             for(i=0 ; i<80 ; i++)
                 printf("=");


Y lo que yo hago se ve así:

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

int main()
{

    FILE *vfile;
    vfile = fopen("c:/texto.txt","r");
    //vfile = fopen("Holafiles.txt","w");
   char vcaracter;
   
    if (vfile == NULL)
    {
        printf("El archivo no se encontro \n");
        getch();
       
    }
    else
    {
        printf("El archivo se abrio con exitos\n");
        getch();
       
    }
   
    char ne = '*';
    char vtexto [100];
   
    while (feof(vfile)==0){
   
vcaracter=fgetc(vfile);

if (!(vcaracter==ne))
printf("%c", vcaracter);
    // fgets(vtexto, sizeof(vtexto),vfile);   
    // printf("%s", vtexto);
    //getch();
    }
     
    getch();
     
     printf("\n");
     printf("\n");
     printf("Ese era el archivo\n");
     
     
    fclose(vfile);

}


El nivel de complejidad de su trabajo es muchisimo mayor, y está enfocado en tareas de programas que sirven para cosas más complejas. Eso es lo que no me enseñan los libros que tengo.

Por ejemplo: si quiero hacer un video juego en C, por dónde se empieza? Es un solo archivo? son varios?

Si quiero hacer una aplicación?

Obviamente no espero una respuesta directa sino una referencia a algún libro, o texto digital.

TnX a lot!!!
"Los genios son idiotas insistentes..."