[英]Unknown length and multiple requirements for input
我正在使用一种名为Objective的结构,该结构包含一个最多8000个字符的char名称(大多数情况下会更短),一个int id,一个int持续时间以及一个称为deps的int数组,在0到9000个元素之间。 这里是:
typedef struct {
unsigned long id, duration, dep [9000];
char name [MAXNAME];
}Objective
我有一些与此结构一起使用的功能,我可以添加,删除,打印等。我需要使用终端指定我要执行的操作,例如添加目标,我需要在终端上编写“添加ID“名称”持续时间deps”。 所以这就是我的问题的开始,以目标的名义,它必须在“”之间,否则命令无效。 我在使用deps数组时也遇到了麻烦,它可以有0到9000个元素,所以我永远不知道有多少个元素,我必须将它们放入将成为目标deps的数组中。 我也不能在参数之间放置两个空格。 输入行的一些示例:
“添加1个“ objective1” 20 2 3 4 5“-这将添加一个ID为1,名称为“ objective1”,持续时间为20并分别为2、3、4和5的目标
“添加1个Objective1 20 2 3 4 5”-无效,因为名称不在“”之间
“ add 1” objective1“ 20”-这将添加一个ID为1,名称为“ objective1”,持续时间为20并且没有deps的目标
“删除1”-删除ID为1的目标
我从以前使用fgets的工作中得到了这一点:
char input[82], col [6], na [80]; unsigned long a, b;
double c;
while(input[0] != 'q'){
if(fgets(input, sizeof(input), stdin)){
if(input[0] == 'p' && input[1] == '\n' && input[2] == '\0'){
list(matrix);
}
else if(input[0] == 'i' && input[1] == '\n' && input[2] == '\0'){
carac(matrix);
}
else if((sscanf(input, "%c %lu %lu %lf\n", &input[0],
&a, &b ,&c) == 4)){
adds(a, b, c, matrix);
}
else if(input[0] == 'l' && (sscanf(input, "%*c %lu\n", &a) == 1)){
printLine(a , matrix);
}
else if(input[0] == 'c' && (sscanf(input, "%*c %lu\n", &a) == 1)){
printColumn(a , matrix);
}
else if(input[0] == 'z' && (sscanf(input, "%*c %lf\n", &c) == 1)){
zero(c , matrix);
}
else if(input[0] == 'o' && input[1] == '\n' && input[2] == '\0'){
sortLine(matrix);
}
else if(input[0] == 'o' && (sscanf(input, "%*c %s\n", col) == 1) && strcmp(col, "column") == 0){
sortColumn(matrix);
}
else if(input[0] == 'w' && input[1] == '\n' && input[2] == '\0'){
file(matrix);
}
else if(input[0] == 'w' && (sscanf(input, "%*c %s\n", na) == 1) ){
newFile(na, matrix);
}
}
}
但是在这种情况下,它必须有很大的不同,“”之间的名称,未知数量的deps元素以及参数之间的空格使这对我来说真的很难,是否有人对我如何做到或如何解决提出建议?我上面列出的问题之一?
首先,关于用户输入的注释:我同意@ryyker,请尝试提出一种易于解析的用户输入格式。 从一开始就试图使输入变得太灵活会妨碍您,而您应该专注于程序的逻辑。 但是也许您不是选择格式的人,所以继续前进...
您选择定义结构并使用fgets()不错。 但是,您将所有内容放在一个while()构造中,这无助于组织代码。 我不会为您提供完整的代码,而只会提供有关如何组织代码的指针。
我建议您分开:
第1部分: scanf()不好,因为您不知道行的长度。 在相当长的缓冲区上继续使用fget,例如:
char buf[1024];
// ...
/* Maybe you'll want to use something else than fgets()
* later on. Encapsulate "reading from user" in a function. */
void read_user_input(char **buf, int size) {
*buf = fgets(*buf, size, stdin);
}
第2部分和第3部分:编写小函数以从缓冲区中提取标记,并检查例如每个标记之间是否用单个空格分隔,或者检查用户是否在“名称”周围使用了引号。
/* Return the index of the first character of the next token
* in a string. Start searching from "idx".
* Tokens are separated by spaces. */
int next_token(char *buf, int idx, const int size) {
while (idx < size && is_whitespace(buf[idx])) {
++idx;
}
if (idx == size) {
return -1; // no token here
}
else {
return idx;
}
}
// ...
int check_spacing(char *buf, int size) {
/* Extract tokens, maybe fill struct Objective along
* the way. */
int idx = 0;
while (idx < size) {
int next_token_idx = next_token(buf, idx, size);
if (next_token_idx - idx > 1) {
// More than 1 space, not good!
}
}
}
第4部分:您已经完成了工作:adds(),printLine(),printColumn()...
一旦切入了简洁的小函数,编写主循环就会容易得多:
main(int argc, char *argv[]) {
const int size = 1024;
char buf[size];
Objective obj = null;
// Read as long as the line is not finished.
do {
read_user_input(buf, size);
// Check that tokens are valid
// Build a struct Objective along the way
// obj = ... ;
// Also fetch the command: "add", "remove"...
} while (! contains_newline(buf));
// Now that you're confident user input is OK,
// you can execute command happily
if (strcmp(command, "add") == 0) {
// Add an objective
}
else if (strcmp(command, "remove") {
// Remove an objective
}
else if (strcmp(command, "i") {
carac(matrix);
}
// etc.
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.