problema con sprintf

Iniciado por m@o_614, 9 Febrero 2014, 19:46 PM

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

m@o_614

Saludos, tengo el siguiente código que me tiene que abrir un archivo que se llama P1ASM.txt, pero el programa me tiene que preguntar el nombre del archivo para ver si se encuentra, pero me imprime No se pudo abrir el archivo y no entiendo por que si el archivo se encuentra en la misma carpeta donde tengo el codigo no deberia de haber errores

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX 40

int main()
{
   FILE *fd;
    char nombre[MAX],archivo[MAX];
    printf("Que archivo quieres abrir: ");
    fgets(nombre,MAX,stdin);
    sprintf(archivo,"%s.txt",nombre);
    if((fd = fopen(archivo,"r"))!= NULL)
       printf("Si se encontro");
    else
       printf("No se pudo abrir el archivo");
   return 0;
}


gracias

leosansan


El problema lo provoca el caracter \n que introduce fgets en la cadena.

Si pruebas con gets o scanf no tendrás ese problema.

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




m@o_614

muchas gracias leosansan por tu respuesta, en vez de usar el gets le puse una funcion para quitarle el salto de linea '\n' y ya con esto ya lo hace correctamente. Una ultima duda, si yo quisiera que al escribirse el nombre del archivo a abrir, no necesariamente tenga que ser identicamente a como se encuentra el original y que pudiera hacerse indistintamente con combinaciones de mayúsculas y minúsculas, ¿cómo lo podría hacer? alguna idea??

Yoel Alejandro

#3
Una observación, la función fgets() es más segura por cuánto permite limitar la longitud de la cadena recibida (el argumento MAX que le pasas), y así prevenir un desbordamiento del búfer. Una verificación que no hacen ni gets() ni scanf(). De hecho, algunos compiladores advierten sobre el uso riesgoso de gets() , desaconsejando su uso.

Yo en su lugar seguiría usando fgets() pero "recortaría" la cadena:

Código (cpp) [Seleccionar]

if ( ( len = strlen( nombre ) ) > 0 && nombre[len - 1] = '\n') nombre[len - 1] = '\0';


Ahora, respecto a que quieres pasar el nombre del archivo sin distinguir mayúsculas y minúsculas lo veo un poco más difícil. Obviamente, no te vas a poner a probar todas las combinaciones de minúsculas y mayúsculas, a ver si alguna abre el archivo (jeje)

A mi se me ocurre listar el contenido del directorio, y probar nombre por nombre contra el nombre dado por el usuario. Si alguno coincide (despreciando mayúsculas y minúsculas), abrir el fichero. Para eso, se requiere un compilador que implemente la biblioteca <unistd.h> la cual obedece un estándar llamado POSIX. Es hecho que sea estándar significa que con seguridad la tienes en una implementación de C para Linux, pero no necesariamente en Windows  :silbar: (ya saben como es Microsoft, rompe-estándares).  

¿Usas Windows verdad? En ese caso, compila con IDE libre para Windows como Dev-Cpp, o MinGW con gcc/g++. No estoy seguro que Borland C lo soporte (la verdad no tengo idea, pues no uso ni Windows ni Borland, jeje).

Bueno, a lo nuestro.
Código (cpp) [Seleccionar]

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <ctype.h>

#define MAX 40

char * str_to_lower( char *);

int main()
{
FILE *fd = NULL;
char name[MAX];
unsigned long len;
char ready;

char dir_name[100]; /* nombre de directorio */
DIR * dir_ptr = NULL; /* apuntador a directorio */
struct dirent * dirent_ptr; /* estructura 'directory-entry' */
char * f_name; /* name de cada fichero leído en el directorio */

printf("Que archivo quieres abrir: ");

fgets( name, MAX, stdin );
/* quitamos el '\n' al final de la cadena */
if ( ( len = strlen( name ) ) > 0 && name[len - 1] == '\n' )
name[len - 1] = '\0';
strcat( name, ".txt" ); /* añadimos '.txt' al final */

/* pongamos el directorio como el actual, puedes cambiarlo xD */
strcpy( dir_name, ".");

/* 'abrimos' el directorio para leer su contenido */
if ( ( dir_ptr = opendir( dir_name ) ) == NULL ) {
printf( "No existe o no se pudo abrir el directorio '%s'\n", dir_name );
return -1;
}

/* ahora recorremos todo el directorio, buscando
* names de fichero que coincidan */
ready = 0;
while ( ( dirent_ptr = readdir( dir_ptr ) ) != NULL ) {
f_name = dirent_ptr -> d_name;

/* verificamos omitiendo mayúsculas y minúsculas */
if ( ! strcmp( str_to_lower(name), str_to_lower(f_name) ) )
if((fd = fopen(f_name, "r")) != NULL) {
printf("Se abrio '%s'\n", f_name);
ready = 1;
}
}

/* y si al finalizar el ciclo no encontro, emitir error */
if ( !ready )
printf("No se pudo abrir el archivo\n");

/* cerramos el directorio, y el fichero */
if ( dir_ptr != NULL ) closedir( dir_ptr );
if ( fd != NULL ) fclose( fd );

return 0;
}

/* Pasa todos los caracteres de la cadena a minúsculas */
char * str_to_lower( char * s ) {

size_t k = 0;

while ( s[k] != '\0' ) {
if ( isalpha( s[k] ) ) s[k] = tolower( s[k] );
k++;
}

return s;
}


Este programa es funcional, sólo necesita ser compilado y probado. Por ejemplo, yo tengo el mi directorio un file1.txt, y al pasarle el nombre 'FiLe1' me dice que lo abrió. Al pasarle 'FilE2' no lo abre, porque no tengo 'file2.txt'.

Como ves, recorremos todo el directorio y convertimos sus nombres a minúsculas usando las funciones de biblioteca isaplha() (prueba si es una letra), y tolower() (pasa una letra a minúscula).

Lo de recorrer directorio requiere conocer acerca de la estructura dirent y la función readdir. Yo escribí un post al respecto el otro foro, te invito a leerlo para comprender esto mejor: http://foro.chuidiang.com/ccplusplus-linux/listar-contenido-de-un-directorio-usando-funciones-posix-de-c/

Se esperan comentarios, opiniones, etc .....  :)
Saludos, Yoel.
P.D..-   Para mayores dudas, puedes enviarme un mensaje personal (M.P.)