Срезание ненужных частей из строки
Мне нужно удалять из строки части, которые во время выполнения могут стать не нужными, я это делаю при помощи memmove.
Код работает, но вот он такой большой и длинный, что я думаю что я где-то намудрил с функцией которая удаляет ненужные части:
#define LIBKODIK_PARAMS_TYPES_START 7 /* Длина начала параматра в строке `type=` */
#define LIBKODIK_PARAMS_TYPES_NO_VALUE 42 /* Позиция в строке, если парамерт необходимо удалить полностью */
#define LIBKODIK_PARAMS_TYPES_MAX 12 /* Максимально возможное кол-во параметров для type=... */
#define LIBKODIK_PARAMS_PRINTF_LENGTH_STRING 3 /* Размер `%s,` */
void
libkodik_api_countries_param_types_remove_unusable_values(char *psz_value, uint8_t i_count) {
size_t const s_strlen = strlen(psz_value);
char buffer[s_strlen];
(void) strcpy(buffer, psz_value);
if (0 == i_count) { /* Кол-во параметров равно нулю? Просто срезает от и до */
(void) memcpy
(
psz_value,
&buffer[LIBKODIK_PARAMS_TYPES_NO_VALUE],
s_strlen - LIBKODIK_PARAMS_TYPES_NO_VALUE + 1
);
return;
}
(void) memmove
(
&psz_value[LIBKODIK_PARAMS_TYPES_START],
&buffer[LIBKODIK_PARAMS_TYPES_START] + (LIBKODIK_PARAMS_PRINTF_LENGTH_STRING * (LIBKODIK_PARAMS_TYPES_MAX - i_count)),
s_strlen - (LIBKODIK_PARAMS_PRINTF_LENGTH_STRING * (LIBKODIK_PARAMS_TYPES_MAX - i_count) + 1)
);
}
Этот тестовый код показывает что функция отрабатывает правильно, но может ее можно как-то улушить?
int main(void) {
char buffer_flags[] = "types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s";
char buffer_flags2[] = "types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s";
uint8_t i_flags_count = 4;
if (12 != i_flags_count) {
libkodik_api_countries_param_types_remove_unusable_values(buffer_flags, i_flags_count);
}
printf("Changed: %s\n", buffer_flags);
printf("Original: %s\n", "types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s");
i_flags_count = 0;
if (12 != i_flags_count) {
libkodik_api_countries_param_types_remove_unusable_values(buffer_flags2, i_flags_count);
}
printf("Changed2: %s\n", buffer_flags2);
printf("Original2: %s\n", "types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s");
return 0;
}
Changed: types=%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s Original: types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s Changed2: year=%lu&translation_id=%lu&translation_type=%s&sort=%s Original2: types=%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s&year=%lu&translation_id=%lu&translation_type=%s&sort=%s
Ответы (2 шт):
А зачем использовать конструкцию
&psz_value[LIBKODIK_PARAMS_TYPES_START]
чем плоха
psz_value + LIBKODIK_PARAMS_TYPES_START
Она даже лучше отражает суть
ВНИМАНИЕ:
char buffer[s_strlen];
(void) strcpy(buffer, psz_value);
я бы тут немного испугался - ведь строка должна заканчиваться \0, а у вас буфер на 1 байт меньше чем строка с \0
правильнее было бы написать
char buffer[s_strlen + 1];
иначе вы можете чего-то лишнего затереть (при условии, что размер строки кратен 4 к примеру)
Что-то вы перемудрили. Требуемое поведение функции вами четко не определено, но насколько я понимаю, вот это должно работать:
void
remove_unusable_specifiers(char *s, unsigned int max_specifiers)
{
char *begin = strlen("types=") + s;
char *end = begin + strspn(begin, "%s,");
if (max_specifiers == 0) {
memmove(s, end + 1, strlen(end) + 1);
return;
}
memmove(begin + strlen("%s,") * max_specifiers - 1, end, strlen(end) + 1);
}
Основная проблема вашего кода — длинные и сложные имена сущностей (переменных и констант). Да, конечно, магические числа в коде — это плохо, но везде нужна золотая середина.