UNIVERSITA' DEGLI STUDI DI ROMA "LA SAPIENZA"

FACOLTA' DI INGEGNERIA

Guida all'uso del TurboC/C++ per la programmazione in C

ANNO ACCADEMICO 2000/01

 
 

1. Ambiente TurboC/C++

Il TurboC/C++ è un ambiente integrato per la messa a punto di programmi in C e in C++. In questo ambiente è possibile creare, correggere, compilare, mandare in esecuzione e memorizzare su disco programmi C/C++.

1.1. L'Ambiente di sviluppo programmi

Lanciando il TurboC/C++ viene visualizzata la schermata seguente:

Tramite i menù è possibile selezionare i comandi desiderati. Questo può avvenire sia utilizzando il mouse sia posizionandosi con le frecce sul comando desiderato e premendo quindi il tasto invio. Ad un comando può inoltre essere associato un tasto F (F1...F10) oppure la combinazione Alt-TASTO F, oppure una sequenza costituita dal tasto Alt seguito da una lettera. La linea in fondo allo schermo indica alcuni comandi eseguibili direttamente con i tasti F. Tra questi il comando F1 per richiedere aiuto (help), cioè spiegazioni sulle operazioni eseguibili nel contesto in cui si lavora ed il comando F10 per spostare il cursore sulla barra dei menù (linea superiore dello schermo).

Se si vuole uscire definitivamente dal TurboC/C++ basta eseguire il comando Quit del menù File (Alt-f e poi q). Se invece si vuole abbandonare temporaneamente l'ambiente TurboC/C++ si usa il comando DOS shell del menù File. Per rientrare in TurboC/C++ si usa il comando DOS exit.

Lo schermo iniziale è diviso in più parti, corrispondenti a finestre denominate: <noname00.c/cpp> (sempre presente), <Output>, <Message>... La finestra di output è quella in cui vengono mostrati i risultati dell'esecuzione dei programmi. La finestra noname00.c/cpp è quella in cui viene scritto il testo del programma, e si chiama finestra di edit. E' possibile ingrandire e spostare queste finestre, se ne possono inserire di nuove e chiudere quelle già aperte. Per aprire finestre vedi: menù File comando Open o New, per spostarle, ingrandirle, chiuderle: menù Window comando Zoom, Size/Move, Close. Tutte le finestre che l'utente apre vengono messe una sotto l'altra, e resta visibile di esse solo il nome (noname00.c/cpp o Output) ed il numero di controllo. Il numero di controllo è quel numero che sta a destra del nome della finestra (ad es. nomame00.c/cpp ha il numero di controllo 1 mentre Output ha il numero di controllo 2) . Solo l'ultima finestra aperta è completamente visibile e tutti i comandi o le funzionalità che si attivano si riferiscono ad essa. Si dice che tale finestra è attiva. Per rendere attiva una finestra si usa Alt-n, con n numero di controllo della finestra che si vuole attivare. Per cambiare finestra attiva, basta premere il tasto F6.

1.2. Come assicurarsi che le compilazioni avvengano tramite il compilatore ANSI C (e non il compilatore C++)

  1. Memorizzare il programma sorgente C in un file avente estensione .C (e non .CPP). Allo scopo di rendere automatico l'uso dell'estensione .c si può intervenire sulla finestra Editor options specificando il suffisso c come Default extension (e non CPP). Tale finestra è accessibile selezionando dal menù Options la voce Editor e nel sottomenù risultante la voce Editor
     
  2. Verificare nella finestra C++ options che la scelta corrispondente a Use C++ Compiler sia CPP extension e non C++ always. Tale finestra è accessibile tramite selezionando dal menù Options la voce Compiler e nel sottomenù risultante la voce C++ options.
     
  3. Infine, per fare riferimento allo standard ANSI del linguaggio C, è opportuno scegliere nella finestra Source options le Keywords ANSI. Tale finestra è accessibile tramite selezionando dal menù Options la voce Compiler e nel sottomenù risultante la voce Source.

 

2. Realizzazione di un programma

Mostriamo le operazioni principali da effettuare per redigere, compilare, eseguire e memorizzare su disco un programma C.

Apertura della finestra di editor

Si esegue il comando Open del menù File (F3), si inserisce nella casella name il nome di un file (cone estensione .c). In questo modo si crea un file con il nome specificato in cui verrà memorizzato il testo del programma (vedi comando Save più avanti). Se il file già esiste in memoria di massa e deve essere modificato, occorre specificarne il nome, ed il direttorio se esso si trova in un direttorio diverso da quello corrente. Viene quindi aperta una finestra col nome specificato, in cui compare il testo del programma contenuto nel file.

Scrittura del programma

Per i comandi dell'editor si rimanda al menù Edit per le operazioni di inserimento e cancellazione del testo ed al menù Search per la ricerca e sostituzione di parti del testo. Si ricorda che le frecce consentono di posizionare il cursore nel punto sul quale si intende lavorare. Quando si ritiene completato il testo del programma questo può essere salvato nel file associato alla finestra tramite il comando Save del menù File (F2). Se si vuole salvare su un nuovo file il comando da utilizzare è Save as, che ne richiede il nome; in questo caso il file di partenza rimane inalterato.

Compilazione del programma

Tramite il comando Compile del menù Compile (Alt-c e poi c). Se la compilazione ha successo, il compilatore segnala Success e premendo un tasto ci si riporta sulla finestra di edit. Se invece ci sono errori o avvertimenti, la finestra di compilazione segnala Errors o Warnings in basso a sinistra. Premendo un tasto, appare la finestra Messages con i messaggi di avvertimento o errore. I messaggi possono essere evidenziati con i tasti freccia. Quando un messaggio è evidenziato, premendo F1 si ottiene una spiegazione estesa dell'errore (ESC per chiudere la finestra). Premendo invio, il cursore si posiziona automaticamente sulla parte di programma in cui è stato commesso l'errore, facilitando così la correzione. Una volta corretto l'errore si deve ricompilare di nuovo il programma, e così via fino a ottenere il messaggio Success. A questo punto conviene salvare nuovamente il programma su file.

Esecuzione del programma

Il comando Run del menù Run (Alt-r seguito da r) compila il programma e, se non vengono individuati errori, lo esegue. L'input e l'output dei dati avvengono nella finestra Output. Per vedere il risultato dell'esecuzione del programma occorre quindi rendere tale finestra attiva. Per interrompere il programma (ad esempio nei casi di non terminazione) si usano i tasti Ctrl-Pausa.

Creazione di una versione eseguibile del programma

Se il programma viene considerato corretto si può costruire una versione eseguibile del programma una versione cioè, che si possa utilizzare senza entrare in TurboC/C++ mandandola in esecuzione direttamente dal DOS. Per fare ciò, si utilizza il comando Make del menù Compile (Alt-c seguito da m). In risposta a tale comando il compilatore memorizza nel direttorio corrente (cioè sul disco rigido o sul floppy) la versione eseguibile del programma (cioè in linguaggio macchina che è direttamente comprensibile dal calcolatore). Si può verificare che nel direttorio corrente viene incluso un file col nome del programma ed estensione exe.
 

3. Individuazione degli errori

Uno degli aspetti più importanti dell'ambiente di programmazione riguarda gli strumenti per l'individuazione degli errori logici contenuti nei programmi. A questo proposito risulta molto utile fare uso degli strumenti offerti dall'ambiente di programmazione.

3.1. Esecuzione del programma istruzione per istruzione

Per ottenere una esecuzione istruzione per istruzione del programma occorre eseguire il comando Trace into del menù Run. Il programma viene compilato e viene posta la barra di esecuzione all'inizio della funzione main(). Ogni volta che si preme F7 viene eseguita l'istruzione successiva.

Consideriamo il programma seguente che somma n interi specificati dall'utente.
 

#include <stdio.h>

int main(void)
{
  int i,m,n;
  int somma = 0;
  printf("Numero dati da sommare = ");
  scanf("%d", &n);
  for (i = 1; i <= n; i++) {
    printf("Prossimo dato = ");
    scanf("%d", &m);
    somma = somma + m;
  }
  printf("Somma = %d\n", somma);
  return 0;
}
Premendo più volte F7 si esegue il programma passo passo. Quando si arriva all'istruzione sottolineata, vengono chiesti dati di input, mostrando la finestra Output, e, per proseguire, occorre inserirli. Nella finiestra Output si può anche verificare l'effetto delle istruzioni di output.

Il comando Step over del menù Run (F8), consente di eseguire in un unico passo l'istruzione corrente, durante l'esecuzione istruzione per istruzione. In particolare quindi, quando si esegue la chiamata ad una funzione in questa modalità, non se ne esegue il flusso completo. Ad esempio:

#include <stdio.h>
int fattoriale(int x)
{
  int i;
  int somma = 1;
  for (i = x; i >= 1; i--)
    somma = somma * i;
  return somma;
}

int main(void)
{
  int numero, fatt;
  printf("Numero = ");
  scanf("%d", &numero);
  fatt = fattoriale(numero);
  printf("Il fattoriale di %d e' %d", numero, fatt);
  return 0;
}
Eseguendo il programma passo passo, arrivati all'istruzione sottolineata dando il comando Step over il sistema restituisce il valore del fattoriale senza eseguire la funzione istruzione per istruzione come invece avrebbe fatto con Trace into.

3.2. Ispezione delle variabili

Durante l'esecuzione passp passo è molto utile verificare il valore delle variabili del programma. A questo scopo occorre specificare le variabili di cui si vuole controllare il valore. Per fare ciò si apre il menù Debug (Alt-d;) e si esegue il comando Watches. Così facendo si attiva un sottomenù nel quale si deve scegliere Add watch. Add watch chiede le Watch Expression, cioè il nome delle variabili di cui si vuole controllare il flusso (si può attivare direttamente l'opzione Add watch premendo Ctrl-F7). Facendo riferimento al programma precedente che somma n interi, può essere utile controllare il valore che assumeranno istruzione dopo istruzione le variabili somma ed n: queste sono le Watch Expression che vanno inserite. Per vedere il valore di tali variabili occorre attivare la finestra Watch, tramite il menù Windows (Alt-w) e si esegue il comando Watch. In tale finestra compaiono i valori che assumono le variabili specificate in precedenza. Se il programma ancora non è stato mandato in esecuzione nella finestra Watch accanto al nome della generica variabile ci sarà: Unknown symbol. Non appena si manda in esecuzione passo passo il programma le variabili assumono i valori determinati dall'esecuzione del programma. Si noti che quando ci sono due variabili con lo stesso nome in due blocchi diversi, viene mostrato il valore della variabile visibile nella parte di programma in esecuzione.

Durante l'esecuzione passo passo, si può anche effettuare un controllo più fine sulle variabili mediante il comando Inspect... dal menù Debug. Questa modalità di ispezione, che funziona solo quando il programma è in esecuzione, permette di visualizzare, oltre al valore di una variabile, anche il tipo dichiarato, e l'indirizzo a partire dal quale essa è memorizzata. Questo è molto utile quando si hanno assegnazioni inaspettate, dovute ad indirizzi fuori controllo. Si consideri il seguente programma, che contiene un errore molto comune in C:

#include <stdio.h>

int main(void)
{
  int a = 5;
  int b[3];
  int i;

  for (i = 0; i <= 3; i++) 
     b[i] = 1;
  printf("valore di a = %d; valori di b = [%d, %d, %d]", 
       a,    b[0], b[1], b[2]);
  return 0;
}
il programma stampa: valore di a = 1; valori di b = [1, 1, 1]
e quindi ha cambiato anche il valore di a; perché?

La risposta si può trovare usando l'esecuzione passo passo, e, dopo aver passato le dichiarazioni, facendo Inspect... sia di a, che di b. Osservate che ispezionare un vettore significa ispezionare tutte le sue componenti. L'indirizzo di a è visibile in alto a sinistra nella finestra di Inspect. Nell'installazione in Laboratorio, esso è DS:FFF4; (DS sta per Data Segment; si veda lo Help per maggiori dettagli) quello di b[0], è DS:FFEE (entrambi in notazione esadecimale). Poiché un intero in TurboC occupa due byte, b[1] ha indirizzo DS:FFF0, b[2] DS:FFF2. Quando i giunge a 3, b[3] ha indirizzo DS:FFF4, che è lo stesso di a, e quindi, assegnando 1 a b[3], in realtà assegna 1 ad a.

3.2.1 Finestre durante l'esecuzione passo passo con ispezione

In questa fase è utile posizionare le finestre in modo da avere sempre sotto gli occhi la finestra Watch, e quella del programma da controllare. Per ridimensionare una finestra si usa il comando Tile del menù Windows. In alternativa si può usare il comando Size/Move del menù Windows: muovendo il mouse o usando le frecce la finestra attiva si sposta e si può organizzare lo schermo a proprio piacimento. Le finestre di Inspect sono invece visibili durante l'esecuzione passo passo, e vengono automaticamete chiuse alla fine dell'esecuzione.

3.3. Punti di arresto

L'esecuzione istruzione per istruzione risulta impraticabile non appena le dimensioni dei programmi e dei dati diventano significative. Si può per questo eseguire il comando Go to cursor del menù Run, che provoca l'esecuzione di tutte le istruzioni da quella corrente fino al punto in cui è posizionato il cursore. Nella finestra Watch compaiono i valori delle variabili aggiornate fino all'ultima istruzione eseguita.

Si può infine richiedere l'arresto dell'esecuzione del programma solo in determinati punti usando i comandi Toggle breakpoint e Breakpoint del menù Debug.

Toggle Breakpoint attiva e disattiva punti di arresto incondizionato, mentre Breakpoint permette di definire e controllare i punti di arresto. All'esecuzione di tale comando si apre una finestra in cui c'è l'elenco dei punti di arresto, la condizione ed il passaggio a cui tale punto di arresto si attiva. Se sono presenti dei punti di arresto incondizionati, cioè inseriti col comando Toggle breakpoint non c'è né la condizione che li determina nè il passaggio in cui vengono attivati. Se si vuole inserire un punto di arresto, si deve scegliere l'opzione Edit con Alt-e : si apre così una finestra di dialogo in cui si possono inserire le seguenti informazioni:
 

Condition - condizione
Pass Count - numero di passaggio prima dell'attivazione
File Name - nome del file
Line Number - numero della riga del punto d'arresto

3.4. La pila delle attivazioni

La pila delle attivazioni (chiamate) di funzione può essere molto utile per esaminare l'esecuzione del programma. Per vedere la pila delle chiamate di funzione si deve esegue il comando Call stack nel menù Debug, durante l'esecuzione passo passo. Questo comando apre una finestra in cui è mostrata la pila delle attivazioni nello stato corrente del programma. Si consideri il seguente programma che contiene una procedura ricorsiva per il calcolo del fattoriale.
#include<stdio.h>

void fattoriale(int* totale, int numero)
{
  if (numero > 1) {
    *totale = numero * (*totale);
    fattoriale(totale, numero-1);
  }
}

int main(void)
{
  int fatt = 1;
  int n;
  printf("Inserisci un numero:  ");
  scanf("%d", &n);
  fattoriale(&fatt, n);
  printf("Il fattoriale e' %d\n", fatt);
  return 0;
}
Supponendo che al programma venga fornito il valore 4, eseguendo il comando Call stack subito dopo la quarta chiamanta alla funzione fattoriale() si ottiene:
fattoriale(1,DS:FFF4)
fattoriale(2,DS:FFF4)
fattoriale(3,DS:FFF4)
fattoriale(4,DS:FFF4)
main()
Si noti che l'ordine dei parametri è invertito rispetto a come essi sono dichiarati nell'intestazione della funzione. Si noti inoltre che tutte attivazioni della funzione fattoriale() hanno il parametro totale pari a DS:FFF4 perchè tutte le chiamate fanno riferimento alla stessa locazione di memoria (la locazione memorizzata nel parametro totale, che è un puntatore).
 

4. I comandi dei menù

4.1. Menù File

4.2.Menù Edit

4.3. Menù Search

4.4. Menù Run

4.5. Menù Compile

4.6. Menù Debug

4.7. Menù Project

Non trattato (serve per definire un progetto - programma C/C++ diviso su più file).

4.8. Menù Options

Non trattato. Qui ricordiamo solo che per lavorare con il compilatore ANSI C si devono selezionare le seguenti opzioni:

4.9. Menù Window

4.10. Menù Help


 

5. Ambiente TurboC/C++: Domande poste frequentemente (FAQ)

Indice FAQ

5.1. Generalità

5.2. Interagire con l'editor

5.3. Caricare e salvare file

5.4. Compilare ed eseguire un programma


Il presente documento è stato redatto da Giuseppe De Giacomo e Francesco M. Donini, Dipartimento di Informatica e Sistemistica, Universita' di Roma "La Sapienza", ed è basato sul materiale di diversi colleghi, in particolare Marco Cadoli, Diego Calvanese, Fabrizio D'Amore, Carla Limongelli, Marco Temperini.