1

我想知道是否可以从标准输入中区分数字和字符。就我而言,我知道文本将不是固定大小的。

例如,我想从键盘读取READ REGISTER A(使用),通过 switch 语句选择我指的是什么情况。但问题是,当我写入时,我必须将字符串写入寄存器并将值(0x002)写入寄存器。我不能,因为价值不固定。我提供的输入有时具有其他格式(例如 INITIALIZE、RESET 等)。gets() fgets()strcmpWRITE REGISTER A 0x002strcmpWRITE REGISTER Astrcmp

我知道sscanf我可以提取参数(十六进制),但我做不到strcmp

我该如何处理?

4

2 回答 2

3

scanf()我建议不惜一切代价避免,并使用strtok()或类似:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXSIZE 1000

int main(void) {
    char buffer[MAXSIZE];
    char * token;
    int n = 1;

    puts("Enter your command:");
    if ( fgets(buffer, MAXSIZE, stdin) == NULL ) {
        fputs("Error getting input", stderr);
        return EXIT_FAILURE;
    }

    token = strtok(buffer, " ");
    while ( token ) {
        printf("Token %d is %s\n", n++, token);
        token = strtok(NULL, " ");
    }

    return EXIT_SUCCESS;
}

显然,您需要以某种方式处理各个令牌,或者将它们存储起来以供以后处理。您可以strcmp()使用各个令牌来检查您是否有“WRITE”或“REGISTER”或其他任何东西,然后将最后一个令牌转换为带有strtol().

这是一个完整的工作示例,简单的从左到右解析通常不合适,但它会展示一种工作技术(编辑:添加了一些更好的错误处理):

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXSIZE 1000

static long register_a = 0;
static long register_b = 0;
static const char * token_delims = " \r\n\t";

static void inst_write(void);
static void inst_write_register(void);
static void inst_write_register_n(long * p_register);
static void error_quit(const char * msg);

int main(void) {
    char buffer[MAXSIZE];
    char * token;

    /* Get input */

    puts("Enter your command:");
    if ( fgets(buffer, MAXSIZE, stdin) == NULL ) {
        error_quit("couldn't get input");
    }

    /* Tokenize and parse first token */

    token = strtok(buffer, token_delims);
    if ( token == NULL ) {
        error_quit("no instruction specified");
    }
    else if ( strcmp(token, "WRITE") == 0 ) {
        inst_write();
    }
    else if ( strcmp(token, "READ") == 0 ) {

        /* Check for other instructions like this */
    }
    else {
        error_quit("unrecognized instruction");
    }

    /* Output register contents */

    printf("Register A contains: %ld\n", register_a);
    printf("Register B contains: %ld\n", register_b);

    return EXIT_SUCCESS;
}

/* Processes a WRITE instruction */

void inst_write(void) {
    char * token = strtok(NULL, token_delims);

    if ( token == NULL ) {
        error_quit("missing WRITE operand");
    }
    else if ( strcmp(token, "REGISTER") == 0 ) {
        inst_write_register();
    }
    else if ( strcmp(token, "MEMLOC") == 0 ) {

        /* Check for other things to which to write */

    }
    else {
        error_quit("unrecognized WRITE operand");
    }
}

/* Processes a WRITE REGISTER instruction */

void inst_write_register(void) {
    char * token = strtok(NULL, token_delims);

    if ( token == NULL ) {
        error_quit("missing WRITE REGISTER operand");
    }
    else if ( strcmp(token, "A") == 0 ) {
        inst_write_register_n(&register_a);
    }
    else if ( strcmp(token, "B") == 0 ) {

        /* Check for other registers to which to write */

        inst_write_register_n(&register_b);
    }
    else {
        error_quit("unrecognized register");
    }
}

/* Processes the operand of a WRITE REGISTER [X] instruction, and
 * stores it in the appropriate register.
 *
 * Arguments:
 *   p_register -- pointer to the register in which to store
 */

void inst_write_register_n(long * p_register) {
    char * token = strtok(NULL, token_delims);

    if ( token == NULL ) {
        error_quit("missing WRITE REGISTER [X] operand");
    }
    else {
        char * endptr;
        long n = strtol(token, &endptr, 16);

        if ( endptr == token ) {
            error_quit("WRITE REGISTER [X] operand should be a hex integer");
        }
        else {
            *p_register = n;
        }
    }
}

/* General error handler, prints the supplied message and exit()s */

void error_quit(const char * msg) {
    fprintf(stderr, "Error: %s\n", msg);
    exit(EXIT_FAILURE);
}
于 2013-07-21T14:20:49.493 回答
0

基本上,您有一组命令、、READ等,您的程序必须识别这些命令并相应地执行一些操作。WRITERESET

您需要通过逐一读取其每个部分并根据用户输入执行命令来解析输入。

这是执行此操作的基本设置:

#include<stdio.h> 
#include<stdlib.h> 
#include<string.h> 


void clear_stdin()
{
    int c;
    while((c = fgetc(stdin)) != '\n' && c != EOF)
        ;
}

int main(int argc, char** argv)  
{ 
    char buf[64];
    char reg[10];
    unsigned int val = 0;
    int r = 0;

    do{
        printf("\nEnter a command: ");
        scanf("%s", buf);
        if(strcmp(buf, "WRITE") == 0) {
            scanf("%s", buf); // read away "REGISTER"
            scanf("%s", reg); // read name of REGISTER
            r = scanf("%x", &val);
            if(r == 1) {
                printf("write %i to register %s\n", val, reg);
            } else {
                scanf("%s", buf);
                printf("input is not valid: %s\n", buf);
            }
        } else if(strcmp(buf, "READ") == 0) {
            // TODO
        } else if(strcmp(buf, "RESET") == 0) {
            // TODO
        } else if(strcmp(buf, "exit") == 0) {
            break;
        } else {
            printf("Unknown command: %s\n", buf);
        }
        clear_stdin();
    } while(1);

    printf("Bye!\n");

    return 0;  
} 

样本输入

WRITE REGISTER A 0xFF

输出

write 255 to register A

您可以使用scanf("%s", buf);并传递bufstrtol而不是scanf("%x", &val)将十六进制数从字符串转换为长整数。

于 2013-07-21T14:03:36.547 回答