[RISOLTO] Prova di informatica insufficiente?

giuscri
..oggi hanno pubblicato i risultati dell'esame di informatica.

La mia prova non è stata valutato nemmeno sufficiente. Vi dico che è una sorpresa spiacevolissima perché credevo d'averlo passato anche molto bene. Eppure mi sembra molto strano perché insufficiente è grave! Vi chiedo di dare uno sguardo al codice per favore, perché non ci credo che non mi sia stato proposto nemmeno un 18 -e andare a fare "reclamo" dal professore mi sembra una cosa poco seria.

So che non posso prendervi per controllori di codice, ma sono un po' deluso e vi chiedo di prestare attenzione.

Il programma deve:

* leggere da un file "coppie.dat" coordinate cartesiane relative a dei punti sul piano.



* salvare i valori su un vettore monodimensionale di lunghezza iniziale pari a $k = 20$ che deve essere "allungato" ogni volta che il numero di elementi caricati supera il numero di posti dell'array (i.e. devo fare uso dei puntatori).

* stampare a video le coppie.

* per ogni punto va calcolata la distanza dall'origine, questa va memorizzata in un vettore.

* ordinare il vettore delle distanze dall'origine.

Ultimo punto, ma non vi chiedo di controllarlo: devo mettere le distanze dall'origine in un istogramma usando il programma ROOT.

Questo è quello che ho consegnato:


#include "dichiarazioni.h"

using namespace std;

int main(int argc, char** argv){

	// TApplication app("App", &argc, argv); // Riga necessaria al programma ROOT

	//Punto 1: caricamento del vettore.

	int i = 0;
	int N = 20;

	float *v = new float[N];

	float coordinata;

	ifstream ingresso;	
	ingresso.open("coppie.dat");

	ingresso >> coordinata;

	while(!ingresso.eof()){

		

		if(i == N){
			float *w = new float [N*2];
			for(int j = 0; j < N; j++)
				w[j] = v[j];
				delete v;
				v = w;
				N *= 2;
		}

		

		v[i] = coordinata;

		i++;

		ingresso >> coordinata;

	}

	ingresso.close();

// Il vettore doveva essere monodimensionale.
// Quindi ho caricato tutte le coordinate, una dopo l'altra:
// agli indici dispari ho le ascisse dei punti
// in quelli pari ho le ordinate.


	ofstream uscita;
	uscita.open("risultati.dat");

	stampaVettore(v, i);

	uscita << "Stampa delle coppie ordinate:\n";

	for(int  j = 0; j < i - 1; j++){
		uscita << v[j] << " " << v[j + 1] << endl;
		j++;
	}

	uscita << endl;

	//Punto 2:

// Per il vettore delle distanze dall'origine non
// ho bisogno dell'allocazione dinamica, né
// il testo me lo chiede esplicitamente.
// So già che mi serviranno i/2 posti, dove
// i è il numero totale di coordinate caricate
// (ascisse e ordinate insieme):

	const int M = i / 2;

	float vettoreDistanze[M];

	for(int  j = 0; j < M; j ++){

		vettoreDistanze[j] = pow(v[j], 2) + pow(v[j + 1], 2);

// Quì la definizione di distanza è palesemente sbagliata... Me ne accorgo solo ora.

	}

	qSort(vettoreDistanze, 0, M - 1);

	stampaVettoreDistanze (vettoreDistanze, M);

	uscita << "Stampa del vettore delle distanze dall'origine:\n";

	for(int j = 0; j < M; j++)
		uscita << vettoreDistanze[j] << endl;
	uscita << endl;

	cout << "Per aprire la finestra con il grafico di ROOT";
	cout << "premere <return>:\n";

	cin.get();

/*

	TH1F *h1 = new TH1F("h1", "Istogramma", 20, 0., vettoreDistanze[M - 1]);

	for(int  j = 0; j < M; j++)
		h1->Fill(vettoreDistanze[j]);

	h1->Draw();

	app.Run();

*/

// La parte commentata sopra è
// relativa al programma ROOT.
// Sono sicuro che funzioni
// perché quello che dobbiamo
// fare è un copia-incolla
// delle istruzioni che ci hanno consegnato:
// i.e. non possiamo fare errori su quella parte.

	return 0;

}



Il file dichiarazioni.h contiene invece il seguente codice:


#include <iostream>
#include <fstream>
#include <cmath>
// #include "TApplication.h" // Libreria per ROOT
// #include "TH1F.h"           // Libreria per ROOT

using namespace std;

void scambia(float* a, float* b){

	float c = *a;
	*a = *b;
	*b = c;

	return;

}

void qSort(float* v, int sx, int dx){  // Ordinamento con quickSort:

	int i = sx;
	int j = dx;

	float pivot = (v[sx] + v[dx]) / 2;

	do{

		while(v[i] < pivot)
			i++;
		while(v[j] > pivot)
			j--;

		if(i <= j){

			scambia(&v[i], &v[j]);
			i++;
			j--;

		}

	}while(j >= i);

	if(j > sx)
		qSort(v, sx, j);
	
	if(i < dx)
		qSort(v, i, dx);

	return;

}	

void stampaVettore(float* v, int i){

	cout << "Stampa delle coppie ordinate\n";

	for(int  j = 0; j < i - 1; j++){
		cout << v[j] << " " << v[j + 1] << endl;
		j++;
	}

	cout << endl;

	return;

}

void stampaVettoreDistanze(float* vettore, int numElementi){

	cout << "Stampa del vettore delle distanze dall'origine:\n";

	for(int j = 0; j < numElementi; j++)
		cout << vettore[j] << endl;

	cout << endl;

	return;

}



Grazie come al solito. :roll:

Risposte
giuscri
EDIT: Ho chiesto al professore un colloquio e lui m'ha mandato le sue correzioni:


1. Raddoppia la dimensione del vettore
2. File .h usato in modo errato.
3. Vettore delle distanze non dinamico ma di dimensione determinata a runtime.
4. Ordina solo il vettore delle distanze, non le coppie.
5. Teorema di Pitagora sbagliato:
I=C1^2+C2^2
Voto: insuff.


Credo principalmente di non aver letto bene la traccia; mi riferisco ai punti 1, 3, 4. Be', vi ringrazio ad ogni modo. Dovrò perdere altri sei mesi. :roll:

claudio862
Non te la prendere troppo, è capitato a tutti di non passare un esame al primo colpo.

Qualche commento (che a dire il vero avrebbe dovuto fare il professore):

1) Il vettore iniziale forse avrebbe dovuto essere un vettore di coppie. Così in ogni elemento del vettore avresti avuto una riga del file coppie.dat.

struct Coppia
{
    float x;
    float y;
};

...

int N = 20;
Coppia * v = new Coppia[N];

float x, y;
ingresso >> x >> y;
if (i == N)
    allunga vettore;

v[i].x = x;
v[i].y = y;

Non è che quello che hai fatto tu sia sbagliato, però è sicuramente un po' contorto.
Inoltre con il tuo metodo il for sarebbe meglio scriverlo così:

for(int  j = 0; j < i; j += 2){
    uscita << v[j] << " " << v[j + 1] << endl;
}

Così è più chiaro che visiti il vettore due elementi alla volta.

2) Nel file .h ci vanno solo le dichiarazione delle funzioni (i prototipi), le definizioni vanno in un file .cpp (oppure le dichiari inline). Non usare mai using namespace ... in un file .h (e preferibilmente nemmeno da altre parti). Infine la funzione scambia() esiste già, si chiama std::swap(), ed esiste anche la funzione di ordinamento std::sort() (anche se magari per un esame è richiesto di scriverle te).

3) La dimensione del vettore deve essere una costante nota durante la compilazione. Non basta assegnare un valore variabile ad una costante, altrimenti potresti fare

int temp;
std::cin >> temp;
const int N = temp;
float v[N]; // Errore, N non è noto a compile time

giuscri
"claudio86":

1) Il vettore iniziale forse avrebbe dovuto essere un vettore di coppie. Così in ogni elemento del vettore avresti avuto una riga del file coppie.dat.

struct Coppia
{
    float x;
    float y;
};

...



Certo! Però nella traccia era richiesto esplicitamente l'uso di un vettore monodimensionale.

"claudio86":

Inoltre con il tuo metodo il for sarebbe meglio scriverlo così:

for(int  j = 0; j < i; j += 2){
    uscita << v[j] << " " << v[j + 1] << endl;
}

Così è più chiaro che visiti il vettore due elementi alla volta.


Già. (Per un attimo avevo creduto ci fossero problemi con la condizione -di primo istinto avrei imposto $j < i-1$; poi ho capito meglio come funziona il ciclo che hai scritto :wink: ).

"claudio86":
2) Nel file .h ci vanno solo le dichiarazione delle funzioni (i prototipi), le definizioni vanno in un file .cpp (oppure le dichiari inline). Non usare mai using namespace ... in un file .h (e preferibilmente nemmeno da altre parti). Infine la funzione scambia() esiste già, si chiama std::swap(), ed esiste anche la funzione di ordinamento std::sort() (anche se magari per un esame è richiesto di scriverle te).


Sì; della funzione swap e sort non ce ne hanno mai parlato e ora ti dico che l'obiettivo era di farle scrivere a noi. Personalmente però mi saranno molto utili, grazie.

"claudio86":
3) La dimensione del vettore deve essere una costante nota durante la compilazione. Non basta assegnare un valore variabile ad una costante, altrimenti potresti fare

int temp;
std::cin >> temp;
const int N = temp;
float v[N]; // Errore, N non è noto a compile time


Quest'errore è stato veramente scandaloso, dato che c'era stata una bella discussione su questa roba quì sul forum.

Grazie Claudio.

Buona giornata,

Giuseppe

Rispondi
Per rispondere a questa discussione devi prima effettuare il login.