Here is an example of how you might write your code with better structure and naming. I've only written the first part, reading in the transition table. I'm not saying it's perfect, but I hope you agree that it is much more readable.
Note that this code makes the mistake that Salem pointed out in the use of realloc (saving the return value to the same pointer used as input). However, since it exits if the return value is NULL, it doesn't matter in this case as the OS will clean everything up. In general you should do as Salem has described.
It also takes advantage of realloc acting like malloc if the input pointer (first parameter) is NULL.
BTW, what language is "letto" and what does it mean? Google translate says it's Italian and means "bed"!
Code:
#include <stdio.h>
#include <stdlib.h>
#define LOW_CHAR '0'
#define HIGH_CHAR 'z'
#define NUM_CHARS (HIGH_CHAR - LOW_CHAR + 1)
typedef struct Instruction Instruction;
struct Instruction {
Instruction *next;
char outSym;
char direction;
int newState;
};
typedef struct Instruction ***Table;
Table read_transition_table(int *numStates);
Table extend_table(Table table, int state, int *numStates);
Instruction **new_table_row();
Instruction *new_instruction(char outSym, char direction, int newState);
void print_transition_table(Table table, int numStates);
void free_transition_table(Table table, int numStates);
void skip_line();
int main() {
int numStates = 0;
skip_line();
Table table = read_transition_table(&numStates);
print_transition_table(table, numStates);
free_transition_table(table, numStates);
return 0;
}
void skip_line() {
for (char ch; (ch = getchar()) != \n' && ch != EOF) ;
}
Table read_transition_table(int *numStates) {
*numStates = 0;
Table table = NULL;
int state, newState;
char inSym, outSym, direction;
while (scanf("%d %c %c %c %d", &state, &inSym, &outSym, &direction,
&newState) == 5) {
if (state >= *numStates) table = extend_table(table, state, numStates);
if (!table[state]) table[state] = new_table_row();
Instruction *inst = new_instruction(outSym, direction, newState);
inst->next = table[state][inSym - LOW_CHAR];
table[state][inSym - LOW_CHAR] = inst;
}
return table;
}
Table extend_table(Table table, int state, int *numStates) {
table = realloc(table, (state + 1) * sizeof *table);
if (!table) {
perror("extend_table");
exit(EXIT_FAILURE);
}
while (*numStates <= state)
table[(*numStates)++] = NULL;
return table;
}
Instruction **new_table_row() {
Instruction **tableRow = malloc(NUM_CHARS * sizeof *tableRow);
if (!tableRow) {
perror("new_table_row");
exit(EXIT_FAILURE);
}
for (int i = 0; i < NUM_CHARS; i++)
tableRow[i] = NULL;
return tableRow;
}
Instruction *new_instruction(char outSym, char direction, int newState) {
Instruction *inst = malloc(sizeof *inst);
if (!inst) {
perror("new_instruction");
exit(EXIT_FAILURE);
}
inst->outSym = outSym;
inst->direction = direction;
inst->newState = newState;
inst->next = NULL;
return inst;
}
void print_transition_table(Table table, int numStates) {
for (int row = 0; row < numStates; ++row)
if (table[row])
for (int col = 0; col < NUM_CHARS; ++col)
for (Instruction *p = table[row][col]; p; p = p->next)
printf("%d %c %c %c %d\n", row, col + LOW_CHAR,
p->outSym, p->direction, p->newState);
}
void free_transition_table(Table table, int numStates) {
for (int row = 0; row < numStates; ++row)
if (table[row]) {
for (int col = 0; col < NUM_CHARS; ++col)
for (Instruction *p = table[row][col]; p; ) {
Instruction *next = p->next;
free(p);
p = next;
}
free(table[row]);
}
free(table);
}