Возвращает длину строки, содержащей любые символы, кроме заданной кодировки - PullRequest
1 голос
/ 07 декабря 2010

Мне нужно написать функцию, которая принимает два char *, один из которых содержит строку, а другой набор символов, который возвращает длину строки, НЕ содержащей ни одного из символов.

Пример:

LenContainsAnyBut("abc", "def"); // returns 3
LenContainsAnyBut("abc", "b"); // returns 1
LenContainsAnyBut("x", "xyz"); // returns 0
LenContainsAnyBut("", "xyz"); // returns 0

Вот моя реализация:

unsigned int LenContainsAnyBut(const char *s, const char *search_chars) {
    unsigned int len = 0;

    while (*(s + len) != '\0' {
        for (const char *search_char = search_chars; *seach_char != '\0'; ++search_char) {
            if (*search_char == *(s + len)) {
                return len;
            }
        }

        ++len;
    }

    return len;
}

Что-нибудь улучшить? Я бы предпочел «нотацию массива», т.е. s[0] вместо s + 0, но это не разрешено в этом назначении.

EDIT

Извините, каким-то образом удалось полностью испортить мой код>. <. </p>

Ответы [ 6 ]

1 голос
/ 08 декабря 2010

Если вы хотите улучшить время выполнения для длинных строк и / или длинных наборов исключений, вы можете попытаться воспользоваться возможностью использовать символы в качестве индексов массива и создать массив, представляющий набор символов, которые разрешены / отстранен от ваших строк.

Если вы создаете массив длиной 256, инициализируйте его равным 1 для всех элементов (кроме элемента 0, так как я думаю, что вы должны предполагать, что он всегда исключается, потому что нет способа представить его в строке исключения, потому что это строка C), а затем переберите строку набора исключений, приведя каждый символ в нем к беззнаковому (символы подписаны в некоторых системах, но они должны быть беззнаковыми, чтобы это работало) и установите байт, индексированный этим символом до 0.

В конце этого у вас есть справочная таблица, которая позволяет очень быстро определить, является ли символ концом вашей строки, и время выполнения O (n + m), а не O (n * m).

1 голос
/ 07 декабря 2010

Отправленный код даже не компилируется, и с очевидными исправлениями он войдет в вечный цикл.

При этом я написал бы эту функцию, используя strchr().

1 голос
/ 07 декабря 2010

Если вы работаете с 8-битными символами, вы можете избежать вложенных циклов. Сначала убедитесь, что s и sc (search_chars) относятся к типу unsigned char * (не просто char *!), Затем:

unsigned char set[32] = "";
size_t l=0;
for (; *sc; sc++) set[*sc/8] |= 1U<<*sc%8;
for (; *s; s++) l += 1-(set[*s/8]>>*s%8 & 1);
1 голос
/ 07 декабря 2010

Одна вещь, которую нужно изменить, это то, что len всегда 0 в вашем коде, вы должны увеличивать len после цикла for внутри while.

Другая небольшая ошибка заключается в том, что вы пропускаете 't' в объявлении len (unsigned in должен быть unsigned int).

Я также верю, что в цикле for вы изменяете само значение указателя, и это будет делать только первый символ s для проверки, при проверке других символов s * search_chars всегда будет равен "/ 0 msgstr "попробуйте также использовать целое число, как len, в цикле for

0 голосов
/ 08 декабря 2010

Я бы просто реализовал это как:

#include <string.h>

unsigned int LenContainsAnyBut(const char *s, const char *search_chars)
{
    return strcspn(s, search_chars);
}

... но эй, это только я;)

0 голосов
/ 07 декабря 2010

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

Так что извиняюсь, если на вопрос есть очевидный ответ,

но где в коде - значение len, увеличивающееся, так как символы в s 'проверяются и передаются'

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