Маркирование строк в C

Многие объяснения уже присутствуют, чтобы объяснить, как это происходит и как это исправить, но вы также должны следовать рекомендациям, чтобы избежать NullPointerException вообще.

См. также: A хороший список лучших практик

Я бы добавил, очень важно, хорошо использовать модификатор final. Использование "окончательной" модификатор, когда это применимо в Java

Сводка:

  1. Используйте модификатор final для обеспечения хорошей инициализации.
  2. Избегайте возврата null в методы, например, при возврате пустых коллекций.
  3. Использовать аннотации @NotNull и @Nullable
  4. Быстрое завершение работы и использование утверждений, чтобы избежать распространения нулевых объектов через все приложение, когда они не должен быть пустым.
  5. Сначала используйте значения с известным объектом: if("knownObject".equals(unknownObject)
  6. Предпочитают valueOf() поверх toString ().
  7. Используйте null safe StringUtils StringUtils.isEmpty(null).

24
задан Yu Hao 1 November 2013 в 05:18
поделиться

6 ответов

Сделайте это как это:

char s[256];
strcpy(s, "one two three");
char* token = strtok(s, " ");
while (token) {
    printf("token: %s\n", token);
    token = strtok(NULL, " ");
}

Примечание: strtok изменяет строку его маркирование, таким образом, это не может быть const char*.

42
ответ дан Yu Hao 28 November 2019 в 22:15
поделиться

Вот пример использования strtok, имейте в виду, что strtok является деструктивным для его входной строки (и поэтому никогда нельзя использовать для строковой константы

char *p = strtok(str, " ");
while(p != NULL) {
    printf("%s\n", p);
    p = strtok(NULL, " ");
}

В основном следует отметить, что передача NULL в качестве первого параметра в strtok говорит ему получить следующий токен из строки, в которой он был ранее токенизирован.

36
ответ дан Yu Hao 28 November 2019 в 22:15
поделиться

strtok может быть очень опасным. Это не ориентировано на многопотоковое исполнение. Его надлежащее использование должно быть вызвано и в цикле, передающем в выводе от предыдущего вызова. Функция strtok имеет внутреннюю переменную, которая хранит состояние вызова strtok. Это состояние не уникально для каждого потока - это глобально. Если какой-либо другой код использует strtok в другом потоке, Вы получаете проблемы. Не вид проблем Вы хотите разыскать также!

я рекомендовал бы искать regex реализацию или использовать sscanf для разделения строки.

Попытка это:

char strprint[256];
char text[256];
strcpy(text, "My string to test");
while ( sscanf( text, "%s %s", strprint, text) > 0 ) {
   printf("token: %s\n", strprint);
}

Примечание: 'текстовая' строка уничтожается, поскольку она разделяется. Это не может быть предпочтительным поведением =)

7
ответ дан Kieveli 28 November 2019 в 22:15
поделиться

Можно упростить код путем представления дополнительной переменной.

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

int main()
{
    char str[100], *s = str, *t = NULL;

    strcpy(str, "a space delimited string");
    while ((t = strtok(s, " ")) != NULL) {
        s = NULL;
        printf(":%s:\n", t);
    }
    return 0;
}
3
ответ дан Ferruccio 28 November 2019 в 22:15
поделиться

При чтении документации strtok я вижу, что вам нужно передать нулевой указатель после первого «инициализирующего» вызова. Может быть, вы этого не сделали. Просто предположение, конечно.

0
ответ дан xtofl 28 November 2019 в 22:15
поделиться

Вот еще одна реализация strtok(), которая имеет возможность распознавать последовательные разделители (стандартная библиотека strtok() не имеет этого)

Функция является частью библиотеки лицензированных строк BSD, называемой ] zString . Приглашаем вас принять участие:)

https://github.com/fnoyanisi/zString

char *zstring_strtok(char *str, const char *delim) {
    static char *static_str=0;      /* var to store last address */
    int index=0, strlength=0;       /* integers for indexes */
    int found = 0;                  /* check if delim is found */

    /* delimiter cannot be NULL
    * if no more char left, return NULL as well
    */
    if (delim==0 || (str == 0 && static_str == 0))
        return 0;

    if (str == 0)
        str = static_str;

    /* get length of string */
    while(str[strlength])
        strlength++;

    /* find the first occurance of delim */
    for (index=0;index<strlength;index++)
        if (str[index]==delim[0]) {
            found=1;
            break;
        }

    /* if delim is not contained in str, return str */
    if (!found) {
        static_str = 0;
        return str;
    }

    /* check for consecutive delimiters
    *if first char is delim, return delim
    */
    if (str[0]==delim[0]) {
        static_str = (str + 1);
        return (char *)delim;
    }

    /* terminate the string
    * this assignmetn requires char[], so str has to
    * be char[] rather than *char
    */
    str[index] = '\0';

    /* save the rest of the string */
    if ((str + index + 1)!=0)
        static_str = (str + index + 1);
    else
        static_str = 0;

        return str;
}

Как упоминалось в предыдущих постах, с strtok(), или тот, который я привел выше, полагается на переменную static *char, чтобы сохранить местоположение последнего разделителя между последовательными вызовами, при работе с многопоточными приложениями следует соблюдать особую осторожность.

0
ответ дан fnisi 28 November 2019 в 22:15
поделиться
Другие вопросы по тегам:

Похожие вопросы: