Как я могу заставить это работать с каждым разделителем? - C ++ - PullRequest
4 голосов
/ 08 февраля 2010

Я только что написал программу, которая токенизирует массив символов с помощью указателей. Программа должна была работать только с пробелом в качестве символа-разделителя. Я просто включил его и получил полный кредит, но после его включения я понял, что эта программа only работает, если символ разделителя - пробел.

У меня вопрос, как я могу заставить эту программу работать с каждым символом разделителя?

Функция, которую я показал вам ниже, возвращает указатель на следующее слово в массиве char. Это то, что я считаю нужным изменить, если оно работает со всеми символами-разделителями.

Спасибо!

Код:

char* StringTokenizer::Next(void)
{
pNextWord = pStart;

if (*pStart == '\0') { return NULL; }

while (*pStart != delim)
{
    pStart++;
}

if (*pStart == '\0') { return NULL; }

*pStart = '\0';
pStart++;

return pNextWord;
}

Цикл печати в основном:

// this loop will display the tokens
while ( ( nextWord = tk.Next ( ) ) != NULL )
{
    cout << nextWord << endl;
}

Ответы [ 5 ]

1 голос
/ 08 февраля 2010

Просто замените

while (*pStart != delim)

на эту строку

while (*pStart != '\0' && strchr(" \t\n", *pStart) == NULL)

Стандартная функция strchr (объявленная в заголовке string.h) ищет символ (заданный в качестве второго аргумента)в C-строке (заданной в качестве первого аргумента) и возвращает указатель на строку из позиции, где этот символ появляется первым.Таким образом, strchr(" \t\n", *pStart) == NULL означает, что текущий символ (*pStart) не найден в строке " \t\n", и это не разделитель!(Измените эту строку разделителя " \t\n", чтобы адаптировать ее к вашим потребностям, конечно.)

Это решение является коротким и простым способом проверить, является ли данный символ в наборе (обычно малом) из заданных интересных символов.И он использует стандартную функцию.

Кстати, вы можете сделать это, используя не только C-строку, но и std::string.Все, что вам нужно, это объявить const std::string с " \t\n" -подобным значением, а затем заменить strchr на find метод объявленной строки разделителя.

1 голос
/ 08 февраля 2010

Самый простой способ - изменить

while (*pStart != delim)

что-то вроде

while (*pStart != ' ' && *pStart != '\n' && *pStart != '\t')

Или вы можете сделать разделитель строкой и создать функцию, которая проверяет, есть ли в строке символ:

bool isDelim(char c, const char *delim) {
   while (*delim) {
      if (*delim == c)
         return true;
      delim++;
   }
   return false;
}

while ( !isDelim(*pStart, " \n\t") ) 

Или, возможно, лучшее решение - использовать для этого одну из готовых функций, например strtok .

0 голосов
/ 08 февраля 2010

Я предполагаю, что мы хотим придерживаться C вместо C ++.Функции strspn и strcspn хороши для токенизации с помощью набора разделителей.Вы можете использовать strspn, чтобы найти, где начинается следующий разделитель (т.е. где заканчивается текущий токен), а затем использовать strcspn, чтобы найти, где заканчивается разделитель (то есть, где начинается следующий токен).Цикл до конца.

0 голосов
/ 08 февраля 2010

Не скомпилировано. но я бы сделал что-то подобное.

 //const int N = someGoodValue;
char delimList[N] = {' ',',','.',';', '|', '!', '$', '\n'};//all delims here.

char* StringTokenizer::Next(void)
{
    if (*pStart == '\0') { return NULL; }

    pNextWord = pStart;

    while (1){  
        for (int x = 0; x < N; x++){
            if (*pStart == delimList[x]){ //this is it.
                *pStart = '\0';
                pStart++;
                return pNextWord;
            }

        }
        if ('\0' == *pStart){ //last word.. maybe.
                return pNextWord;   
        }
        pStart++;
    }
}

// (!compiled).
0 голосов
/ 08 февраля 2010

Хм ... это выглядит не совсем правильно:

if (*pStart = '\0')

Условие никогда не может быть верным. Я предполагаю, что вы намеревались == вместо =? У вас также есть небольшая проблема здесь:

while (*pStart != delim)

Если за последним словом в строке не указан разделитель, это будет конец строки, что вызовет серьезные проблемы.

Редактировать: Если вам действительно не нужно делать это самостоятельно, рассмотрите возможность использования потока строк для этой работы. У него уже есть все правильные механизмы на месте и довольно тщательно проверены. Это увеличивает накладные расходы, но во многих случаях вполне приемлемо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...