Comportamento alieno di un programma scritto in C

di il
11 risposte

Comportamento alieno di un programma scritto in C

Salve a tutti,sono disperato, aiutatemi, cerco di essere sintetico e di spiegarvi il comportamento strano che fa il programma.
Il problema sorge sulla scanf() , in pratica devo mettere uno spazio per la "%c " altrimenti il programma esce.
Allego codice con commento sulla scanf difettosa, dategli anche uno sguardo generale se qualcosa non va.
#include <stdio.h>
#define READNUM 0xa
#define WRITEINT 0xb
#define NEWLINE 0xc
#define WRITEFLOAT 0xd
#define READCHAR 0xe
#define LOAD 0x14
#define STORE 0x15
#define ADD 0x1e
#define SUB 0x1f
#define DIVIDE 0x20
#define MULTIPLY 0x21
#define REST 0x22
#define POWER 0x23
#define JUMP 0x28
#define JUMPNEG 0x29
#define JUMPZERO 0x2a
#define HALT 0x2b
#define SIZE 100

void insert(int[], const int);
void dump(const int[],const int *,const int *,const int *,const int *,const int *, const int);

int main() {
	
		int memory[SIZE] = {0}, accumulator = 0, instructionCounter = 0, operationCode, operand, instructionRegister, i = 1, x, y;
		float f;
		char c;
		
		printf("\n*** Welcome to Simpletron! ***\n\n");
		insert(memory, SIZE);
		
		while(i) {
			instructionRegister = memory[instructionCounter];
			operationCode = instructionRegister / 0x100;
			operand = instructionRegister % 0x100;

			switch(operationCode) {
				case READNUM:
					printf(" ? ");
					scanf("%f", &f);
					while(f <= -10000 || f >= 10000) {
						printf("Valore immesso non corretto, immettere inferiore a +9999 e superiore a -9999\n");
						scanf("%f", &f);
					}
					memory[operand] = f;
					if ((f - memory[operand]) != 0.0) {
						f -= memory[operand];
						memory[operand + 1] = f * 10;
						}							//calcoli imprecisi, da migliorare!!!!!!
					break;
				case WRITEINT:
					printf("\nIl risultato è %d \n\n",memory[operand]);
					break;
				case WRITEFLOAT:
					f = (float) memory[operand] + (memory[operand + 1] * 0.1);
					printf("\nIl risultato è %.2f\n\n", f);
					break;
				case NEWLINE:
					printf("\n");
					break;
				case READCHAR:
					printf(" ? ");
					scanf("%d", &x);
					memory[operand] = x * 100;
					dump(memory,&accumulator,&instructionCounter,&operationCode,&operand,&instructionRegister,SIZE);
					for (; x > 0; x--) {
						printf(" ? ");
						scanf("%c ", &c);            //!!!!!!!!!!comportamento anomalo scanf!!!!!!!!!!!
						y = c;
						if(x % 2 != 0) {
							++operand;
							y *= 100;
						}
						memory[operand] = y;
						dump(memory,&accumulator,&instructionCounter,&operationCode,&operand,&instructionRegister,SIZE);
					}
					break;
				case LOAD:
					accumulator = memory[operand];
					break;
				case STORE:
					memory[operand] = accumulator;
					break;
				case ADD:
					if (accumulator + memory[operand] <= 9999)
						accumulator += memory[operand];
					else {
						printf("Dimensione superata\n");
						i = 0;
					}
					break;
				case SUB:
					if (accumulator - memory[operand] >= -9999)
							accumulator -= memory[operand];
						else {
							printf("Dimensione superata\n");
							i = 0;
						}
					break;
				case DIVIDE:
					if(memory[operand])
						if (accumulator / memory[operand] >= -9999)
							accumulator /= memory[operand];
						else {
							printf("Dimensione superata\n");
							i = 0;
						}
					else {
						printf("Attempt to divide by zero\n");
						i = 0;
					}
					break;
				case MULTIPLY:
					if (accumulator * memory[operand] <= 9999)
						accumulator *= memory[operand];
					else {
						printf("Dimensione superata\n");
						i = 0;
					}
					break;
				case REST:
						if(memory[operand])
						accumulator %= memory[operand];
					else {
						printf("Attempt to divide by zero\n");
						i = 0;
					}
					break;
				case POWER:
					for (; accumulator > 0 ; --accumulator)
						i *= memory[operand];
						if(i >= -9999 && i <= 9999)
							accumulator = i;
						else {
							printf("Dimensione superata");
							i = 0;
							break;
						}
					break;
				case JUMP:
					instructionCounter = operand;
					continue;
				case JUMPNEG:
					if(accumulator < 0) {
						instructionCounter = operand;
						continue;
						}
					break;
				case JUMPZERO:
					if(accumulator == 0) {
						instructionCounter = operand;
						continue;
						}
					break;
				case HALT:
					i = 0;
					break;
				default:
					printf("Codice operazione non valido\n");
					i = 0;
			}
			++instructionCounter;		//istruzione da inserire in ogni case opportuno
		}
		dump(memory,&accumulator,&instructionCounter,&operationCode,&operand,&instructionRegister,SIZE);
		return 0;
}

void insert(int vect[], const int size) {

		int i = 0, x;
		
		printf("Inserisci le istruzioni, usa -10000 per uscire e 10000 per tornare indietro\n\n");
		
		while(i < size) {
			printf("%02d ? ", i);
			scanf("%x", &x);
			if(x == -0x10000) {
				printf("*** Program loading completed ***\n");
				printf("*** Program execution begins  ***\n\n");
				break;
			}
				
			if (x == 0x10000) {
				if( i > 0)
					i--;
				continue;
			}
			while(x < -0xffff || x > 0xffff) {
				printf("Reinserisci altro numero compreso tra -0xffff e +0xffff: ");
				scanf("%x", &x);
			}
			vect[i] = x;
			i++;
		}
}

void dump(const int vect[],const int *accPtr,const int *countPtr,const int *codePtr,const int *operPtr,const int *regPtr, const int size) {
		
		int i;
		
		printf("\nREGISTER:\n");
		printf("accumulator +%04d\n",*accPtr);
		printf("instructionCounter %002d\n",*countPtr);
		printf("instructionRegister +%04x\n",*regPtr);
		printf("operationCode %02x\n",*codePtr);
		printf("operand %02x\n\n",*operPtr);
		printf("MEMORY:\n   ");

		for (i = 0; i < 10; i += 1) {
			printf("%6d", i);
		}
		for (i = 0; i < size; i += 1) {
			if(i % 10 == 0)
				printf("\n%3d ", i);
			printf("+%04d ", vect[i]);
		}
		printf("\n");
}
Spero che qualcuno bravo mi aiuti altrimenti getto la spugna.

11 Risposte

  • Re: Comportamento alieno di un programma scritto in C

    Ti dispiace indicare i valori che dai al programma così da generare il bug? E spiegare meglio il comportamento alieno?
  • Re: Comportamento alieno di un programma scritto in C

    Questo è un programma che simula la macchina simpletron,appena avviato l'ELF do le istruzioni in pseudo linguaggio macchina come segue:
    0e0a
    2b00
    -10000 per uscire dall'inserimento
    la 0e0a corrisponde alla READCHAR e punta alla memory[10] convertito in decimale
    poi in esecuzione
    devo dare per prima cosa il numero di caratteri da inserire, facciamo un esempio 4 e poi immettere 4 caratteri per poi convertirli in decimale "meglio se esadecimale" per inserirli nel vettore memory, solo che se non metto lo spazio "%c" il programma mi fa inserire solo 2 caratteri invece di 4 o addirittura esce, invece se metto lo spazio"%c " mi da l'input di inserire 4 caratteri ma non li memorizza nel vettore memory.
  • Re: Comportamento alieno di un programma scritto in C

    Dimenticati che esiste la scanf ed inizia ad utilizzare la fgets()!!!
  • Re: Comportamento alieno di un programma scritto in C

    Ok!

    Allora il problema sta nel fatto che quando usi la scanf per leggere caratteri anche il carattere \n presente nel buffer è un carattere che legge. Ecco perché riscontri l'anomalia.

    Ti conviene leggere con la fgets mettere in una stringa, sostituire il carattere \n con \0 e leggere con sscanf %c.
  • Re: Comportamento alieno di un programma scritto in C

    Per quel che deve fare può anche non usare la sscanf, a quel punto se è su windows può mettere una fflush(stdin) dopo ogni scanf e amen.
  • Re: Comportamento alieno di un programma scritto in C

    Come sistema uso linux, e come compilatore uso clang 3.5.
    La fgets() in quale libreria la trovo, mi da errore in compilazione con la sola stdio.h
  • Re: Comportamento alieno di un programma scritto in C

    La fgets() è nella libreria libc inclusa automaticamente da tutti i compilatori, il suo prototipo si trova proprio in <stdio.h>
    Che ambiente di sviluppo usi?
    perché clang?
    penso dovresti usare il compilatore giusto sotto gnu/Linux, ovvero GCC.
  • Re: Comportamento alieno di un programma scritto in C

    Uso clang perché ha un ottimo output per gli errori.
    Come devo implementarla nel codice la fgets(), ancora non lo studiata, e da pochi mesi che studio C.
  • Re: Comportamento alieno di un programma scritto in C

    Ma un pessimo livello di ottimizzazione, è un prodotto troppo acerbo per poter pensare di usarlo a livello di studio, dovresti usare le armi consolidate, sicure e ben documentate.
    Su quale libro stai studiando?
    quale ide usi?
    il reference della lo trovi ovunque, soprattutto sui libri di testo.

    Gli si passa un buffer con la sua dimensione e il file dove si vuole leggere e lei ti ritorna nel buffer tutti i caratteri letti fino a '\n' compreso.

    Dato che su GNU/Linux la fflush(stdin) non è implementata puoi farlo tu:
    
    void fflushin(void)
    {
        int c;
        while ( EOF != (c = getchar()) && '\n' != c );
    }
    
    ora richiami fflushin() dopo ogni scanf();
  • Re: Comportamento alieno di un programma scritto in C

    Sto leggendo il libro dei fratelli Deitel, come ide nessuno, uso un semplice editor "gedit 3.16 corredato di plugins" e poi mi compilo i programmi con i soliti cc o clang.
    Ok domani proverò ad implementarlo,comunque ho pensato pure ad un puntatore a stringa con aritmetica dei puntatori, cosa ne dite?
    PS: per il momento grazie a tutti.
  • Re: Comportamento alieno di un programma scritto in C

    Ciao a tutti, comunque ho risolto con una scanf("%s", &c) ho messo stringa al posto di carattere così non mi ha letto più i line feed '\n'.
Devi accedere o registrarti per scrivere nel forum
11 risposte