Когда вы думаете о том, что вам нужно, чтобы получить от вашей функции синтаксического анализа, вы знаете, что вы хотите, массив указателей, указывающих на выделенные блоки памяти, содержащую отдельные слова в usertyped
, но вы также должны знаете, сколько слов есть. Поскольку вы передаете массив указателей в качестве аргумента для работы самой функции, вам нужно только вернуть количество отдельных слов в заданной строке. Вы можете использовать что-то вида:
int parse (char **words, char *str);
(примечание: пропусканием массив из указателей (100
), вы ограничены только 100 отдельных слов, не давая возможности перераспределить если вы превысите это число. Вы можете передать указатель на указатель на символ * и перераспределить, если необходимо. Также обратите внимание, что если вы не возвращаете отрицательное число в качестве условия ошибки, выбор size_t
для возврата может более целесообразным)
При использовании strtok
, вы можете адаптировать, где и как strtok
отдельные слова, пошив разделителейstrtok
использует. (например, в предложении "This. Not that."
, если просто разбивать на spaces
, ваши разделенные слова будут включать в себя и символ '.'
). Чтобы этого не произошло, вы можете указать символ '.'
в строке разделителейstrtok
. С этой точки зрения, она также имеет смысл передать список разделителей в качестве параметра для вашей parse
функции, а также:
int parse (char **words, char *str, char *delims);
Вы можете использовать первоначальный вызов strtok
с исходной строкой, указанной в качестве аргумента, а затем закончить синтаксический анализ оставшихся строк в отдельном цикле, проходящий в качестве аргумента NULL
. Или вы можете обрабатывать оба случая в одном цикле for
. Это просто вопрос формы, либо это прекрасно.Пример:
int parse (char **words, char *str, char *delims)
{
int n = 0;
char *p;
for (p = strtok (str, delims); p; p = strtok (NULL, delims))
{
words[n++] = strdup (p); /* allocate/copy */
if (n == MAXW) { /* limit reached - realloc/break */
fprintf (stderr, "warning: MAXW reached.\n");
break;
}
}
return n;
}
Простой пример программы, указав разделители и передавая их функции parse
вместе с массивом и строка может быть:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXW = 100, MAXC = 1000 };
int parse (char **words, char *str, char *delims);
int main (void) {
char usertyped[MAXC] = {0};
char *userargv[MAXW] = {NULL};
char *delims = " \t\n.,:;";
int i, nwords = 0;
printf ("typesomething> ");
if (!fgets (usertyped, 1000, stdin)) {
fprintf (stderr, "error: invalid input.\n");
return 1;
}
if (!(nwords = parse (userargv, usertyped, delims))) {
fprintf (stderr, "error: parsed no words.\n");
return 1;
}
for (i = 0; i < nwords; i++)
printf ("userargv[%2d] : %s\n", i, userargv[i]);
for (i = 0; i < nwords; i++)
free (userargv[i]);
return 0;
}
int parse (char **words, char *str, char *delims)
{
int n = 0;
char *p;
for (p = strtok (str, delims); p; p = strtok (NULL, delims))
{
words[n++] = strdup (p); /* allocate/copy */
if (n == MAXW) { /* limit reached - realloc/break */
fprintf (stderr, "warning: MAXW reached.\n");
break;
}
}
return n;
}
Пример использования/вывода
$ ./bin/strtok_parse
typesomething> a quick brown fox jumps over the laszy dog.
userargv[ 0] : a
userargv[ 1] : quick
userargv[ 2] : brown
userargv[ 3] : fox
userargv[ 4] : jumps
userargv[ 5] : over
userargv[ 6] : the
userargv[ 7] : laszy
userargv[ 8] : dog
Несколько дополнительных заметок. Обычно в C стиль избегает использования переменных camelCase. Таким образом, usertyped
вместо userTyped
выше. (другой вопрос только для формы). Поскольку strdup
выделяет вам память, вы должны убедиться, что возврат не NULL
(как и в случае с malloc
или calloc
) для защиты от исчерпания памяти. Также обратите внимание, что вы можете либо #define SOMECONST value
, либо, как указано выше, использовать enum
для определения констант. Дайте мне знать, если у вас возникнут дополнительные вопросы.
Стандартная библиотечная функция 'strtok' может помочь вам с частью этого. –
Это ощущение домашнего задания. –
@DavidHoelzer да, это домашнее задание. но я просто прошу помощи с этой проблемой синтаксиса, а не с моим фактическим назначением (которое должно написать оболочку). – user3290724