Purtroppo nel tuo codice si sovrappongono numerosi errori sintattici e di progetto.
Cominciamo dagli aspetti più banali. Ecco cosa diventa il tuo codice dopo una passatina in mani esperte:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define MAX_PAROLE 10
#define SIZE_PAROLA 20
void separaFrase (char alfa[], char beta[][SIZE_PAROLA])
{
int i, j, k;
int len;
len = strlen(alfa);
for(i = 0, j = 0, k = 0; i < len; ++i)
{
if (isspace(alfa[i]))
{
strncpy(beta[k], alfa + j, i - j);
++k;
j = i + 1;
}
}
}
int main (void)
{
int i;
char parsed[MAX_PAROLE][SIZE_PAROLA];
char frase[] = "Alle dame del castello piace molto fare quello ";
for (i = 0; i < MAX_PAROLE; ++i)
{
memset(parsed[i], '\0', SIZE_PAROLA * sizeof(char));
}
separaFrase(frase, parsed);
for (i = 0; i < MAX_PAROLE; ++i)
{
if (strlen(parsed[i]))
{
printf("[%s]\n", parsed[i]);
}
}
return (0);
}
Il codice, così modificato, compila senza warning con il mitico BCC 5.5.1 (e quindi con qualsiasi compilatore INCITS C'89 decente).
Inoltre, funziona perfettamente con la semplice frase di test appositamente confezionata.
(1)Tuttavia, quel codice - pur se in qualche modo funzionante - non è assolutamente robusto rispetto all'input.
Giusto per limitarci alle magagne più macroscopiche, il codice così concepito non gestisce sequenze di spazi multipli e/o tabulazioni, e non controlla in alcun modo i boundaries sul buffer-matrice "beta": né sulla singola stringa (nonostante la presenza di strncopy, la differenza tra "i" e "j" cresce incontrollatamente), né sul numero totale di stringhe.
Tali limiti arbitrari possono essere bellamente sorpassati con input appositamente malformati, con tutte le più ovvie conseguenze del caso.
E' infatti sufficiente dare in pasto una banalissima frase del tipo
"Ciao, sono una bella frase di test ma con troppi spazi"
per vedere crollare miseramente la qualità del parsing. Per non parlare dell'overflow, fin troppo facile da provocare.
Le uniche opzioni seriamente spendibili, anche limitatamente all'ambito didattico, sono:
- L'implementazione di un vero automa a stati finiti, che ruoti attorno ai due stati fondamentali "inword" e "blank";
#include <string.h>
#include <stdio.h>
#include <ctype.h>
/*
** Per i nostri scopi, si definisce qui la stringa
** dei separatori: caratteri che delimitano cio' che
** consideriamo "parole"
*/
#define DELIM_STR " \t\n\r"
typedef enum {ST_BLANK, ST_INWORD} Status_t;
int main(void)
{
Status_t FSM_Status = ST_BLANK;
const char input[] = "Alle dame del Castello piace molto fare quello";
char *inizio, *fine;
inizio = input;
fine = inizio;
printf("Input da elaborare: \n[%s]\n\n", input);
while('\0' != *fine)
{
switch (FSM_Status)
{
case ST_INWORD:
if (NULL != strchr(DELIM_STR, *fine))
{
char c;
FSM_Status = ST_BLANK;
c = *fine;
*fine = '\0';
puts(inizio);
*fine = c;
}
break;
case ST_BLANK:
if (NULL == strchr(DELIM_STR, *fine))
{
FSM_Status = ST_INWORD;
inizio = fine;
}
break;
default: break;
}
++fine;
}
if (ST_INWORD == FSM_Status)
{
puts(inizio);
}
return(0);
}
- L'uso della sempreverde
strtok().
#include <string.h>
#include <stdio.h>
#include <ctype.h>
/*
** Per la nostra strtok(), si definisce qui la stringa
** dei separatori: caratteri che delimitano cio' che
** consideriamo "parole"
*/
#define DELIM_STR " \t\n\r"
/*
** Si stabilisce un limite arbitrario per la lunghezza dell'array
** presente nell'esercizio (qui non esplicitato).
** Il limite e' volutamente basso per evidenziarne l'effetto
** nell'esempio.
*/
#define MAX_WORDS 6
/*
** Dimensione statica della singola parola (stringa della matrice),
** sempre in riferimento all'esercizio originale.
*/
#define MAX_WORD_SIZE 16
/*
** Queste macro avanzate di preprocessore consentono l'utilizzo
** della costante MAX_WORD_SIZE entro una stringa di formato
** della printf().
** Ottima occasione per imparare un "trucco" poco noto e molto utile.
**
** In alternativa, si può assegnare il valore definito tramite
** detta macro MAX_WORD_SIZE ad una variabile qualificata come segue:
**
** const unsigned int MaxWordSize = MAX_WORD_SIZE;
**
** Usando poi tale variabile nei modi più consueti entro la printf().
*/
#ifdef ADVANCED_PREPROC
#define str(x) # x
#define xstr(x) str(x)
#endif
int main(void)
{
char input[] = "supercalifragilistic-espiralidoso: "
"Alle dame del Castello piace molto fare quello";
char *p;
int len;
int i = 0;
/* Vedi commenti a str() e xstr() tra le defines soprastanti */
#ifndef ADVANCED_PREPROC
const unsigned int MaxWordSize = MAX_WORD_SIZE;
#endif
p = strtok(input, DELIM_STR);
while (NULL != p)
{
len = strlen(p);
#ifdef ADVANCED_PREPROC
printf("%2d) [%-" xstr(MAX_WORD_SIZE)
"s] size = %d ** %s **\n",
++i, p, len,
len < MAX_WORD_SIZE ? "OK" : "TRONCAMENTO");
#else
printf("%2d) [%-*s] size = %d ** %s **\n",
++i, MaxWordSize, p, len,
len < MAX_WORD_SIZE ? "OK" : "TRONCAMENTO");
#endif
p = strtok(NULL, DELIM_STR);
if (MAX_WORDS == i)
{
p = NULL;
puts("\n** Spazio esaurito ! **\n");
}
}
return 0;
}
Ricordo inoltre per l'ennesima volta che nel confronto tra una espressione variabile (potenzialmente un lvalue, ossia assegnabile, ovvero sintatticamente ammessa a sinistra di un operatore di assegnazione) e una costante, è buona norma
anteporre sempre l'espressione costante, come segue:
if (69 == static_pos)
In questo modo, nel caso fin troppo comune di omissione di uno dei due simboli '=', si scarica comunque sul banale controllo sintattico del compilatore la rivelazione di un errore semantico (assegnazione in luogo di confronto), dal momento che l'espressione posta a sinistra è non assegnabile, dunque non può essere un lvalue valido.
(1) Si tratta del titolo ufficiale (ma in circolazione vi sono vari errori, perfino sulle copertine dei DVD ristampati di recente) di uno dei primissimi film della splendida Edwige nazionale: forse il primo in assoluto, relativamente alla circolazione commerciale.
Si tratta di un capolavoro visto da pochissimi intenditori, nel quale peraltro la famosa e formosa attrice, decisamente agli esordi della sua carriera, viene vistosamente doppiata anche nell'originale tedesco. Tuttavia, in questi casi non sta esattamente nei dialoghi la forza icastica del messaggio filmico, l'estasi e il tormento del cineasta...
