我想知道是否可以从标准输入中划分数字和字符。 在我的情况下,我知道文本将不是固定大小。
例如,我想从键盘READ REGISTER A
(使用 gets()
fgets()
)读取,strcmp
通过switch语句进行选择我指的是什么情况。
但问题是,当我写WRITE REGISTER A 0x002
时,我必须strcmp
字符串WRITE REGISTER A
和
写入寄存器的值(0x002)。我不能strcmp
因为价值不固定。
我提供的输入有时会有其他格式(例如INITIALIZE,RESET等)。
我知道使用sscanf
我可以提取参数(十六进制),但我不能strcmp
。
我该如何处理?
答案 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(®ister_a);
}
else if ( strcmp(token, "B") == 0 ) {
/* Check for other registers to which to write */
inst_write_register_n(®ister_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)
基本上,您有一组命令,READ
,WRITE
,RESET
等,您的程序必须识别并执行某些操作。
您需要通过逐个读取每个部分来解析输入,并根据用户输入执行命令。
以下是执行此操作的基本设置:
#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。