
Originariamente inviata da
edoardol
tu mi consigli di partire dal c passare c++ o diretto al c++?
La domanda fondamentale è: C e/o C++ sarebbe il tuo primo linguaggio di programmazione?
Su questo punto vi sono stati ampi dibattiti ai quali hanno partecipato non solo Bjarne Stroustrup (ideatore del secondo linguaggio) ma anche altri mostri sacri come Ed Sutter, Andrew Koenig, Scott Meyers e molti altri. L'orientamento generale è che ambedue i linguaggi siano sconsigliati come abbrivio: il punto di vista più radicale nella didattica, in realtà, sconsiglia sia C che C++ come primo approccio non solo per chi è totalmente digiuno di programmazione, ma anche per elettronici e affini che non abbiano già maturato ampie competenze in linguaggio Assembly e linguaggi di descrizione hardware (i quali hanno peculiarità tutt'altro che banali).
Un tempo il ruolo di "primo linguaggio ideale" nella didattica era ricoperto soprattutto dal Pascal di Wirth, ma anche da vari BASIC (ritenuti assolutamente fuorvianti e deleteri da autorità assolute come Dijkstra e da miriadi di altri programmatori, ivi incluso il sottoscritto, si parva licet magnis componere): oggi in genere ci si orienta più volentieri, e più saggiamente, verso Python.
L'argomento è comunque stato approfondito numerose volte, anche nel recente passato. Ti suggerisco, per una prima panoramica, di leggere con attenzione questo thread. C e C++ sono linguaggi fondamentalmente diversi, richiedono una diversa forma mentis (appropriata la citazione della nozione di paradigma coniata dall'epistemologo Kuhn e permeata ormai da decenni anche nella cultura collettiva) come diversi sono i domini applicativi.
Volendo porre la questione in termini manichei, ci si può rifare a quanto a più riprese asserito dal creatore del linguaggio C++, Stroustrup: C++ nasce esplicitamente per creare applicazioni di grandi dimensioni, pur mantenendo un certo livello di retrocompatibilità con il C. Se "grandi dimensioni" erano, inizialmente, quelle proibitive per Simula (linguaggio di riferimento all'epoca dello sviluppo di C++ nei primissimi anni Ottanta del secolo scorso), Bjarne parla intenzionalmente di "applicazioni" come dominio separato da ciò che è invece programmazione system-level, sviluppo di driver e moduli kernel, e ovviamente cross-development: come mostra la lunga e significativa esperienza di Embedded C++, sono pochissime le caratteristiche di C++ che ha realmente senso prendere in considerazione nello sviluppo su piattaforme embedded, e sono ancora meno le piattaforme che offrono le risorse necessarie, ed i compilatori che supportano estensioni tipo Embedded-C++.
D'altro canto, anche su sistemi convenzionali mainstream usare velleitariamente C++ a livello di system programming e affini è un ottimo modo per essere bersagliati da lanci di pomodori e uova marce, come testimonia un vecchio amico qui. 
Riguardo alla generazione di numeri pseudocasuali, l'argomento è vasto e probabilmente non banale al tuo livello di preparazione. Suggerirei come abbrivio la lettura di questo articolo, eventualmente ignorando i paragrafi più tecnici.
Riguardo alla domanda sulle #define, considera il seguente codice:
codice:
#include <stdio.h>
#include <string.h>
int main(void)
{
char matrix[4][4];
char buff[32];
FILE *fp;
const char FILENAME[] = "boolmat.dat";
size_t curr_row = 0;
size_t i, j;
fp = fopen(FILENAME, "r");
if (NULL == fp)
{
fprintf(stderr, "Errore durante l'apertura del file %s!\n\n", FILENAME);
return 1;
}
while (NULL != fgets(buff, 32, fp))
{
size_t k;
size_t cols = strlen(buff) -1;
if (cols < 4)
{
fprintf(stderr, "Errore nel file %s: dati insufficienti alla riga %d!\n[%s]\n\n",
FILENAME, curr_row +1, buff);
fclose(fp);
return 2;
}
for (k = 0; k < cols; ++k)
{
if (NULL != strchr("01", buff[k]))
{
matrix[curr_row][k] = buff[k] - '0';
}
else
{
fprintf(stderr, "Errore nel file %s: carattere non consentito [%c] alla riga %d!\n[%s]\n\n",
FILENAME, buff[k], curr_row +1, buff);
fclose(fp);
return (3);
}
}
if (MATRIX_SIZE == ++curr_row)
{
break;
}
}
fclose(fp);
printf("Sono state acquisite %d righe.\n", curr_row);
for (i = 0; i < 4; ++i)
{
for (j = 0; j < 4; ++j)
{
printf("%d ", matrix[i][j]);
}
puts("");
}
return 0;
}
Ignora per il momento l'esatta semantica delle operazioni svolte e alcune assunzioni troppo frettolose fatte dallo studente che ha risolto quell'esercizio. Se il docente ti chiedesse di modificare la dimensione della matrice, ad esempio passando da 4x4 a 7x7, quali e quante modifiche dovresti attuare sul sorgente? E se si dovesse modificare la dimensione del buffer di riga? Quali rischi si corrono in operazioni del genere?
L'uso di costanti figurative emulate tramite definizioni di preprocessore (taluni linguaggi le supportano invece esplicitamente), sebbene deprecato o fortemente limitato entro le regole di stile più diffuse, è ampiamente consentito a livello didattico (e non solo) in C, proprio al fine di aggiungere un minimo di flessibilità e mantenibilità, limitando al contempo possibili errori di refactoring. L'uso di costanti numeriche esplicite deve essere il più possibile limitato, essendo inerentemente poco robusto nei confronti del refactoring e più in generale del riuso dei sorgenti. Naturalmente esistono idiomi alternativi, anch'essi caratterizzati da pro e contro, la cui disamina sarebbe comunque fuori luogo in un thread come il presente.