Сократить строку, используя словарь в C


Ищем комментарий кода: Сократить строку, используя словарь приемлемо аббревиатуры.

Примечания:

Только "целые слова" быть сокращены. То есть, если слово "запись" может быть сокращено до "РОЦ", "рекорды" не должны быть сокращенно "РЭС".

  • "Целое слово" - это последовательность алфавитно-цифровых символов.
  • Если сокращенно строка не помещается в буфер назначения зажать струны.
  • Бонусные баллы за предоставление возможности замещения без учета регистра, но и дело знают. Он должен обрабатывать три случая, оригинальное слово все строчные, все заглавные, или первую букву только оприходованы. Смешанные случаи могут быть обработаны любым разумным способом.
  • Например, если в словаре содержится "запись"->"отдых":

    • "запись" должно быть заменено словом "отдых"
    • "Запись" должно быть заменено словом "Отдых"
    • "Запись" должно быть заменено словом "отдых"
    • "Запись" можно заменить на "отдых", "отдых" или "отдых"
  • @param str - источник строк для сокращения (оканчивающуюся нулем)

  • @param str_abbr - назначение буфера для хранения сокращенную версию 'стр'
  • @param str_abbr_len - длина 'str_abbr' буфер, включая нуль-Терминатор
  • @param dictionary - массив допустимых сокращений
  • @param dictionary_len - количество элементов в словаре

сокр.ч

#include <stdlib.h>

typedef struct
{
    const char * full;
    const char * abbr;
} dictionary_t;

void abbreviate_string(const char * str, char * str_abbr, size_t str_abbr_len, dictionary_t * dictionary, size_t dictionary_len);

const char* CheckMatchinDictionary(char *result, dictionary_t* dictionary, size_t dictionary_len ); 

сокр.с

#include "abbr.h"

void abbreviate_string(const char * str, char * str_abbr, size_t str_abbr_len, dictionary_t * dictionary, size_t dictionary_len)
{
    const char* inputString = str;
    char ** wordArray  = NULL;
    int numOfWords = 0;

    char* word = strtok (inputString," ,-.:;");
    while (word != NULL)
    {
        wordArray = realloc (wordArray, sizeof (char*) * ++numOfWords);

        //Check memory allocation
        if(wordArray == NULL)
            exit(-1);

        wordArray[numOfWords - 1] = word;
        word = strtok (NULL, " ,-.:;");
    }

    memset(str_abbr, 0, str_abbr_len - 1);
    int i;
    int stringLength = 0;
    for(i=0; i < numOfWords; ++i )
    {
        const char* result = CheckMatchinDictionary(wordArray[i], dictionary, dictionary_len );

        // Append to the str_abbr only if fits in the destination buffer
        if( stringLength < str_abbr_len - 1)
        {
            if(result != NULL)
            {
                strcat(str_abbr, result);
                stringLength += strlen(result);
            }
            else
            {
                strcat(str_abbr, wordArray[i]);
                stringLength += strlen(wordArray[i]);
            }

            strcat(str_abbr, " ");
            stringLength += 1;
        }
        else
        {
            if(result != NULL)
                strncat(str_abbr, result, str_abbr_len - stringLength - 1);
            else
                strncat(str_abbr, wordArray[i], str_abbr_len - stringLength - 1 );
        }

    }
    //printf("The abbreviated string is %s\n", str_abbr);

}

// Function to check the match from the dictionary
const char* CheckMatchinDictionary(char *input, dictionary_t* dictionary, size_t dictionary_len )
{
    unsigned int index;
    for(index=0; index < dictionary_len; ++index)
    {
        if(strcmp(dictionary[index].full, input) == 0)
            return dictionary[index].abbr;

        else if(strcasecmp(dictionary[index].full, input) == 0)
        {
           size_t length = strlen(dictionary[index].abbr);
           char* substr = malloc(sizeof(char) * length);
           strncpy(substr, input, length);
           substr[length + 1] = '\0';
           return substr;
        }

    }

    return NULL;
}

главная

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

int main(void)
{
    /* Sample Dictionary */
    dictionary_t dictionary[] =
    {
        {"record", "rec"},
        {"maximum", "max"},
        {"minimum", "min"},
        {"number", "no"}
    };

    char str[100];
    char str_abbr[100];

    strcpy(str, "maximum record rate is:");

    abbreviate_string(str, str_abbr, sizeof(str_abbr), dictionary,   sizeof(dictionary) / sizeof(dictionary[0]));

    printf("%s -> %s\n", str, str_abbr);

    return 0;
}


157
1
задан 20 февраля 2018 в 03:02 Источник Поделиться
Комментарии
1 ответ


  1. Сэкономить время. Компиляции кода с все предупреждения включены.

  2. Код формата, с автоматического форматирования (экономит время). Еще лучше, если указана ширина, формат достаточно узким, чтобы предотвратить горизонтальные полосы прокрутки, когда разместил здесь.

  3. Члены dictionary_t используется в код перед определением. Если dictionary_t был определен в "abbr.h"тогда его повторное заявление не относится в main.c

  4. #include <string.h> отсутствует до вызова strtok(). Стандартные заголовочные файлы не должны рассчитывать на существование в "abbr.h".

  5. Звоню strtok (inputString,... С const char* inputString это неопределенное поведение , как inputString указывает на const данных.

  6. #include <stdlib.h> отсутствует до вызова realloc().

  7. А не sizeof (char*)используйте sizeof *wordArray в wordArray = realloc (wordArray, sizeof (char*) * ++numOfWords);. Это легче правильно код, пересматривать и поддерживать.

  8. CheckMatchinDictionary() вызывается перед декларации.

  9. if( stringLength < str_abbr_len - 1) миксы подпись-ность сравнивать. Предлагаю

    size_t str_abbr_len

    // int stringLength = 0;
    //....
    // if( stringLength < str_abbr_len - 1)

    size_t stringLength = 0;
    ....
    if(stringLength + 1 < str_abbr_len)


  10. Странный код использует -1 в memset(str_abbr, 0, str_abbr_len - 1); если str_abbr_len == 0, тогда слишком большое значение передается memset(). Кроме того, это не полностью заполняет называют массив с нулями. (Баг?) Рекомендую memset(str_abbr, 0, str_abbr_len);. Далее: предлагаю название изменить: str_abbr_len для str_abbr_size. С длиной в строку не считать нулевым символом. Размер лучше передает размер массива, который содержит строку.

  11. strcasecmp() это не стандартная библиотека c функцией. Легче достаточно, чтобы сделать аналогичные функции с tolower(), toupper().

  12. Хорошая попытка использования const.

  13. Недостающие "abbr.h" усложненный обзор. @Тоби спит лучше, чтобы добавили его.

  14. Ошибка? Я ожидал stringLength Обновлено в else блок.

  15. Как функция не меняет словарь, код может использовать const чтобы лучше передать код функции и разрешить некоторые оптимизации.

    void abbreviate_string(const char * str, char * str_abbr, size_t str_abbr_len, 
    // dictionary_t * dictionary, size_t dictionary_len)
    const dictionary_t * dictionary, size_t dictionary_len)

  16. Дополнительно: указатели, конечно, не указывают на перекрывающихся данных, поэтому добавьте restrict для дополнительной оптимизации потенциала.

    void abbreviate_string(const char * restrict str, char * restrict str_abbr, 
    size_t str_abbr_len, const dictionary_t * restrict dictionary,
    size_t dictionary_len)

  17. Обычно принято размещать указатели на измененные данные, а не в середине.

    //abbreviate_string(str, str_abbr, str_abbr_len, dictionary, dictionary_len)
    abbreviate_string(str_abbr, str_abbr_len, str, dictionary, dictionary_len)

  18. Добавлены abbr.h должны быть толерантными быть включены несколько раз. Исследования код охранники.

2
ответ дан 21 февраля 2018 в 07:02 Источник Поделиться