功能无法正确读取标准输入

时间:2016-08-07 09:57:53

标签: c function computer-science stdin

所以我一直在尝试编写一个从stdin读取数据的虚拟计算机程序。 stdin继续以(%d %s %d)的形式出现,数据基本上代表一个具有特定任务的程序,如下所示:

01 READ 60
02 LOAD 60
03 SUB 61
04 STOR 60
05 BRNG 15
06 READ 70
07 LOAD 70
08 ADD 80
09 STOR 80
10 LOAD 60
11 SUB 61
12 STOR 60
13 BRNG 15
14 BRAN 6
15 WRIT 80
16 HALT 99
61 SET 1
80 SET 0

有一个函数可以作为编译器工作,并且应该逐行读取这些数据,但出于某种原因,无论何时运行此函数,我都会“不正确的格式程序现在将退出”。我一直试图弄清楚为什么它现在已经做了一段时间而没有任何线索。

程序逐行读入stdin流,当没有stdin时它应该停止,它应该检查格式是否正确,它确实是正确的格式,为什么它没有正确读取?我个人的猜测是,由于某些原因,它不是逐行阅读,但我不确定是不是这样!

PS:我第一次使用这个程序时使用的是文件指针,它工作得很好,但当我将流切换到stdin时,它开始给出不正确的格式错误!

int compile ( int memory [], int* instructionCounter , int* instructionRegister ,int*operationCode ,int* operand){
    char s[80]; /* The buffer */
    *instructionRegister=0;
    *operationCode=0;
    while(((*instructionRegister)=scanf("%d %s %d", operationCode,s,operand)) != NULL){ /*Reads data line by line then stores the integer returned by fscanf to instructionRegister pointer so that I can check for formating */
       if((*instructionRegister) ==3 ){ /*Checks for improper format by comparing the current instructionRegister count to 3, returns improper format otherwise */
            if(*operand >9999|| *operand <0){  /* Checks for word overflow in compiler, makes sure that digits do not exceed 9999 */
                printf("attempts to place a word in memory that is larger than 4 digits, or attempted to pass in a negative value\n ");
                exit(0);
            }
            /*Compares the string section of the code and checks if it matches the following words and then it converts it to it's 4 digit value by adding into it the operand */
            if(strcmp(s,"READ") == 0) {
                memory[*operationCode] = 10 * 100 + *operand;
            }
            else if(strcmp(s,"WRIT") == 0) {
                memory [*operationCode] = 11 * 100 + *operand;
            }
            else if(strcmp(s,"LOAD") ==0){
                memory [*operationCode] = 20 * 100 + *operand;
            }
            else if(strcmp(s,"PRNT") ==0){
                memory [*operationCode] = 12 * 100 + *operand;
            }
            else if(strcmp(s,"STOR") ==0){
                memory [*operationCode] = 21 * 100 + *operand;
            }
            else if(strcmp(s,"SET") ==0){
                memory [*operationCode] = *operand;
            }
            else if(strcmp(s,"ADD") ==0){
                memory [*operationCode] = 30 * 100 + *operand;
            }
            else if(strcmp(s,"SUB") ==0){
                memory [*operationCode] = 31 * 100 + *operand;
            }
            else if(strcmp(s,"DIV") ==0){
                memory [*operationCode] = 32 * 100 + *operand;
            }
            else if(strcmp(s,"MULT") ==0){
                memory [*operationCode] = 33 * 100 + *operand;
            }
            else if(strcmp(s,"MOD") ==0){
                memory [*operationCode] = 34 * 100 + *operand;
            }
            else if(strcmp(s,"BRAN") ==0){
                memory [*operationCode] = 40 * 100 + *operand;
            }
            else if(strcmp(s,"BRNG") ==0){
                memory [*operationCode] = 41 * 100 + *operand;
            }
            else if(strcmp(s,"BRZR") ==0){
                memory [*operationCode] = 42 * 100 + *operand;;
            }
            else if(strcmp(s,"HALT")==0){
                memory [*operationCode] =9999;
            }

            else {   /* Prints back to the user that the compiler did not recognize one of them commands as it was going through it */
                printf ("This is an unknown command, commands are case sensitive, program will now exit \n");
                exit(0);

            }
        }
        else{    /* Returns improper format if instructionRegister does not match 3*/
            printf("Improper Format, program will now exit \n");
            exit(0);
        }

    }
    /* Checks if the instruction data contains a HALT, if not it would terminate */
    while(*instructionCounter<100){
        if (memory[*instructionCounter] == 9999){
            return 1;
        }
        else
            (*instructionCounter)++;
    }
    printf("Halt was not found, program will now exit");
    exit (0);
}

此功能的目的是逐行读入数据并将其存储在内存虚拟单元中。它应检查这些行的格式为%d %c %d,以便它可以提取数据并将其存储在内存中。

1 个答案:

答案 0 :(得分:0)

你的问题就在这一行:

while(((*instructionRegister)=scanf("%d %s %d", operationCode,s,operand)) != NULL){

scanf()函数返回

  • 成功转化的次数,即0到3之间的任何值,或
  • EOF如果在任何成功转换之前发生输入失败(文件结束或读取错误)。 EOF宏是一些负数,通常为-1

您将返回值与NULL0(或(void *)0或类似)的while进行比较。根据您提供的输入,scanf()循环将继续阅读,直到EOF返回while。这不会突破 if((*instructionRegister) ==3 ){ /* big snip */ else{ printf("Improper Format, program will now exit \n"); exit(0); } 循环,但下一次测试将失败:

EOF

当然,解决方案是将结果与NULL而不是scanf()进行比较。

%s电话中还有潜在的缓冲区溢出。如果字符串长度超过79个字符,scanf()转换说明符将使s[]写入\0缓冲区的末尾。 (别忘了它写一个终止scanf ("%d %79s %d", /*...*/) 。)

您可以通过添加最大字段宽度来限制金额:

"%d"

如果输入字符串超过79个字符,则输入将无法与scanf()修饰符之前的空格匹配,而2将返回<div style={{width: 'calc(100% - 276px)'}}></div> 以指示不完整的结果。