Newsgroup: it.comp.lang.c++
Titolo: consiglio per principiante c++

Salve,
Sto studiando il c++, provengo da java/c# e sto facendo alcuni
esercizi. Uno di questi esercizi è l'implementazione di un algoritmo
di merge sorting. I problemi maggiori sono l'utilizzo delle strutture
dati (in questo caso il vector).
Il codice che ho scritto lancia un eccezione durante l'inserimento nel
vector b con l'ausilio dell'iterator, e non riesco a capire quale sia
l'errore. Qualcuno mi può dare una mano? Inoltre ci sono errori
grossolani di forma o di sostanza in questo codice?
Grazie per l'aiuto. Cordiali saluti.
segue il codice--- il metodo lanciato da un main è: ex01()
#include <string>
#include <list>
#include <vector>
#include <iostream>
#include <cmath>
#include <istream>
#include <iterator>
void merge(std::vector<std::string>& list, int left, int center, int
right);
void mergesort(std::vector<std::string>& list, int left, int right);
void printVector(std::vector<std::string>& v);
void ex01() {
	std::vector<std::string> v;
	std::string input;
	while (input != "quit") {
		std::getline(std::cin, input);
		v.push_back(input);
	}
	mergesort(v, 0, v.size());
	printVector(v);
}
void printVector(std::vector<std::string>& v) {
	std::vector<std::string>::iterator it;
	for (it = v.begin(); it < v.end(); ++it) {
		std::cout << *it << std::endl;
	}
	std::cout << "print end" << std::endl;
}
void merge(std::vector<std::string>& list, int left, int center, int
right) {
		std::vector<std::string>* a = &list;
		std::vector<std::string> b;
		std::vector<std::string>::iterator it;
		b.resize(a->size());
		it = b.begin();
		int i = left;
		int j = center + 1;
		while ((i <= center) && (j <= right)) {
			if (a->at(i) <= a->at(j)) {
				b.insert(it, a->at(i));
				i = i + 1;
			} else {
				b.insert(it, a->at(j));
				j = j + 1;
				it++;
			}
		}
		while (i <= center) {
			b.insert(it, a->at(i));
			i = i + 1;
			it++;
		}
		while (j <= right) {
			b.insert(it, a->at(j));
			j = j + 1;
			it++;
		}
		int k;
		for (k = left; k <= right; ++k) {
			a->at(k) = 
b.at
(k - left);
		}
}
void mergesort(std::vector<std::string>& list, int left, int right) {
	std::vector<std::string>* a = &list;
	printVector(*a);
	if (left < right) {
		int center = int(std::floor((left + right) / 2));
		mergesort(*a, left, center);
		mergesort(*a, center + 1, right);
		merge(*a, left, center, right);
	}
}

 grossolani di forma o di sostanza in questo codice?
Se permetti l'ho "corretto" velocemente sotto Visual Studio (mi diverto 
con la trial del 2010, che vuoi fare...).
Il codice con i commenti sotto. Spesso il tuo codice e' stato commentato 
(per fare comparison veloce)
#include <string>
#include <list>
#include <vector>
#include <iostream>
#include <cmath>
#include <istream>
#include <iterator>
#include <cassert>
void merge(std::vector<std::string>& list, int left, int center, int right);
void mergesort(std::vector<std::string>& list, int left, int right);
void printVector(std::vector<std::string>& v);
void ex01() {
    std::vector<std::string> v;
    // suppongo che vuoi ordinare stringhe generiche e non solo numeri, 
vero ? (Il compare dell'ordinamento con le stringhe non e' proprio 
uguale a quello dei numeri)
    // NOTA: tuo codice era sbagliato, lasciava "quit" nella lista
    std::string input;
    while (true) {
		std::getline(std::cin, input);
		if (input == "quit")
			break;
		v.push_back(input);
    }
    mergesort(v, 0, v.size());
    printVector(v);
}
void printVector(std::vector<std::string>& v) {
    std::vector<std::string>::iterator it;
    for (it = v.begin(); it < v.end(); ++it) {
	std::cout << *it << std::endl;
    }
    std::cout << "print end" << std::endl;
}
void merge(std::vector<std::string>& list, int left, int center, int 
right) {
    std::vector<std::string>& a = list;  // usa direttamente reference
    // puoi usare "list", qui ho mantenuto "a" per evitare di correggere 
codice originale
    std::vector<std::string> b;
    // Correggi caso limite indice finale (i.e. se a.vsize()==4 indice 4 
non puo' essere usato (out of range))
    right = right == list.size() ? right-1 : right;
    //b.resize(a->size());   // NON servono se usi push_back
    //it = b.begin();	    // vedi sotto
		int i = left;
		int j = center + 1;
		while ((i <= center) && (j <= right)) {
			if (a[i] <= a[j]) { // accedi agli elementi con operatore []
				b.push_back(a[i++]);
				//b.insert(it++,a->at(i++);
				//b.insert(it, a->at(i));
				//i = i + 1;
			} else {
				b.push_back(a[j++]);
				//b.insert(it++,a->at(j++));
				//b.insert(it, a->at(j));
				//j = j + 1;
				//it++;
			}
		}
		while (i <= center) {
			b.push_back(a[i++]);
			//b.insert(it, a->at(i));
			//i = i + 1;
			//it++;
		}
		while (j <= right) {
			b.push_back(a[j++]);
			//b.insert(it, a->at(j));
			//j = j + 1;
			//it++;
		}
		assert(b.size() == (right - left + 1));
		//for (int k = left; k <= right; ++k) {
		//	a->at(k) = 
b.at
(k - left);
		//}
		for (int k=left; k<b.size(); k++)
			a[k] = b[k - left];
}
void mergesort(std::vector<std::string>& list, int left, int right) {
	// Non c'e' bisogno di usare sintassi puntatore, basta usare reference
	// come da ingresso. Per mantenere "a" come prima, a e' un alias di list...
	std::vector<std::string>& a = list;
	printVector(a);
	if (left < right) {
		int center = std::floor((left + right) / 2.0);  // .0 serve a 
promuovere in float i parametri ingresso
		mergesort(a, left, center);
		mergesort(a, center + 1, right);
		merge(a, left, center, right);
	}
}
int _tmain(int argc, _TCHAR* argv[])
{
	ex01();
	return 0;
}
Non se se altri vorranno aggiungere ulteriori commenti
PS: Scusa la scarsa indentazione, ma e' tardi
Ciao
gio

> esercizi.
Considera che per codice da produzione e' meglio usare
#include <algorithm>
...
std::sort(v.begin(), v.end());
ciao


Figurati, grazie sei stato chiarissimo.
Saluti
Guido

 nell'utilizzo dell'iteratore.
ma guarda che anche con l'iteratore andava bene, solo che devi 
preallocare lo spazio inizialmente e digitare di piu' (vedi cosa ne 
pensano a proposito i perl-isti :-) ).
A proposito di preallocazione, con la push_back l'ho tolta ma era piu' 
correto/veloce se la lasciavo - usando v.reserve(num_items) - all'inizio 
visto che il num di elementi da inserire era noto.
Il baco nella "merge" e' stato fissato con l'aggiunta di
    right = right == list.size() ? right-1 : right;
Cercavi di accedere ad un elemento non esistente (se size e' n non puoi 
accedere all'elemento n, gli indici cominciano da 0).
Poi nel codice iniziale, mancava un it++ dove sotto commentato
while ((i <= center) && (j <= right)) {
	if (a->at(i) <= a->at(j)) {
		b.insert(it, a->at(i));
		i = i + 1;
		// manca it++
	} else {
		b.insert(it, a->at(j));
		j = j + 1;
		it++;
	}
}
Ciao
Gio

 Gio
Ciao grazie.
Guido
ps. ma come fanno i programmatore di c++ quando usano
l'autocompletamento? In java o c# si capisce la firma del metodo, con c
++ non riesco a capirla se non guardando la documentazione.

 ++ non riesco a capirla se non guardando la documentazione.
L'autocompletamento dipende dall'ambiente di sviluppo, non dal linguaggio.
Evidentemente Eclipse (che io non conosco), o almeno la versione che 
stai utilizzando, non č molto avanzato da quel punto di vista.

 ops, vero, come right posso passare direttamente size()-1
Uhmm, potrebbe non essere cosi' semplice (penso che devi correggere di 
conseguenza i punti dove usi  right).
- gio

 l'autocompletamento?
Mi sa che i programmatori Java sono un po' viziati, vah.
Niente di male ad essere viziati.
In generale in C++ quando impari ad usare per bene la STL e compagnia
dovresti riuscire a scrivere codice leggermente piu' compatto che in
Java e di conseguenza recuperi cosi'.
Comunque alcuni ambienti riescono a completare un po' meglio in C++. Non
saprei darti dei nomi... tempo fa avevo fatto trottare l'omnicomplete di
vim. Ma mi sa che programmativamente sono di altra scuola.
-- 
-riko

 vim. Ma mi sa che programmativamente sono di altra scuola.
Personalmente trovo l'autocompletamento utile quando ancora non conosci 
o sai a memoria il nome dei vari metodi o proprietà soprattutto per 
classi/librerie di terze parti. Così come le informazioni sugli 
argomenti delle funzioni.
Se per autocompletamento si intende la finestrella che elenca appunto i 
vari nomi disponibili.
Marco

 Marco
Sicuramente come programmatore Java sono viziato :)
Però quando si usano decine di librerie con decine di migliaia di
metodi è impossibile muoversi senza documentazione.
L'autocompletamente spesso evita il continuo riferimento alla
documentazione perchè suggerisce l'uso del metodo e le diverse firme.
Sicuramente c++ e java sono scuole diverse, per questo mi sto
documentando :)

 documentazione perch� suggerisce l'uso del metodo e le diverse firme.
Che � quello che ho detto io :) :)
Marco

 documentazione perch� suggerisce l'uso del metodo e le diverse firme.
Non fraintendermi, anche a me piace(rebbe) l'autocompletamento
a-la-java. Non sono sicuramente uno che dice che si sta meglio senza.
Purtroppo io non conosco qualcosa che lo abbia "altrettanto buono".
Sono convinto che dovrebbe esistere; la maggior parte degli IDE hanno
questa funzione, ma in quelli che ho provato io, semplicemente funziona
male oppure l'ide nel suo complesso non mi piaceva (o gira su
piattaforme che non uso). Non ho idea se questo sia dovuto ad errata
configurazione mia o ad altro.
Riesco ad avere risultati decenti con vim+ctags. 
Se oggi dovessi iniziare un progetto Qt con C++, probabilmente valuterei
il loro IDE. Potresti comunque provarlo.
-- 
-riko

 il loro IDE. Potresti comunque provarlo.
Che invece io odio :)
Soprattutto la parte designer � piena di bug o funzionamenti "strani".
Ok, lo so che si parlava di autocompletamento, per�... :)
Marco

 Soprattutto la parte designer � piena di bug o funzionamenti "strani".
Io l'ultima volta che lo avevo usato non avevo avuto grossi problemi.
Possibile che non ci avessi fatto una GUI, tuttavia.
-- 
-riko

 Soprattutto la parte designer è piena di bug o funzionamenti "strani".
curioso, sei il primo che sento che dice questa cosa
ricordi cos'è che trovavi "strano"?
-- 
By ZeD

 ricordi cos'è che trovavi "strano"?
Ora non ce l'ho più sotto mano quindi non posso darti procedure precise 
per ricrearli.
Comunque trovavo estremamente scomodo e "strano" il comportamento dei 
widget layout in particolare. Nel senso che sistemando i controlli nei 
relativi layout e chiudendo e riaprendo la finestra questi ultimi 
venivano a volte spostati. Oppure l'effetto non era quello previsto: 
cioè analizzando il codice generato il posizionamento non era quello 
atteso e soprattutto non sempre ripetibile.
Fai conto che ora sviluppo applicazioni QT con Python e come IDE uso 
Eclipse (dove come plug-in c'è anche il QTDesigner) ma le interfacce 
grafiche le realizzo via codice.
Mi dispiace non poter essere più preciso.
Marco