PDA

View Full Version : [C] Domande da principiante


Sick Boy
08-05-2008, 11:50
ciao,
mi sto addentrando nel mondo del C per un esame, ma ho molti problemi nel cominciare. Per questo ho aperto questo thread, in modo da postare qui tutte le domande che mi verranno nel corso dello studio (anche quelle di altri sono bevenute ovviamente!).

Per prima cosa: un esercizio mi chiede di creare un programma per il conteggio dei caratteri di tabulazione, di newline e di spazio in un testo in ingresso.

ho pensato a una cosa del genere:

#include <stdio.h>

int main()
{
int c;
int ns, nt, nl;

ns = 0;
nt = 0;
nl = 0;

while((c = getchar()) != EOF)
{
if(c == '\n')
++nl;
else if(c == '\t')
++nt;
else if(c == ' ')
++ns;
}
printf("Spazi: %d\n", ns);
printf("Tabulazioni: %d\n", nt);
printf("Righe: %d\n", nl);
}


ma il programma non funziona correttamente. dove ho sbagliato?

grazie

Sick Boy
08-05-2008, 15:25
perfetto! ora funziona! grazie!

in una versione precedente usavo EOF e fino a un certo punto mi dava risultati corretti (chiudevo il programmacon control+C)

DanieleC88
08-05-2008, 18:59
Dichiara la variabile c come char, e non come int. :)

Comunque l'EOF lo puoi dare facilmente anche via tastiera, su Linux con Control+D, su Windows con Control+Z. ;)

DanieleC88
08-05-2008, 19:05
Whoops è vero! :fagiano: :( :muro:

Sick Boy
14-05-2008, 15:41
ciao!

sono alle prese con un altro programma: devo calcolare la lunghezza delle parole inserite in input (da linea di comando) e poi crearne un istogramma in base alla loro lunghezza.

in parole povere: l'output del programma dovrebbe essere per esempio:

parole con 0 lettere:
parole con 1 lettere: X
parole con 2 lettere: XXX
parole con 3 lettere: XXXXXX
...

per ora ho evitato di stampare già le X per l'istogramma, ma ho comunque molti problemi.
questo è quello che ho provato a fare fin'ora:

#include <stdio.h>
#define MAX 20

int main()
{
int lung, c, i, fin, n;
int parole[MAX], ndigit[MAX];

for(i = 0; i < MAX; ++i)
ndigit[i] = 0;

lung = i = 0;

while((c = getchar()) != EOF)
{
if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
++lung;
else if(c == ' ')
{
parole[i] = lung;
lung == 0;
++i;
}
fin = i;
}

for(i = 0; i <= fin; ++i)
{
n = parole[i];
++ndigit[n];
fin = i;
}

for(i = 0; i <= MAX; ++i)
printf("Parole con %d lettere: %d", i, ndigit[i]);
}


dunque:

- l'uso di MAX deriva dal fatto che non mi ha permesso di definire un array di interi vuoto (e già qui è un problema, che ho pensato di risolvere usando l'intero "fin" che sarebbe l'indice finale dell'array riempito, ma su cui ho MOLTI dubbi)
- il funzionamento del ciclo while mi sembra corretto perchè controlla se il carattere in ingresso è una lettera (ho usato la tabella ASCII per fare il controllo del if), incrementa la variabile "lung", mentre se è uno spazio il valore della lunghezza della parola viene inserità nell'array "parole", "lung" viene riportata a 0 per il prossimo calcolo e l'indice dell'array viene incrementato. infine ho pensato di assegnare alla variabile "fin" il valore di "i" così da avere il valore totale degli indici dell'array.
- l'ultima parte è piena di dubbi: ho usato un secondo array "ndigit", per calcolare le varie occorrenze di lunghezze di parole (es: se ci fossero due parole di 3 lettere, allora all'indice 3 di ndigit avremo il valore 2), ma nonostante questo ho dei problemi.

dove ho sbagliato?
grazie!

DanieleC88
14-05-2008, 15:54
No, un'array vuoto non avrebbe senso, e la larghezza variabile la puoi ottenere usando dei puntatori. Comunque, se la lunghezza massima è 20, puoi definire un'array di 20 interi inizializzati a zero, leggere la lunghezza di ogni singola parola, ed incrementare l'intero presente nell'indice (lunghezza-1) dell'array - la lunghezza è l'unico dato che ti interessi realmente, o mi sbaglio? :)

Una cosa tipo:
int nWordLength[N_MAX] = {0};
int nLength = 0;
char cInput = 0;

while ((cInput = getchar()) != EOF) {
if (isalpha(cInput)) {
nLength++;
continue;
}
else if (cInput == ' ') {
++nWordLength[nLength-1];
nLength = 0;
}
}

StampaIstogramma();
(è solo un esempio, non prenderlo come vero "codice")

Comunque prova ad usare isalpha() invece che tutti quei controlli sul carattere, è una macro standard e dovrebbe funzionare.

Sick Boy
14-05-2008, 18:45
No, un'array vuoto non avrebbe senso, e la larghezza variabile la puoi ottenere usando dei puntatori. Comunque, se la lunghezza massima è 20, puoi definire un'array di 20 interi inizializzati a zero, leggere la lunghezza di ogni singola parola, ed incrementare l'intero presente nell'indice (lunghezza-1) dell'array - la lunghezza è l'unico dato che ti interessi realmente, o mi sbaglio? :)

Una cosa tipo:
int nWordLength[N_MAX] = {0};
int nLength = 0;
char cInput = 0;

while ((cInput = getchar()) != EOF) {
if (isalpha(cInput)) {
nLength++;
continue;
}
else if (cInput == ' ') {
++nWordLength[nLength-1];
nLength = 0;
}
}

StampaIstogramma();
(è solo un esempio, non prenderlo come vero "codice")

Comunque prova ad usare isalpha() invece che tutti quei controlli sul carattere, è una macro standard e dovrebbe funzionare.

si, mi interessa solo la lunghezza delle parole e quante volte parole di una certa lunghezza si ripresentano.
con isalpha si alleggerisce molto il codice, però bene o male era come avevo fatto io, mentre il mio problema è più nel aumentare un "counter" per le parole di lunghezza uguale e poi stamparlo a video!

DanieleC88
14-05-2008, 18:55
Vabbe', lo scheletro è quello, ma era per farti vedere una specie di pseudocodice che potevi usare solo una array e un contatore per fare tutto, riduce un po' il lavoro che devi fare e migliora la leggibilità. Per il resto credo andasse bene. ;)

dreadknight
15-05-2008, 10:00
ciao!

sono alle prese con un altro programma: devo calcolare la lunghezza delle parole inserite in input (da linea di comando) e poi crearne un istogramma in base alla loro lunghezza.

in parole povere: l'output del programma dovrebbe essere per esempio:

parole con 0 lettere:
parole con 1 lettere: X
parole con 2 lettere: XXX
parole con 3 lettere: XXXXXX
...

per ora ho evitato di stampare già le X per l'istogramma, ma ho comunque molti problemi.



prova ad usare la funzione strlen, che restituisce la lunghezza di una stringa. Però ricordati di includere la libreria string.h

Sick Boy
15-05-2008, 11:32
ho provato a fare come dicevi tu daniele e va già meglio!
però non mi funziona per ogni input! ad esempio per parole di 9 lettere non mi funziona!

riposto il codice modificato:

#include <stdio.h>
#define MAX 20

int main()
{
int lung, c, i;
int parole[MAX] = {0};

lung = i = 0;

while((c = getchar()) != EOF)
{
if(isalpha(c))
{
++lung;
continue;
}
else if(c == ' ')
{
++parole[lung];
lung = 0;
}
}

for(i = 0; i <= MAX; ++i)
printf("Parole con %d lettere: %d\n", i, parole[i]);
}

dreadknight
15-05-2008, 11:35
la variabile c e l'array li devi dichiarare come char, visto che stai inserendo dei caratteri e non dei numeri

Sick Boy
15-05-2008, 12:19
la variabile c e l'array li devi dichiarare come char, visto che stai inserendo dei caratteri e non dei numeri

con getchar() si usano gli interi, mentre nell'array non inserisco nessun carattere, ma solo l'intero che corrisponde alla lunghezza delle parole della stringa in ingresso!

DanieleC88
15-05-2008, 13:53
Da me veramente pare funzionare... fai una cosa però, non controllare solo (c == ' '), anche quella sostituiscila con isspace(c), che controlla anche altre punteggiature e altri separatori, fai prima.

Comunque:
per usare le macro isalpha() e isspace() devi include ctype.h la funzione main() deve restituire un intero: dai un return 0; alla fine non controllare (i <= MAX) nell'ultimo for, o avrai 21 iterazioni che leggeranno un elemento fuori dal vettore: controlla solo (i < MAX)

ciao ;)

Sick Boy
20-05-2008, 12:08
qui c'è la versione finale!
in fase di stampa ho modificato in modo che stampi una X a ogni occorrenza di una parola di una certa lunghezza, mentre non stampi nulla se non ci sono occorrenze di parole di una certa lunghezza.
ci può essere qualche ottimizzazione secondo voi?
sapete se c'è qualche funzione standard di C per calcolare le prestazioni (tempo e memoria) di un programma?

#include <stdio.h>
#include <ctype.h>
#define MAX 20

int main()
{
int lung, c, i, n;
int parole[MAX] = {0};

lung = i = 0;

while((c = getchar()) != EOF)
{
if(isalpha(c))
{
++lung;
continue;
}
else if(isspace(c))
{
++parole[lung];
lung = 0;
}
}

for(i = 0; i < MAX; ++i)
{
if(parole[i] == 0)
{
continue;
}
else if(parole[i] != 0)
{
printf("Parole con %d lettere: ", i);
for(n = 1; n <= parole[i]; ++n)
printf("X");
}
printf("\n");
}
return 0;
}

DanieleC88
20-05-2008, 12:14
sapete se c'è qualche funzione standard di C per calcolare le prestazioni (tempo e memoria) di un programma?
Se usi un sistema Unix puoi lanciare il programma usando:
time ./<programma>
E vedrai il tempo impiegato.

Altrimenti, se vuoi farlo da codice, ci sono vari modi. Puoi usare clock() (http://linux.die.net/man/3/clock), ad esempio.

Sick Boy
22-05-2008, 15:13
ciao!

ho bisogno di un aiuto per un programma che copi due concateni due stringhe, tramite l'uso di puntatori. senza usare funzioni della libreria standard.

ho provato a fare così:

#include <stdio.h>

int main()
{
strcon(char *s, char *t)
{
while(*s != '\0')
s++;

while(*t != '\0')
{
s + t;
t++
}
}
}

ma con pessimi risultati!
sapete dirmi i (numerosi) punti in cui ho sbagliato e perchè?
grazie.

wingman87
22-05-2008, 15:46
while(*t != '\0')
{
s + t;
t++
}
Il pezzo di codice che ti ho evidenziato non fa nulla..

PS: Nel tuo corso non avete ancora parlato di allocazione dinamica? Se sì in questo esercizio penso che dovresti sfruttarla, se no non importa, continua così

Sick Boy
22-05-2008, 21:18
perchè non fa nulla?

grigor91
22-05-2008, 21:20
perchè non fa nulla?

perchè il risultato della somma non è assegnato a nessuna variabile.

Sick Boy
23-05-2008, 11:48
è vero! ho fatto un sacco di errori in quel codice! dovevo essere fuso!

comunque ho modificato un po' la funzione è compilando questo codice non mi da errore (solo 2-3 warning).

#include <stdio.h>

int main()
{
char *(strcon)(char *s, char *t)
{
char *str;
while(*s != '\0')
{
str = s;
s++;
str++;
}

while(*t != '\0')
{
str = t;
t++;
str++;
}
return *str;
}

return 0;
}

però non sono sicuro che funzioni correttamente (ho il dubbio che in str copiasse prima la stringa s e poi la sovrascrivesse con la stringa t). nel main che cosa potrei inserire per testarlo?
grazie ancora per la pazienza

DanieleC88
23-05-2008, 15:53
nel main che cosa potrei inserire per testarlo?
Una bella printf()? :Prrr:
while(*s != '\0')
{
str = s;
while(*t != '\0')
{
str = t;

Anche queste non fanno un bel nulla, dovevi usare *str = *s e *str = *t.

Sick Boy
11-06-2008, 14:12
ciao!

ho trovato su internet questa implementazione di un albero rosso-nero (è solo una parte):

typedef int key;

typedef enum { red, black } color;

struct rbnode {
key v;
color c;
struct rbnode *left, *right, *up;
};

typedef struct rbnode rbnode;

typedef struct {
rbnode *root, *nil;
} rbtree;

...

ho capito bene o male il funzionamento di un albero rosso-nero, ma non mi è chiaro questo passaggio:

typedef struct {
rbnode *root, *nil;
} rbtree;

praticamente questa è la dichiarazione dell'albero (vuoto ovviamente) con il puntatore alla radice e al nodo nil, che è puntato da tutte i figli delle foglie e dal puntatore padre della radice?

ho dei dubbi anche sull'inizializzazione:

rbtree *createrbtree(void);

...

rbtree *createrbtree(void)
{
rbtree *t = malloc(sizeof(rbtree));

if(!t) {
fprintf(stderr,"Errore di allocazione A\n");
exit(-1);
}
if(!(t->root = malloc(sizeof(rbnode)))) {
fprintf(stderr,"Errore di allocazione B\n");
exit(-2);
}
t->nil = t->root;
t->nil->left = t->nil->right = t->nil->up = t->nil;
t->nil->c = black;
return t;
}

da quello che ho capito t è il puntatore alla radice dell'albero. si fanno dei controlli sullo spazio allocabile (non ho capito bene il secondo controllo.. a cosa serve? non basta il primo?). poi si passa a inizializzare la radice con tutti i campi vuoti no?

grazie!

Sick Boy
14-06-2008, 18:06
ciao,
ho bisogno del vostro aiuto!

ho bisogno di costruire una funzione che mi dica se due strutture rettangolari, rappresentate da 4 campi int (cioè x1,y1, il punto in basso a sinistra e x2,y2 il punto in alto a destra) e da un puntatore a char per il nome, sono o no sovrapposte fra loro.

questo è il codice della struttura rettangolo:

struct rettangolo
{
int x1,y1,x2,y2;
char *nome;
};

typedef struct rettangolo rettangolo;

la funzione dovrebbe prendere in input i due nomi delle strutture e stampa a video un messaggio per dire se sono o no sovrapposte.

avete qualche idea?

grazie

DanieleC88
14-06-2008, 18:31
Ad occhio, direi che ti basta controllare se anche uno solo dei vertici del primo rettangolo è all'interno del secondo (controlla che un punto sia al suo interno con (vX - primo.x1) <= primo.x2 e contemporaneamente (vY - primo.y1) <= primo.y2).

Sick Boy
14-06-2008, 18:34
i tuoi Vx e Vy a cosa corrispondono?
non ho specificato che le coordinate possono anche essere negative

DanieleC88
14-06-2008, 19:03
i tuoi Vx e Vy a cosa corrispondono?
Alle coordinate di un singolo vertice. :)
non ho specificato che le coordinate possono anche essere negative
Dovrebbe funzionare lo stesso, solo avevo sbagliato un po' l'equazione:
int PuntoInterno(int vX, int vY, rettangolo R)
{
int nRight = (R.x2 - R.x1);
int nTop = (R.y2 - R.y1);
int dX = (vX - R.x1);
int dY = (vY - R.y1);

if ((dX >= 0 && dX <= nRight) && (dY >= 0 && dY <= nBottom))
{
return 1;
}
return 0;
}

E poi si tratta solo di fare una catena di Or per ogni vertice... ;)

Sick Boy
15-06-2008, 18:11
scusa se abuso della tua pazienza, ma non ho capito alcune cose:

da quel che ho capito dX e dY sono le distanze del mio punto dal rettangolo considerato (ma vedo solo x1 e y1, basta solo un punto?). perchè deve essere maggiore o alpiù uguale a zero?

poi, sinceramente, non mi è chiaro il funzionamento dell'if, anche perchè c'è un nbottom che non è mai presente prima!