Неизвестная длина и несколько требований для ввода - PullRequest
0 голосов
/ 17 мая 2018

Я работаю со структурой под названием target, которая состоит из имени символа длиной не более 8000 символов (большую часть времени будет намного меньше), int id, int duration и массива int, называемых deps который может иметь от 0 до 9000 элементов. Вот оно:

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

У меня есть некоторые функции для работы с этой структурой, я могу добавить одну, удалить, можно распечатать и т. Д. Мне нужно использовать терминал, чтобы указать, что я хочу сделать, например, чтобы добавить цель, которую мне нужно написать на терминале, «добавить идентификатор», имя «продолжительность депс». Так вот где начинается моя проблема, во имя цели она должна быть между "", если не команда не действительна. У меня также возникают проблемы с массивом deps, он может содержать от 0 до 9000 элементов, поэтому я никогда не знаю, сколько их, я должен поместить их в массив, который будет основой задачи. Я также не могу поставить два пробела между аргументами. Некоторые примеры строк ввода:

«добавить 1» цель1 «20 2 3 4 5» - это добавляет цель с идентификатором 1, именем «цель1», длительностью 20 и глубиной 2, 3, 4 и 5

"добавить 1 цель1 20 2 3 4 5" - это недопустимо, потому что имя не находится между ""

"добавить 1" цель1 "20" - это добавляет цель с идентификатором 1, именем "цель1", длительностью 20 и без задержек

"удалить 1" - удаляет цель с идентификатором 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 и пробелами между аргументами делает это действительно трудным для меня, у кого-нибудь есть совет, как я могу это сделать или как можно решить одну из перечисленных выше проблем?

1 Ответ

0 голосов
/ 18 мая 2018

Во-первых, примечание о пользовательском вводе: я согласен с @ryyker, попробуйте придумать формат для пользовательского ввода, который вам легко разобрать. Попытка сделать ввод слишком гибким с самого начала будет мешать вам, в то время как вы должны сосредоточиться на логике программы. Но, может быть, вы не тот, кто выбрал формат, так что, двигаясь дальше ...

Ваш выбор определения структуры и использования fgets () неплох. Но вы помещаете все в одну конструкцию while (), которая не поможет вам организовать ваш код. Я не буду давать вам полный код, а лишь покажу, как вы могли бы его организовать.

Я предлагаю вам отдельно:

  1. Чтение пользовательского ввода в буфер.
  2. Извлечение команд из этого буфера.
  3. Проверка правильности ввода пользователя.
  4. Интерпретация команд и выполнение программной логики.

Часть 1: scanf () не очень хорош, потому что вы не знаете, какова будет длина строки. Продолжайте использовать fgets в достаточно длинном буфере, например ::01019

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: Вы уже выполнили задание: добавление (), 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.
}
...