Torna indietro   Hardware Upgrade Forum > Software > Programmazione

DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker
Analizziamo nel dettaglio DJI RS 5, l'ultimo arrivato della famiglia Ronin progettato per videomaker solisti e piccoli studi. Tra tracciamento intelligente migliorato e ricarica ultra rapida, scopriamo come questo gimbal eleva la qualità delle produzioni.
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming
AMD Ryzen 7 9850X3D è la nuova CPU gaming di riferimento grazie alla 3D V-Cache di seconda generazione e frequenze fino a 5,6 GHz. Nei test offre prestazioni superiori a 9800X3D e 7800X3D, confermando la leadership AMD nel gaming su PC.
Le soluzioni FSP per il 2026: potenza e IA al centro
Le soluzioni FSP per il 2026: potenza e IA al centro
In occasione del Tech Tour 2025 della European Hardware Association abbiamo incontrato a Taiwan FSP, azienda impegnata nella produzione di alimentatori, chassis e soluzioni di raffreddamento tanto per clienti OEM come a proprio marchio. Potenze sempre più elevate negli alimentatori per far fronte alle necessità delle elaborazioni di intelligenza artificiale.
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 28-11-2016, 18:17   #1
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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;
}
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 28-11-2016, 18:50   #2
the_best_hacker
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
the_best_hacker è offline   Rispondi citando il messaggio o parte di esso
Old 28-11-2016, 18:57   #3
Torsen_ITA
Junior Member
 
L'Avatar di Torsen_ITA
 
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.
Torsen_ITA è offline   Rispondi citando il messaggio o parte di esso
Old 28-11-2016, 20:09   #4
71106
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;
}
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 28-11-2016, 21:01   #5
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 08:20   #6
zeMMeMMez
Bannato
 
Iscritto dal: Aug 2016
Messaggi: 871
secondo te sizeof(s) cosa ritorna?
zeMMeMMez è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 09:39   #7
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
Quote:
Originariamente inviato da zeMMeMMez Guarda i messaggi
secondo te sizeof(s) cosa ritorna?
Ah. Forse la dimensione del puntatore all'array? Sbaglio lì?
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 13:14   #8
71106
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
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 13:25   #9
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Quote:
Originariamente inviato da masticaedera Guarda i messaggi
Ah. Forse la dimensione del puntatore all'array? Sbaglio lì?
sei incappato in una feature piuttosto ostica del C e C++. Sarebbe stato meglio seguire una strada piu' semplice come quella delle STL che ti ho indicato, che sono molto ben conosciute e documentate, ma almeno cosi' imparerai qualche dettaglio non ovvio del linguaggio.

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;
Questo stampa "40" perche' la dimensione di int e' 4 byte e ce ne sono 10.

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);
Quindi si, sizeof(s) restituisce la dimensione in byte di un puntatore, che su una macchina a 64 bit e' 8.

Ultima modifica di 71106 : 29-11-2016 alle 13:29.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 15:09   #10
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 15:41   #11
zeMMeMMez
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)
zeMMeMMez è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 16:15   #12
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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;
}
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 16:50   #13
zeMMeMMez
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"
zeMMeMMez è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 17:25   #14
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Quote:
Originariamente inviato da masticaedera Guarda i messaggi
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;
}
la funzione "invert" non ha scopo, non fa altro che invocare un'altra funzione. Inoltre non e' necessario passare l'oggetto string per copia e poi restituirne un'altra copia ancora, lo stai copiando due volte e senza motivo visto che std::reverse cambia la stringa originale.

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;
}
Inoltre non includere <cstring>, che equivale a <string.h> e definisce demenziali funzioncine C come la sopracitata strnlen, bensi' <string> che definisce std::string.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 17:46   #15
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 18:40   #16
zeMMeMMez
Bannato
 
Iscritto dal: Aug 2016
Messaggi: 871
Quote:
Originariamente inviato da masticaedera Guarda i messaggi
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
e come pensi, così tanto per curiosità, di "andare avanti" se non sai fare neppure questo.
prima di camminare devi imparare a gattonare.

PS perchè pensavi fosse "facile"?
zeMMeMMez è offline   Rispondi citando il messaggio o parte di esso
Old 29-11-2016, 19:08   #17
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
Iscritto dal: Jun 2006
Città: Borgosesia (VC)
Messaggi: 509
Quote:
Originariamente inviato da zeMMeMMez
PS perchè pensavi fosse "facile"?
Non lo pensavo.

LM
masticaedera è offline   Rispondi citando il messaggio o parte di esso
Old 30-11-2016, 00:52   #18
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Quote:
Originariamente inviato da masticaedera Guarda i messaggi
Tutto chiaro a parte "const &s"... Perché const e perché &?
"&" definisce un tipo "reference", nel caso specifico un riferimento a std::string. I reference in C++ sono implementati come i puntatori, solo che nel sistema di tipi hanno caratteristiche diverse che li rendono un po' più sicuri da usare, dove in questo caso "sicuri" significa "type-safe". Un esempio basilare è che i reference sono molto più difficili da rendere nulli o invalidi, anche perchè il compilatore è in grado di emettere warnings in alcune delle situazioni "a rischio". In generale diciamo che i reference dovrebbero essere preferiti ai puntatori ovunque possibile. Il problema è che non sempre è possibile.

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;
"s" è un puntatore che punta a un puntatore che punta a un puntatore che punta a un oggetto string. Nella pratica non devi mai scrivere una cosa del genere e col tempo i tuoi occhi impareranno a sanguinare nel vederne, ma è per farti l'esempio.

Ora la domanda: se vuoi rendere immutabile l'oggetto string puntato, dove scrivi "const"? Risposta: a destra di "string":

Codice:
string const ***s;
Se invece avessi voluto rendere immutabile il puntatore a string, a cui s punta con due livelli di indirezione, avresti dovuto metterlo a destra del primo asterisco:

Codice:
string *const **s;
Se invece avessi voluto rendere immutabile il puntatore al puntatore all'oggetto string, avresti dovuto metterlo a destra del secondo asterisco:

Codice:
string **const *s;
E così via.

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.
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 30-11-2016, 01:11   #19
71106
Bannato
 
Iscritto dal: Nov 2014
Messaggi: 292
Ah, dimenticavo. A volte potresti trovare scritto anche così:

Codice:
const string ***s;
È equivalente a:

Codice:
string const ***s;
71106 è offline   Rispondi citando il messaggio o parte di esso
Old 30-11-2016, 10:40   #20
masticaedera
Senior Member
 
L'Avatar di masticaedera
 
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
masticaedera è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


DJI RS 5: stabilizzazione e tracking intelligente per ogni videomaker DJI RS 5: stabilizzazione e tracking intelligent...
AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequenze al top per il gaming AMD Ryzen 7 9850X3D: Zen 5, 3D V-Cache e frequen...
Le soluzioni FSP per il 2026: potenza e IA al centro Le soluzioni FSP per il 2026: potenza e IA al ce...
AWS annuncia European Sovereign Cloud, il cloud sovrano per convincere l'Europa AWS annuncia European Sovereign Cloud, il cloud ...
Redmi Note 15 Pro+ 5G: autonomia monstre e display luminoso, ma il prezzo è alto Redmi Note 15 Pro+ 5G: autonomia monstre e displ...
L'ultima puntata di Falsissimo rimossa d...
NASA Perseverance ha utilizzato percorsi...
Blue Origin sospende per almeno due anni...
Stampanti, Los Angeles verso il divieto ...
Roscosmos Amur: il razzo spaziale riutil...
Robot aspirapolvere per tutte le tasche:...
Accedere alle mail di un lavoratore lice...
Amazon Haul scatenato: migliaia di prodo...
Amazon Seconda Mano rilancia: sconto ext...
Super prezzo Amazon per ECOVACS DEEBOT T...
NVIDIA Shield TV: dieci anni di aggiorna...
Le 10 offerte migliori su Amazon oggi, c...
Autostrade che 'pensano': l'AI arriva su...
AMD alza l'asticella: Zen 6 è la ...
Il satellite spia russo Olymp-1 si &egra...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 12:54.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v