【问题标题】:scanf's return values and validation of inputsscanf 的返回值和输入验证
【发布时间】:2013-06-03 16:26:52
【问题描述】:

输入应该是整数字整数格式,中间有空格。我已经编写了下面的代码,据我所知它有效。我现在正在处理代码的错误检查部分。

如果输入的格式不正确,我将如何检查它?

我需要检查的三种错误类型具有以下输入格式:“WORD 99”、“10WORD 33”和“10 WORD”。

提供更多细节。输入的形式为 10 READ 10。第一个整数 10 是输入的其余部分将存储的内存地址。在这种情况下,单词或 READ 是指令。 convertOpCode 函数将单词中的字母与已知指令进行匹配,并将指令代码保存到操作码寄存器中,即*operationCode。第二个整数是操作使用的地址。读取会将用户输入存储到第二个整数的地址位置。

现在 convertoOpCode 函数丢弃第一个空格并读取下一个字符,直到它读取一个空格。如果空格之间的字符与已知操作匹配,则保存相应的操作代码并返回,如果未找到已知操作,则抛出错误并退出程序。

同样,我仅限于显示的变量。我有 int 数组“内存”来存储编译结果和显示的 5 个 int 变量。我无法创建任何其他数组或缓冲区。

int compile( int memory[], int *accumulator, int *instructionCounter, 
    int *instructionRegister, int *operationCode, int *operand ){

while( scanf( "%d", accumulator) == 1 ){

    *instructionRegister = convertOpCode( instructionCounter, instructionRegister, operationCode, operand );
    if( *instructionRegister == 0 ){
        ERRORUC( accumulator );
    scanf( "%d", operand );
    if( *operationCode != 22 ){
        if( *operand > 99 ){
            ERROROPERAND( accumulator );
        memory[ *accumulator ] = ( ( *operationCode ) * 100 ) + ( *operand ); 
    }
    else{
        if( *operand > 9999 ){
            ERRORSET( accumulator );
        }
        memory[ *accumulator ] = *operand;
    }
}
checkHalt( memory, instructionCounter, accumulator );
print( memory );
return 0;

}

这里要求的是 convertOpCode 函数的外观。

int convertOpCode( int *reg1, int* reg2, int* opCode, int* reg3 ){

    getchar();
    *reg1 = (int)getchar();
    *reg2 = (int)getchar();
    *reg3 = (int)getchar();
    *opCode = (int)getchar();

    switch( *reg1 ){
        case (int)'R':
            if( *reg2 == (int)'E' && *reg3 == (int)'A' && *opCode == (int)'D' ){
                *reg1 = (int)getchar();
                if( *reg1 == (int)' ' ){
                    *opCode = READ;
                    return 1;
                }else{
                    return 0;
                }
            }else{
               return 0;
            }
        case (int)'W'.....

}

【问题讨论】:

  • WORD 9910WORD 3310 WORD的含义是什么,预期的输入是什么,--函数convertOpCode()转换是什么?
  • 由于对我们设置的限制,我在整个程序中只能使用 5 个整数。 @rubberboots 希望我在对问题的新编辑中更好地解释它。
  • 为什么不一次获取所有值呢?像 chux 建议的那样使用 fgets 然后“sscanf(buffer, "%s %s %s", one, two, three );"。然后您可以使用诸如“isalpha()”之类的东西和 sscanf 的返回值来决定如何处理扫描的元素。此外,将程序的输入视为数组的索引对我来说似乎非常不安全——尤其是没有边界测试。
  • @n0741337 由于无法创建缓冲区,因此无法一次全部读取。我有 5 个可以使用的整数变量,仅此而已。这就是我读入地址值并将其存储在累加器中的原因。然后我使用剩下的 4 个变量将单词作为整数读取并将其转换为正确的代码。一旦完成,我就可以重用未使用的变量来分配操作数并将所有内容存储在内存数组中。对于这个任务,我们假设索引值是正确的,所以我不需要检查边界。
  • @user1362058 - 我发表评论后看到了您的扩展要求。你能告诉我们 convertOpCode() 函数吗?如果您只有 5 个整数可以使用,那么您可能不需要 convertOpCode() 使用其中的 4 个。例如,“R”和“W”是否足以唯一标识输入中的操作?

标签: c validation scanf


【解决方案1】:

我想我不会滥用其他整数来读取操作码的字符。我不完全清楚任务的要求,但我过去教过 C,如果没有其他方法,我不会提出这样的要求(你的老板可能会有所不同:-))。

我认为您可以在阅读字符时对其进行解析,构建一个类似于允许单词树的案例结构。可以说(例如简单地说)您有说明 询问 MUL SUB

int getopcode()
{
    if (getchar()==' ') {  // ok, starting with space

        switch (getchar()) { 

            case 'A': // probably A(DD) but make sure ...
                if (getchar()=='D' && getchar()=='D') {
                    return 1; // opcode for ADD
                }
                break;


            case 'M': // probably M(UL) but make sure ...
                if (getchar()=='U' && getchar()=='L') {
                    return 2; // opcode for MUL
                }
                break;

            ....
        }
    }

    return 0;  // error if we arrive here. 
}

如果您有以相同字母开头的操作(ADD 和 ASK),则需要在“A”开关内堆叠第二个开关,以根据第二个字母进行操作。

对于主程序,我只是重新勾画了一下,以便进行更多错误检查(不确定您的某些宏,例如 ERRORUC,但我相信您会明白的):

while( scanf( "%d", accumulator) == 1 ){

    *instructionRegister = getopcode();
    if (*instructionRegister!=0) {

        if (scanf(" %d", operand )==1) {  // ok, one more decimal operand

            switch (*operationCode) {   // operand error checking per opcode

                case 22: 
                        if( *operand> 99 )
                            ERROROPERAND(accumulator);
                         break;

                default:
                        if( *operand > 9999 )
                            ERRORSET(accumulator);
                        break;
            }
        }
        else {
            // error reading 2nd operand
            ERRORUC( accumulator );
        }

    }
    else {
        // error in opcode
        ERRORUC( accumulator );
    }


    if ( no error set in accumulator, i.e. no ERRORxx macro called) {
         // accumulator, instructionRegister and operand are ok here
         // write to memory
    }
    else 
        break; // break the loop, end compiling
}

print( memory );
return 0;

需要做一些事情来根据错误打破循环或最初不使其成为循环。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-21
    • 2021-01-23
    • 1970-01-01
    • 2016-07-10
    • 2013-02-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多