PDA

View Full Version : invertire una stringa contenente spazi...con ciclo di ritorno!


angelica
15-11-2003, 17:02
Ciao ragazzi! :)

Mi sono messa a tentare qualcosina con il C.
Quel che mi interessa fare, è un programmino che, data in input una stringa, me la inverta in output; e poi chieda se voglio invertire qualcos'altro e, nel caso, ricominci.

In pratica, vorrei che, dando
mi chiamo angelica
mi venga restituito
acilegna omaihc im

Ora, io ho scritto il seguente programmino:

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

#define max 255

main()

{
char testo[max], risp[max];
void Inverti (char *);

risp[0] = 's';
while(risp[0] == 's')
{
system("cls");
printf("Immetti una stringa di testo da invertire: \n");
scanf("%s",testo); /* gets(testo); */
Inverti(testo);
printf("\n\nLa stringa invertita e':\n");
puts(testo);
printf("\n\nVuoi invertire un'altra stringa? (s/n) : ");
scanf("%s",risp);
while(risp[0] != 'n' && risp[0] != 's')
{
printf("\nrisposta non accettabile! digita per favore s/n : ");
scanf("%s",risp);
}
}
}


void Inverti (char *s)
{
int c;
char *p = s;

for (p += strlen(s) - 1; p > s; p--, s++)
c = *s, *s = *p, *p = c;
}

Solo che non funziona come vorrei, se trova uno spazio, tronca l'inversione:

http://manuangi.altervista.org/immagini/C_Inverti_01.jpg

La colpa è dello scanf, che prende lo spazio come un termina stringa, penso.
Ho provato allora con il gets che vedete nel codice come commento, al posto del primo scanf...il risultato è che la prima inversione me la fa:

http://manuangi.altervista.org/immagini/C_Inverti_02.jpg

Ma quando gliene chiedo un'altra, va direttamente ancora al ciclo di richiesta altra inversione...

http://manuangi.altervista.org/immagini/C_Inverti_03.jpg

Forse è il gets, ma non capisco perché...:cry:

Non è che qualcuno riesce a darmi una mano?
Ci sto sbattendo la testa da un po', ma non riesco a venirne fuori!

L'eseguibile del programmino lo potete scaricare qui (http://manuangi.altervista.org/sw/inverti.exe) (tasto dx mouse -> salva con nome).

Davvero grazie!!

VICIUS
15-11-2003, 18:16
prima di tutto un consiglio. invece di gets usa fgets:
char *fgets(char *s, int size, FILE *stream);
il motivo è che gets non controlla se la stringa in ingresso è piu grande dell'array di destinazione. questo puo portare a dei buffer overflow, problemi di sicurezza e tanti bei crash.

il programma salta l'inserimento delle frasi successive perchè un carattere di infio viene lasciato nel buffer e interpretato dal c come il prossimo inserimento da tatsiera dell'utente.

ciao ;)

angelica
15-11-2003, 21:27
Originariamente inviato da VICIUS
prima di tutto un consiglio. invece di gets usa fgets:
char *fgets(char *s, int size, FILE *stream);
il motivo è che gets non controlla se la stringa in ingresso è piu grande dell'array di destinazione. questo puo portare a dei buffer overflow, problemi di sicurezza e tanti bei crash.[/b]
grazie per la spiegazione...mi puoi aiutare a far andare il proggie? ti prego! :)

allora, ho provato col tuo consiglio.
ho sostituito a gets(testo) fgets(testo,max-1,stdin), ma il comportamento è sempre il solito, al secondo tentativo di inversione:

http://manuangi.altervista.org/immagini/C_Inverti_03.jpg

stessa cosa se metto
fgets(testo,strlen(testo),stdin)
(non so comunque se è corretto chiamare strlen lì)

Non ci sarebbe modo di "dire" a scanf di considerare lo spazio come un carattere?

il programma salta l'inserimento delle frasi successive perchè un carattere di invio viene lasciato nel buffer e interpretato dal c come il prossimo inserimento da tastiera dell'utente.
Quindi, secondo te, risolverei togliendo quel carattere dal buffer...? Sinceramente, non ho idea di come fare...
Caspita, mi sembrava un proggie così semplice, e invece mi sono impantanata...

Se puoi darmi una mano, ti ringrazio davvero!
Tanto il codice l'ho postato!

Grazie!! :)

angelica
15-11-2003, 22:09
ho provato a togliere un '\n' dall'array di input...ma forse tu non intendevi quello, parlando di buffer...?

ho implementato una funzione "togli"
void togli (char *p)
{
while (*p && *p != '\n') p++;
*p = '\0';
}

e, nel main(), chiamo "togli" prima di "inverti"

(...)
printf("Immetti una stringa di testo da invertire: \n");
fgets(testo,max-1,stdin);
togli(testo);
inverti(testo);

...Nulla da fare...cambia però una cosa: alla seconda stringa da invertire, ho questa schermata:

http://manuangi.altervista.org/immagini/C_Inverti_04.jpg

Mi toglie giustamente il "new line" prima di invertire...ma tutto lì... :rolleyes:

grazie per l'aiuto!

ri
15-11-2003, 22:51
premessa: ho provato a capire cosa c'era che non andava nel tuo codice, davvero... però dato che non amo la sintesi estrema nella scrittura di codice a scapito della leggibilità, ho preferito riscrivere il tutto...


#include <stdio.h>
#include <conio.h>
#include <process.h>
#include <string.h>

#define max 255

void Inverti(const char *originale, char* invertita);

void main()
{
char input[max],
output[max];

do
{
// svuoto i buffer
input[0] = output[0] = '\0';

// stampo la "gui"
system("cls");
printf("Immetti una stringa di testo da invertire: \n");

// immissione del testo ed elaborazione
gets(input);
Inverti(input, output);

// stampa output e richiesta operazione
printf("\nLa stringa invertita e':\n");
puts(output);

printf("\nVuoi invertire un'altra stringa? (s/n) : ");
}
while(getch() != 'n');
}

void Inverti(const char *originale, char* invertita)
{
for(int i = strlen(originale) - 1; i >= 0; i--)
*invertita++ = *(originale + i);

*invertita = '\0'; // terminatore di stringa
}

recoil
16-11-2003, 01:17
io ricordo che per risolvere problemi simili mettevo delle getchar in modo da leggere i caratteri di "a capo" per essere pronto a leggere una nuova linea.
qualcosa tipo

while (getchar() == '\n')


cmq ormai sono entrato completamente nel mondo Java quindi non mi capitano più questi problemi :)

verloc
16-11-2003, 08:09
#include <stdio.h>
#include <iostream.h>
#include <sstream>
#include <string>
#include <algorithm> // per reverse:funziona su tutti i containers

using namespace std;

main()
{

cout<<"Scrivi la stringa"<<'\n';
stringstream sstream;
char c;

//il carattere End Of File dalla tastiera è Ctrl+z
while((c=cin.get())!=EOF) sstream<<c;

//estrae la string dallo string stream
string reverted=sstream.str();
//la capovolge
reverse(reverted.begin(),reverted.end());
cout<<reverted;
getchar();


}




In questo modo puoi scrivere anche tutta la Divina Commedia senza buffer overflow

ri
16-11-2003, 10:06
dai si sa che le stl sono un universo avanti... il problema era da risolvere in C :p

VICIUS
16-11-2003, 10:16
Originariamente inviato da angelica
[...] ho sostituito a gets(testo) fgets(testo,max-1,stdin), ma il comportamento è sempre il solito, al secondo tentativo di inversione:
[...]

il parametro "int size" di fgets indica alla funzione il massimo elemento dell'array che puo scrivere senza andare ad invadere in altre aree di memoria. quindi il modo giusto di chiamare fgets è:
fgets (testo, max, stdin);
Originariamente inviato da angelica
[...] stessa cosa se metto
fgets(testo,strlen(testo),stdin)
(non so comunque se è corretto chiamare strlen lì) [...]
qui usare strlen è sbagliato. la funzione ritorna il numero di caratteri da cui è composta la stringa. se la stringa fosse stata vuota (un carattere '\0' nel primo elelmento) non avresti letto niente in ingresso.

ciao ;)

verloc
16-11-2003, 11:07
Originariamente inviato da ri
dai si sa che le stl sono un universo avanti... il problema era da risolvere in C :p


Ma allora vi volete fare proprio male ! :D :D :D

Masochisti! :D

Ciao :)

angelica
16-11-2003, 11:49
Originariamente inviato da VICIUS
il parametro "int size" di fgets indica alla funzione il massimo elemento dell'array che puo scrivere senza andare ad invadere in altre aree di memoria. quindi il modo giusto di chiamare fgets è:
fgets (testo, max, stdin);

Thx...comunque anche con MAX (che avevo provato, senza scriverlo nel post), il programma dà sempre lo stesso errore...
Hai provato a tentare di correggerlo?

Ora provo un po' a guardare quel che ha scritto "ri"...

Ah, ragazzi, dato che ormai mi è venuta la fissa, e il C++ è molto più potente...potete consigliarmi un ottimo posto dove trovare delle risorse?
Considerate che le basi della programmazione le ho già! :sofico: (be', con cicli e puntatori me la cavo! :p )

verloc
16-11-2003, 17:43
Originariamente inviato da angelica
Ah, ragazzi, dato che ormai mi è venuta la fissa, e il C++ è molto più potente...potete consigliarmi un ottimo posto dove trovare delle risorse?
Considerate che le basi della programmazione le ho già! :sofico: (be', con cicli e puntatori me la cavo! :p )


Senza dubbio da quà.

http://www.icce.rug.nl/documents/cplusplus/

e scarica questo: (ti servirà credimi)
http://www.fz-juelich.de/zam/cxx/cxxkurs.pdf

ha una reference della STL string meravigliosa oltre a tantissime altre cose

Luc@s
16-11-2003, 18:07
Originariamente inviato da verloc
e scarica questo: (ti servirà credimi)
http://www.fz-juelich.de/zam/cxx/cxxkurs.pdf

ha una reference della STL string meravigliosa oltre a tantissime altre cose

tnk 100000000000000000

angelica
16-11-2003, 19:15
Originariamente inviato da ri
dai si sa che le stl sono un universo avanti... il problema era da risolvere in C :p


grazie, ri...ho scoperto dove era il problema...non nei vari fgets, gets e compagnia bella...ma nella richiesta finale di un'altra inversione...evidentemente c'è qualcosa che non va nel vettore risp o nello scanf della risposta che si interfaccia col gets del ciclo...non so...

comunque, fgets o gets van bene entrambi...col do while con il getch finale, ho risolto...pensa te! :)
(il getchar mi dava probs perché accetta più di un carattere...)

ti ringrazio...e mi do al C++! :D

bel forum, però, non pensavo di ricevere tanti commenti e aiuti!
di certo mi rifarò sentire con i miei problemi!! :p

ciau! :)

ora vi posto il codice finale del programmino:

#include .....

#define max 255

void inverti(char *);

main()

{
char testo[max];
int c;

do
{
system("cls");
printf("Immetti una stringa di testo da invertire: \n");
gets(testo);
inverti(testo);
printf("\n\nLa stringa invertita e':\n");
puts(testo);
printf("\n\nVuoi invertire un'altra stringa? (s/altro) : ");
}
while((c = getch()) == 's' || c == 'S');
}



void inverti (char *s)
{
int c;
char *p = s;

for (p += strlen(s) - 1; p > s; p--, s++)
c = *s, *s = *p, *p = c;
}