|
|||||||
|
|
|
![]() |
|
|
Strumenti |
|
|
#1 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
[C++] Invertire una stringa
Ciao,
vorrei imparare un po' di C/C++ e ho iniziato, come molti suggeriscono, a scrivere piccoli programmi. In particolare mi sono bloccato su uno in C++ che dovrebbe invertire, con una funzione, una stringa di testo inserita. Non funziona come dovrebbe in quanto stampa sempre e solo un carattere, l'ottavo della riga, e nulla più. Il bello è che ho provato a fare un programma analogo in Fortran e lì mi è venuto al primo colpo! Dove sbaglio? Grazie, Lorenzo Codice:
#include <iostream>
#include <cstring>
#define BUFFER 1000
char invert(char s[]);
main()
{
char input_string[BUFFER];
std::cout << "Inserire una stringa di testo" << std::endl;
std::cin.getline(input_string, 999);
std::cout << "Stringa invertita:" << std::endl;
std::cout << invert(input_string) << std::endl;
return 0;
}
char invert(char s[])
{
char inverted_string[BUFFER];
int j = 0;
int k = sizeof(s)/sizeof(*s);
do
{
inverted_string[j] = s[k];
j++;
k--;
} while (k == 0);
return *inverted_string;
}
|
|
|
|
|
|
#2 |
|
Senior Member
Iscritto dal: Aug 2011
Città: /dev/null
Messaggi: 740
|
A parte che manca un bel pezzo di codice, io ti direi di cercare un modo per utilizzare la classe string.
Se invece vuoi utilizzare le stringhe in stile C ricorda che il terminatore è il carattere '/0' e che la dimensione dell'area di char deve essere nota e costante a tempo di compilazione. Tra l'altro questo valore ti serve a prescindere per creare la funzione.. Inviato dal mio iPhone utilizzando Tapatalk
__________________
Ho concluso con: Zodd_Il_nosferatu - mattxx88 - BlackDavid - Steven1987 - giannireale88 - jumpingflash - fabiolino - adelage - alessandro1189 - MrEnrich |
|
|
|
|
|
#3 |
|
Junior Member
Iscritto dal: Jan 2016
Città: Salerno
Messaggi: 15
|
la condizione del while dovrebbe essere >= 0
Il while viene eseguito fintanto che la condizione è vera. Per come lo hai scritto al primo passaggio la condizione è falsa ed esce fuori. |
|
|
|
|
|
#4 |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Codice:
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main() {
string s = "abcdefg";
reverse(s.begin(), s.end());
cout << s << endl;
}
|
|
|
|
|
|
#5 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
Anzitutto grazie per le risposte.
71106, volevo in realtà farlo senza ricorrere ad algorithm. Però è vero, come dice the_best_hacker, che sono palesemente in difetto nell'apprendimento delle classi. Torsen_ITA, ho provato al volo a cambiare la condizione del while (>=0, >0, oppure mettendo "inverted_string[j] == '\0'", ecc.) ma non cambia nulla. Sospetto che ci sia un problema più che altro nel passaggio dell'array di char alla funzione. LM |
|
|
|
|
|
#6 |
|
Bannato
Iscritto dal: Aug 2016
Messaggi: 871
|
secondo te sizeof(s) cosa ritorna?
|
|
|
|
|
|
#7 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
|
|
|
|
|
|
#8 |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Se non vuoi usare std::reverse te la puoi reimplementare da solo. Qui trovi un esempio di possibile implementazione: http://en.cppreference.com/w/cpp/algorithm/reverse
|
|
|
|
|
|
#9 | |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Quote:
Normalmente la sintassi con le parentesi quadre dichiara array e sizeof restituisce la dimensione dell'intero array espressa in bytes. Esempio: Codice:
int a[10]; cout << sizeof(a) << endl; I parametri di funzione pero'... fanno eccezione. Fanno eccezione perche' gli array vengono sempre passati per puntatore, ma una volta che hai passato un array a un'altra funzione il sistema di tipi perde l'informazione sulla dimensione di quell'array perche' la funzione deve poter accettare array di qualunque dimensione (da cui la possibilita' di non mettere nulla dentro le parentesi quadre, ma solo nelle dichiarazioni di funzioni), quindi si e' deciso che anche a livello semantico i parametri array devono essere dei puntatori a tutti gli effetti anche se vengono dichiarati con la sintassi delle parentesi quadre. Queste due dichiarazioni sono completamente equivalenti: Codice:
void f(char s[]); void f(char *s); Ultima modifica di 71106 : 29-11-2016 alle 13:29. |
|
|
|
|
|
|
#10 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
71106, sei stato chiarissimo e ti ringrazio. Ragionerò sulla base delle indicazioni del tuo post!
LM |
|
|
|
|
|
#11 |
|
Bannato
Iscritto dal: Aug 2016
Messaggi: 871
|
ci sono poi tutta un'altra serie di errori
1) ritorno un char, ma volevi davvero tornare un char? 2) non allochi memoria "nuova" ad ogni chiamata, anzi usi sempre la stessa 3) avresti ovviamente dei leak di memoria 4) per la lunghezza della stringa (in C) puoi usare strnlen (con la n) per mettere un limite superiore 5) non fare mai confronti (vale in generale) del tipo =0 con variabili int (possono essere anche negative) 6) in linea generale la funzione dovrebbe ricevere DUE parametri. Il primo è la stringa da invertire, il secondo la stringa invertita. In questo caso avrai problemi se il secondo parametro non è "buono" 7) oppure un unico parametro, nel qual caso invertirai proprio la stringa che viene passata (personalmente la vedrei come scelta migliore). in questo caso, ovviamente, NON utilizzerai un vettore di "appoggio" in cui invertire la stringa, per poi ricopiarla. Ti basta invertire "a coppie" i caratteri 8) nel tuo "tentativo" hai vari approcci se chiami la funzione di calcolo lunghezza stringa allora userai un ciclo for se invece fai "caserecciamente" attenzione ad avere una dimensione "ragionevole" nella stringa (per gestire il caso in cui manca lo zero finale) |
|
|
|
|
|
#12 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
Così funziona come atteso ma ho usato algorithm. Si poteva fare senza funzione ma volevo vedere se il parametro passava sia in andata che in ritorno.
Leggo che la classe string dovrebbe risolvere automaticamente anche i problemi di allocazione della memoria (in risposta a zeMMeMMez); è così? Qualsiasi tentativo di fare l'inversione "a mano" col tipo string mi si risolveva invece in errori di out of range, quindi per il momento ho lasciato perdere. Codice:
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
string invert(string s);
int main()
{
string input_string;
cout << "Inserire una stringa di testo" << endl;
getline (cin, input_string);
cout << "Stringa invertita:" << endl;
cout << invert(input_string) << endl;
return 0;
}
string invert(string s)
{
reverse(s.begin(), s.end());
return s;
}
|
|
|
|
|
|
#13 |
|
Bannato
Iscritto dal: Aug 2016
Messaggi: 871
|
francamente così non hai imparato nulla.
sporcati le mani, non leggere nessuna soluzione già fatta, impegna la tua testa. fai il "problem solving" |
|
|
|
|
|
#14 | |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Quote:
Se vuoi creare una funzione che produca un nuovo oggetto std::string senza modificare l'originale, passa l'originale per riferimento ed evita di copiarlo una volta di troppo: Codice:
string invert(string const &s) {
string t = s;
reverse(t.begin(), t.end());
return t;
}
|
|
|
|
|
|
|
#15 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
Tutto chiaro a parte "const &s"... Perché const e perché &?
Sul riscrivere "dal basso" ci ripenso più avanti. Molto difficile comunque la logica della programmazione, davvero (ecco perché non mi è mai troppo riuscita!). LM |
|
|
|
|
|
#16 | |
|
Bannato
Iscritto dal: Aug 2016
Messaggi: 871
|
Quote:
prima di camminare devi imparare a gattonare. PS perchè pensavi fosse "facile"? |
|
|
|
|
|
|
#17 | |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
Quote:
LM |
|
|
|
|
|
|
#18 | |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Quote:
Ciò detto ti esorto a documentarti autonomamente sull'argomento che è piuttosto ampio e non mi va di spiegartelo per iscritto. "const" invece marca la parte a sinistra del tipo come immutabile. Ho specificato "la parte a sinistra" perchè "const" può avere varie posizioni nella definizione di un tipo. Prendi ad esempio questo tipo balordo: Codice:
string ***s; Ora la domanda: se vuoi rendere immutabile l'oggetto string puntato, dove scrivi "const"? Risposta: a destra di "string": Codice:
string const ***s; Codice:
string *const **s; Codice:
string **const *s; Quindi, come dicevo, "const" rende immutabile la parte a sinistra del tipo definito. Quindi "string const &s" vuol dire che "s è un riferimento a un oggetto string che non può essere modificato. Se provi a modificarlo all'interno della funzione "invert", il compilatore spara un errore. D'altro canto, chi invoca la funzione "invert" ha garanzie che essa non cambierà il contenuto della stringa passata. Può sembrarti inutile adesso, magari penserai "se non voglio che invert cambi la stringa basta che non la cambio, invert l'ho scritta io". Ma non sarà sempre così, per due motivi: 1. non sempre sarai tu l'autore del codice che usi, molto presto inizierai a usare librerie altrui (come le stesse STL); e 2. quando comincerai a scrivere tonnellate di codice non potrai più fidarti neanche di te stesso perchè la probabilità di commettere errori di programmazione aumenterà con le dimensioni del programma. Lo scopo di un sistema di tipi è quello di impedire determinati tipi di errori bloccando il compilatore qualora tu li commetta. |
|
|
|
|
|
|
#19 |
|
Bannato
Iscritto dal: Nov 2014
Messaggi: 292
|
Ah, dimenticavo. A volte potresti trovare scritto anche così:
Codice:
const string ***s; Codice:
string const ***s; |
|
|
|
|
|
#20 |
|
Senior Member
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
|
71106, la tua spiegazione, pur nella difficoltà dell'argomento, è molto esaustiva! Hai fatto veramente molto e ti ringrazio. Osservo che anche scrivere un programma per un'operazione tutto sommato semplice non è per nulla ovvio e richiede molta documentazione. Non credo che scriverò tonnellate di codice, ma apprendere le basi mi interessa molto e cercherò di fare un po' di pratica in materia.
Diciamo che ci sono probabilmente linguaggi più semplici per imparare, a quanto mi dicono... Comunque oggi magari ci lavoro ancora un po', cerco qualche guida più specifica. Lorenzo |
|
|
|
|
| Strumenti | |
|
|
Tutti gli orari sono GMT +1. Ora sono le: 12:54.



















