PDA

View Full Version : [C] Funzione fgets


Baio84
28-05-2012, 13:26
Ho necessità di inserire una stringa. Utilizzando la funzione fgets ho notato che, nell'array in cui vado ad inserire la stringa, inserisce alla fine anche un carattere '\n'.
Quindi se dovessi inserire 'ciao', nel mio array troverei c i a o \n \0.

Per me è un problema perchè dopo dovrei inserire un'altra stringa nell'array ottenuto da fgets, tramite strcat, e quel newline lì mi provoca problemi seguenti.

C'è per caso una soluzione semplice al problema, ho devo "giocare" con la stringa per sostituire\eliminare il newline?

ESSE-EFFE
28-05-2012, 15:35
Ho necessità di inserire una stringa.

C'è per caso una soluzione semplice al problema, ho devo "giocare" con la stringa per sostituire\eliminare il newline?

Non ci capisce bene come tu debba "inserire" la stringa. Comunque, se ci pensi, vedrai che rimuovere quel "new line" in fondo alla stringa è una cosa semplice.

Baio84
28-05-2012, 16:32
Mi sono appena affaciato al C, per cui scusa per il mio linguaggio non proprio da programmatore. :p

Inserire nel senso che digito la frase su tastiera e tramite gets la inserisco nel vettore.

La soluzione diciamo che ce l'avevo già. Utilizzo una funzione specifica che ricerca \n nella stringa (strchr mi sembra), che mi restituisce la posizione del newline. Poi mi basterebbe porre vettore[posizione_newline] = '\0'.

In questo modo troverei alla fine della stringa due '\0'. Quello che volevo sapere è se questo modo possa andare bene. Per spiegarmi ancora meglio, siccome sono agli inizi, non volevo fare troppi giri con diverse funzioni, quando invece c'è n'è una che faccia al caso mio ma che non conosco ancora.

ESSE-EFFE
28-05-2012, 16:54
La soluzione diciamo che ce l'avevo già. Utilizzo una funzione specifica che ricerca \n nella stringa (strchr mi sembra), che mi restituisce la posizione del newline. Poi mi basterebbe porre vettore[posizione_newline] = '\0'.

Posta un po' di codice la prossima volta. Comunque in questo caso non serve "cercare" il newline. Se c'è, è l'ultimo carattere della stringa.

In questo modo troverei alla fine della stringa due '\0'. Quello che volevo sapere è se questo modo possa andare bene.

Direi che non ci sono problemi.

Baio84
28-05-2012, 18:51
Hai ragione. Pensavo fosse un po' più semplice da svolgere, ma con un po' di codice ci si capisce meglio.

if ( seconda_scelta == si )
{
sprintf (vecchionome, "%s", file->d_name);
printf ( "vecchionome: %s\n", vecchionome );

l = strlen ( vecchionome ) - 5;
for ( i = 0; i < 5; i++ )
{
estensione [i] = vecchionome [l];
l++;
}

printf ( "estensione: %s\n", estensione );
fgets ( nuovonome, 80, stdin );
printf ( "nuovonome: %s\n", nuovonome );
newline = strlen ( nuovonome ) - 1;
nuovonome [ newline ] = '\0';
printf ( "estensione: %s\n", estensione );
strcat ( nuovonome, estensione );
printf ("nuovonome + estensione: %s\n", nuovonome);
rinomina = rename (vecchionome, nuovonome);
if ( rinomina == 0 )
printf ("File rinominato!");
else
printf ("Errore");

printf ("\n\n");
}

Ecco qua. Ho risolto in questo modo. I tanti printf sono per controllare se tutto va bene.

ESSE-EFFE
28-05-2012, 19:32
fgets ( nuovonome, 80, stdin );
printf ( "nuovonome: %s\n", nuovonome );
newline = strlen ( nuovonome ) - 1;
nuovonome [ newline ] = '\0';


Ecco qua. Ho risolto in questo modo. I tanti printf sono per controllare se tutto va bene.

fgets potrebbe anche non inserire il newline. Come dicevo nel mio precedente messaggio, se c'è, è l'ultimo carattere (ma non è detto che ci sia).

Baio84
28-05-2012, 20:29
Allora con un if penso di risolvere:

if ( strrchr ( nuovonome, '\n' ) )
{
newline = strlen ( nuovonome ) - 1;
nuovonome [ newline ] = '\0';
}

Devo dire che pensavo fosse più facile creare un programmino, anche semplice come questo, ma devo ammettere che ci si blocca spesso. Però è stimolante trovare le soluzioni per superare questi ostacoli!

Baio84
28-05-2012, 22:34
Ecco qua il programma completo.
Posto il codice se qualcuno ha voglia di testarlo o magari ha qualche consiglio per ottimizzarlo.

Le uniche cose che al momento so che bisogna migliorare sono:
-la codifica: cioè i caratteri accentati non vengono stampati correttamente. Me la devo studiare bene;
-il riconoscimento tra file e cartelle. Viene effettuato se nel nome del file c'è un punto o meno. Questo va migliorato perchè ormai si possono avere quasi tutti i caratteri immaginabili, e se in una cartella è presente un punto, viene riconosciuta come file, creando anche problemi sulla sua rinomina.

#include <stdio.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>

#define MAX_PATH 100

int main ()
{
int l, rinomina, newline, punto = 0, g;
char vecchionome [80], nuovonome [80], estensione [10];
char dir [MAX_PATH], prima_scelta = '1', unpunto [] = ".", duepunti [] = "..", prog [] = "Programma rinominare.exe", seconda_scelta = 's', si = 's', no = 'n', uno = '1', due = '2';
struct dirent *file;
DIR *aperto;

printf ( "%s\n%s\n\n",
"Programma per rinominare file e cartelle.",
"Verranno rinominati i file e le cartelle all'interno della cartella contenente il programma." );
do
{
if ( prima_scelta != uno && prima_scelta != due )
printf ( "Valore immesso non valido.\n" );
printf ( "1 per cominciare a rinominare - 2 per uscire: " );
scanf ( "%c", &prima_scelta );
while ( getchar () != '\n' );
printf ( "\n\n" );
} while ( prima_scelta != uno && prima_scelta != due );


if ( prima_scelta == uno )
{
printf ( "In caso di file, la loro estensione non verrà modificata.\n\n" );
getcwd ( dir, MAX_PATH );
aperto = opendir ( dir );
while ( file = readdir ( aperto ))
{
if ( strcmp ( file->d_name, unpunto ) != 0 && strcmp ( file->d_name, duepunti ) != 0 && strcmp ( file->d_name, prog ) )
{
do
{
if ( seconda_scelta != si && seconda_scelta != no )
printf ( "Carattere immesso non valido.\n" );
if ( strrchr ( file->d_name, '.' ) )
printf ( "File da rinominare: %s\n%s", file->d_name, "Rinominarlo? s = Sì, n = No " );
else
printf ( "Cartella da rinominare: %s\n%s", file->d_name, "Rinominarlo? s = Sì, n = No " );
scanf ( "%c", &seconda_scelta );
while ( getchar () != '\n' );
printf ( "\n" );
} while ( seconda_scelta != si && seconda_scelta != no );

if ( seconda_scelta == si )
{
printf ( "Inserisci il nuovo nome: " );
sprintf (vecchionome, "%s", file->d_name);
for ( g = 0; g < 10; g++)
estensione [g] = '\0';
if ( strrchr ( vecchionome, '.' ) )
{
l = strlen ( vecchionome );
for ( g = l; vecchionome [g] != '.'; g-- )
punto++;
l -= punto;
for ( g = 0; g < punto; g++ )
{
estensione [g] = vecchionome [l];
l++;
}
punto = 0;
}
fgets ( nuovonome, 80, stdin );
if ( strrchr ( nuovonome, '\n' ) )
{
newline = strlen ( nuovonome ) - 1;
nuovonome [ newline ] = '\0';
}
strcat ( nuovonome, estensione );
rinomina = rename (vecchionome, nuovonome);
if ( rinomina == 0 )
if ( strrchr ( nuovonome, '.' ) )
printf ("File rinominato in %s .", nuovonome);
else
printf ("Cartella rinominata in %s .", nuovonome);
else
printf ("Errore");
printf ("\n\n");
}
else
;
}
}
printf ( "Non ci sono più file da rinominare." );
getchar ();
return 0;
}
else
return 0;
}

ESSE-EFFE
29-05-2012, 09:29
Allora con un if penso di risolvere:

if ( strrchr ( nuovonome, '\n' ) )
{
newline = strlen ( nuovonome ) - 1;
nuovonome [ newline ] = '\0';
}


Non ho guardato il programma completo, ma per verificare la presenza del newline puoi evitare la strrchr:


pnewline = strlen(nuovonome) - 1;
if (nuovonome[pnewline] == '\n') nuovonome[pnewline] = '\0';