【问题标题】:program won't stop to scanf程序不会停止 scanf
【发布时间】:2017-03-11 21:17:22
【问题描述】:

这是我的名为 test1 的输入文件:

00 READ 9
01 READ 10
02 LOAD 9
03 SUB 10
04 BRNG 7
05 WRIT 9
06 HALT 99
07 WRIT 10
08 HALT 99
09 SET 0
10 SET 0

这些命令应该从用户那里读取两个值并输出两者中较大的一个。

我在unix上使用命令编译:

gcc -Wall -ansi -pedantic -std=c99 computer.c

程序编译得很好。

我使用命令运行它:

./a.out

这是我名为computer.h的头文件:

int dataDump (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand);
int compile (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand);
int execute (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand);

这是我的名为computer.c的源代码文件:

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include "computer.h"

int main ()

{
    int memory [100] = {0};
    int accumulator = 0;
    int instructionCounter = 0;
    int instructionRegister = 0;
    int operationCode = 0;
    int operand = 0;

    compile(memory, &accumulator, &instructionCounter, &instructionRegister, &operationCode, &operand);
    execute(memory, &accumulator, &instructionCounter, &instructionRegister, &operationCode, &operand);

    return 0;
}

//This function works correctly
int compile (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand)
{
    char word[4];

    while ((*operationCode = scanf("%d %s %d", accumulator, word, operand)) > 0)
    {
        if (strncmp("SET", word, 4) != 0 && *operand > 99)
        {
            printf("ERROR Word overflow");
            exit(1);
        }

        if (strncmp("SET", word, 4) == 0 && *operand > 9999)
        {
            printf("ERROR Word overflow");
            exit(1);
        }

        if (strncmp("READ", word, 4) == 0)
            memory[*accumulator] = 1000 + *operand;
        else if (strncmp("WRIT", word, 4) == 0)
            memory[*accumulator] = 1100 + *operand;
        else if (strncmp("PRNT", word, 4) == 0)
            memory[*accumulator] = 1200 + *operand;
        else if (strncmp("LOAD", word, 4) == 0)
            memory[*accumulator] = 2000 + *operand;
        else if (strncmp("STOR", word, 4) == 0)
            memory[*accumulator] = 2100 + *operand;
        else if (strncmp("SET", word, 3) == 0)
            memory[*accumulator] = *operand;
        else if (strncmp("ADD", word, 3) == 0)
            memory[*accumulator] = 3000 + *operand;
        else if (strncmp("SUB", word, 3) == 0)
            memory[*accumulator] = 3100 + *operand;
        else if (strncmp("DIV", word, 3) == 0)
            memory[*accumulator] = 3200 + *operand;
        else if (strncmp("MULT", word, 4) == 0)
            memory[*accumulator] = 3300 + *operand;
        else if (strncmp("MOD", word, 3) == 0)
            memory[*accumulator] = 3400 + *operand;
        else if (strncmp("BRAN", word, 4) == 0)
            memory[*accumulator] = 4000 + *operand;
        else if (strncmp("BRNG", word, 4) == 0)
            memory[*accumulator] = 4100 + *operand;
        else if (strncmp("BRZR", word, 4) == 0)
            memory[*accumulator] = 4200 + *operand;
        else if (strncmp("HALT", word, 4) == 0)
        {
            memory[*accumulator] = 9900 + *operand;
            *instructionCounter = 1;
        }
        // add HALT error and word not found error
    }

    if (*operationCode == 0)
    {
        printf("ERROR Undefined use");
        exit(1);
    }

    if (*instructionCounter == 0)
    {
        printf("ERROR No HALT");
        exit(1);
    }

    return 0;
}

// the bug is in this function
int execute (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand)
{
    *accumulator = 0;
    *instructionCounter = 0;
    *instructionRegister = 0;
    *operationCode = 0;
    *operand = 0;

    for (*instructionCounter = 0; *instructionCounter < 100; *instructionCounter += 1)
    {
        *instructionRegister = memory[*instructionCounter];
        *operationCode = *instructionRegister / 100;
        *operand = *instructionRegister % 100;

        switch (*operationCode)
        {
            case 10:
                //printf("got here");
                scanf("%d", &memory[*operand]); // won't stop to scan in input here
                // I even tried putting a space before the %d and it still won't work
                // I also tried fflush(stdin) before scanf and it still wouldn't stop
                break;

            case 11:
                printf("%d", memory[*operand]);
                break;

            case 12:
                while (memory[*operand] != 0)
                {
                    if (memory[*operand] / 100 == 10 || (memory[*operand] / 100 >= 65 && memory[*operand] / 100 <= 90))
                    {
                        printf("%c",  memory[*operand] / 100);
                    }
                    else
                    {
                        printf("ERROR Unknown Character");
                        exit(1);
                    }

                    if (memory[*operand] % 100 == 10 || (memory[*operand] % 100 >= 65 && memory[*operand] % 100 <= 90))
                    {
                        printf("%c",  memory[*operand] % 100);
                    }
                    else if (memory[*operand] % 100 == 0)
                    {
                        break;
                    }
                    else
                    {
                        printf("ERROR Unknown Character");
                        exit(1);
                    }

                    *operand += 1;
                }

                break;

            case 20:
                *accumulator = memory[*operand];
                break;

            case 21:
                memory[*operand] = *accumulator;
                break;

            case 30:
                *accumulator += memory[*operand];
                break;

            case 31:
                *accumulator -= memory[*operand];
                break;

            case 32:
                if (memory[*operand] != 0)
                {
                    *accumulator /= memory[*operand];
                }
                else
                {
                    printf("ERROR Divide 0");
                }

                break;

            case 33:
                *accumulator *= memory[*operand];
                break;

            case 34:
                if (memory[*operand] != 0)
                {
                    *accumulator %= memory[*operand];
                }
                else
                {
                    printf("ERROR Divide 0");
                }

                break;

            case 40:
                *instructionCounter = memory[*operand] - 1;
                break;

            case 41:
                if (*accumulator < 0)
                {
                    *instructionCounter = memory[*operand] - 1;
                }

                break;

            case 42:
                if (*accumulator == 0)
                {
                    *instructionCounter = memory[*operand] - 1;
                }

                break;

            case 99:
                dataDump(memory, accumulator, instructionCounter, instructionRegister, operationCode, operand);
                return 0;
                break;

            default:
                printf("ERROR Unknown command");
                exit(1);
                break;
        }
    }

    return 0;
}

//This function works correctly
int dataDump (int memory [], int* accumulator, int* instructionCounter, int* instructionRegister, int* operationCode, int* operand)
{
    printf("\nREGISTERS:\n");
    printf("%-25s%+05d\n", "accumulator", *accumulator);
    printf("%-28s%02d\n","instructionCounter", *instructionCounter);
    printf("%-25s%+05d\n","instructionRegister", *instructionRegister);
    printf("%-28s%02d\n","operationCode", *operationCode);
    printf("%-28s%02d\n", "operand", *operand);
    printf("MEMORY:\n   ");

    for(*accumulator = 0; *accumulator <= 9; *accumulator += 1)
    {
        printf("%5d ", *accumulator);
    }

    for(*accumulator = 0; *accumulator < 100; *accumulator += 1)
    {
        if(*accumulator % 10 == 0)
            printf("\n%2d ", *accumulator);

        printf("%+05d ", memory[*accumulator]);
    }

    printf("\n");

    return 0;
}

这是输出:

0
REGISTERS:
accumulator              +0000
instructionCounter          06
instructionRegister      +9999
operationCode               99 
operand                     99
MEMORY:
       0     1     2     3     4     5     6     7     8     9
 0 +1009 +1010 +2009 +3110 +4107 +1109 +9999 +1110 +9999 +0000
10 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
20 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
30 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
40 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
50 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
60 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
70 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
80 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000
90 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000 +0000

【问题讨论】:

  • 您从文件test1 重定向了标准输入,compile 一直读取到 EOF。因此,当execute 调用scanf 时,仍然没有任何内容可供阅读。您可能希望将程序解释为命令行参数而不是标准输入。

标签: c scanf


【解决方案1】:

如果我理解正确,compile() 应该从文件中读取“程序”,execute() 应该运行该程序。而您面临的问题是execute() 应该从用户那里获得输入,但scanf 不要求输入。

如果是这种情况,那么您观察到的行为是预期的。您正在使用输入重定向 (./a.out &lt; test1) 从文件中获取数据,因此,当您希望 scanf 获取用户输入时,它会再次尝试从文件中读取并要求用户不输入。检查是否是这种情况,您可以在scanf 之后立即printf 并查看读取的内容。

要解决这个问题,不要使用输入重定向来读取文件,而应该使用文件访问(fopen()fclose()fscanf()fprintf() 等...)。将文件名作为命令行参数 (./a.out test1) 传递,然后使用 argv[] 检索它。从文件中读取您需要的内容。一旦用户需要输入数据,请使用scanf(),它现在可以从控制台正确读取。

【讨论】:

    猜你喜欢
    • 2016-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    相关资源
    最近更新 更多