проверка значений массива с помощью strcmp и вложенного цикла

Я добрался до финальной части программы и снова столкнулся с некоторыми проблемами.


Проблема № 1: Когда я печатаю отдельные строковые части массива в цикле токенизации, значения в порядке. НО, когда я печатаю puts(tokenArray[1]), отображается только одна буква команды, например: Input: "qwe rty" | Распечатка в цикле while: qwe rty | Распечатка с использованием puts(tokenArray[1]) вне цикла: "e" (да, просто буква).


Проблема № 2: я заметил это во время отладки. После того, как я ввожу случайный ввод, а затем ввожу «историю», tokenArray первая позиция заполнена «историей», а следующая позиция заполнена «историей». Для этого я не могу использовать вложенный цикл и strcmp, как вы можете видеть ниже, чтобы проверить, является ли первая часть «историей», и если да, проверьте вторую часть. Если вторая часть пуста, просто показать историю команд, или если она "1"/"2" и т. д. (когда пользователь ввел "история 1", выполнить первую команду в истории.

Это мой прогресс до сих пор:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main (int argc, char *argv[])
{
    int i=0; int j=0; int k=0;
    char inputString[100];
    char *result=NULL;
    //char *result2=NULL;
    char delims[] = " ";
    char historyArray[100][100] = {0};
    char historyKey[] = "history";
    char *tokenArray[100] = {0} ;
    //char exitString[] = "exit";

    do
    {
        printf("hshell>");
        gets(inputString);
        strcpy (historyArray[k], inputString);
        k++;

        // Break the string into parts
        result = strtok(inputString, delims);


        while (result!=NULL)
        {
            //result2 = result;
            tokenArray[j] = result;
            //puts(result);
            result= strtok(NULL, delims);
            //puts(tokenArray[j]);
            j++;
        }
        //j = 0;
        puts(tokenArray[1]);
        if (strcmp(tokenArray[0],historyKey) == 0)
        {
            if (strcmp(tokenArray[1], " " ) == 0)
            {
                for (i=0; i<k; i++)
                {
                    printf("%d. %s \n",i+1,historyArray[i]);
                }
            }
        }
        else if (strcmp ("exit",inputString) != 0)
        {
            printf("\nCommand not found \n");
        }

    } while (strcmp ("exit", inputString) != 0);
    return 0;
}

person serge    schedule 20.02.2013    source источник
comment
Боковая панель: Никогда не используйте gets(). Это так плохо, что оно устарело с C99 и даже не присутствует в C11. Это ужасно. Вместо этого используйте fgets() с stdin.   -  person WhozCraig    schedule 20.02.2013
comment
У меня было fgets, но тогда моя программа ничего не делала, ни выхода, ни копирования массива. вот почему я использовал gets(), все, что я печатал, приводило к тому, что команда не найдена. Любые идеи по этому поводу?   -  person serge    schedule 20.02.2013
comment
Это было бы действительно странно. Я предполагаю, что вы использовали stdin и указали соответствующую длину для вашего входного буфера. В коде есть еще одна проблема, если это так. Я просматриваю это прямо сейчас. это было первое, что бросилось в глаза.   -  person WhozCraig    schedule 20.02.2013
comment
Да, это выглядело так fgets(inputString, 100, stdin);. Спасибо   -  person serge    schedule 20.02.2013
comment
Проблема при использовании fgets() заключается в том, что он сохраняет перевод строки в конце строки, а gets() — нет. Обычно он вам не нужен, поэтому вам нужно либо игнорировать его при сравнении, либо сначала найти его и удалить.   -  person unwind    schedule 20.02.2013


Ответы (1)


Сразу бросается в глаза несколько вещей.

  1. Вы никогда не сбрасываете значение j из одной командной строки в другую.
  2. strtok() не будет вставлять строку с одинарным пробелом в ваши входные токены только потому, что вы вводите что-то вроде «команда». Это удалит разделители, поэтому ваша логика ошибочна в этой идее. Токены ввода для «команды» будут одиночными токенами, для «команды один» это будет «команда» и только «один». Вы, очевидно, думаете, что это даст вам строку с одним пробелом из того, что вы делаете с strcmp(tokenArray[1], " " ).
  3. Основная, но не связанная с вашей непосредственной проблемой, в конечном итоге вы переполните свой стек, когда k станет достаточно большим (точнее, 100 команд)
  4. Престижность @unwind, вам нужно выбросить новую строку, полученную с помощью fgets(), что я и сделал при тестировании. Наверное, стоило упомянуть об этом.

Исправьте первое, переосмыслите второе и рассмотрите альтернативную структуру хранения истории для третьего. Наконец, я протестировал это с fgets(inputString, 100, stdin);, и это работает, так что понятия не имею, что не так с вашей стороны.

person WhozCraig    schedule 20.02.2013
comment
Кажется, у меня был номер 1. закомментировано по какой-то причине я не помню. То, как я думал об этой части проблемы, таково: разбить ввод (история 1) на части. Вставьте первую часть в tokenArray[j], а вторую в tokenArray[j+1]. Затем проверьте: если первое - это история, проверьте, пусто ли первое... и т. д. Разве это не так? - person serge; 20.02.2013
comment
@ voth1234 voth1234, если бы я сделал это, я бы сохранил разделение токенов как историю в структуре и анализировал токен за раз, бок о бок со строкой ввода. - person WhozCraig; 20.02.2013
comment
это кажется более логичным подходом. Я попробую это. Спасибо. РЕДАКТИРОВАТЬ: Как вы выбрасываете новую строку? - person serge; 20.02.2013
comment
@voth просто найдите последний символ в строке и установите для него ноль (0), если это символ '\n'. Кстати, будьте осторожны при обработке строки с нулевой длиной, чего технически у вас не должно быть. - person WhozCraig; 20.02.2013