从stdin划分数字和字符串

时间:2013-07-21 12:27:47

标签: c

我想知道是否可以从标准输入中划分数字和字符。 在我的情况下,我知道文本将不是固定大小。

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

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

我该如何处理?

2 个答案:

答案 0 :(得分: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()个别令牌来检查您是否有“写入”或“注册”等等,然后将最后一个转换为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);
}

答案 1 :(得分:0)

基本上,您有一组命令,READWRITERESET等,您的程序必须识别并执行某些操作。

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

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

#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);并将buf传递给strtol而不是scanf("%x", &val),以便将十六进制数字从字符串转换为long。