【问题标题】:Unknown length and multiple requirements for input未知长度和输入的多重要求
【发布时间】:2018-10-28 03:30:46
【问题描述】:

我正在使用一个名为 objective 的结构,它由一个最多 8000 个字符的字符名称(大部分时间会小得多)、一个 int id、一个 int 持续时间和一个称为 deps 的 int 数组组成可以有 0 到 9000 个元素。 这里是:

typedef struct {
unsigned long id, duration, dep [9000];
char name [MAXNAME];
}Objective

我有一些函数可以使用这个结构,我可以添加一个,可以删除,可以打印等。 我需要使用终端来指定我想要做的事情,例如添加一个我需要在终端上写的目标“add id”name“duration deps”。 所以这就是我的问题开始的地方,以目标的名义,它必须在“”之间,否则命令无效。我也遇到了 deps 数组的问题,它可以有 0 到 9000 个元素,所以我永远不知道有多少,我必须将它们放入一个数组中,该数组将成为目标的 deps。我也不能在参数之间放置两个空格。 输入行的一些示例:

"add 1 "objective1" 20 2 3 4 5" - 这会添加一个 id 为 1、名称为 "objective1"、持续时间为 20 和 deps 为 2、3、4 和 5 的目标

"add 1 objective1 20 2 3 4 5" - 这是无效的,因为名称不在“”之间

"add 1 "objective1" 20" - 这会添加一个 id 为 1、名称为 "objective1"、持续时间为 20 且没有依赖关系的目标

"remove 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 元素和参数之间的空格让这对我来说真的很困难,有没有人对我如何做到这一点或如何做到这一点有一些建议我可以解决上面列出的问题之一吗?

【问题讨论】:

  • 如果您正在使用一个名为 objective 的结构,您不应该将它包含在您的邮政编码部分吗?
  • @ryyker 谢谢我已经为我的结构添加了代码
  • 对于任何依赖于用户输入的应用程序,复杂性(处理用户输入所需的)与强加给用户的控制成反比。即,如果对用户的约束为 0,那么处理输入的应用程序的复杂性将达到无穷大。简化建议: 1) 使用一个菜单或一系列菜单,不要接受除您提供的选项之外的任何选项。 2)不要使用结构,使用列表。它们更容易添加删除部分,

标签: c arrays input struct terminal


【解决方案1】:

首先,关于用户输入的说明:我同意@ryyker,尝试为用户输入提供一种易于解析的格式。从一开始就试图让输入过于灵活会阻碍你,而你应该专注于程序的逻辑。 但也许你不是选择格式的人,所以,继续……

您选择定义结构并使用 fgets() 还不错。 但是您将所有内容都放在一个 while() 构造中,这无助于您组织代码。我不会给你一个完整的代码,而只是告诉你如何组织它。

我建议你分开:

  1. 将用户输入读入缓冲区。
  2. 从该缓冲区中提取命令。
  3. 检查用户输入是否正确。
  4. 解释命令和执行程序逻辑。

第 1 部分: scanf() 不好,因为你不知道这条线会有多长。 继续在相当长的缓冲区上使用 fgets,例如:

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.
}

【讨论】:

    猜你喜欢
    • 2016-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-04
    相关资源
    最近更新 更多