Необходимо написать оптимальную по обращению к памяти функцию для обрезки пробелов справа. Сама обрезка сложностей не вызывает, непонятно, что можно сделать для оптимизации и можно ли вообще оптимизировать такую реализацию.
void TrimRight(char* s) {
size_t len = strlen(s);
char* iter = s + len - 1;
if (*iter != ' ') {
// Если последний символ не пробел,
// то и обрезать нечего
return;
}
while (*iter == ' ' && iter != s) {
// Идти от конца к началу,
// пока не кончатся пробелы либо строка
iter--;
}
if (iter == s) {
// Если строка пройдена
// и полностью состоит из пробелов
// то результатом будет пустая строка
*iter = '\0';
}
else {
// Если пройдены все пробелы
// и поиск дошел до первого не пробела,
// то заменить первый пробел на конец строки.
*(iter + 1) = '\0';
}
}
https://ideone.com/EwHSCG
#include <cstring>
#include <iostream>
using namespace std;
char *trimRight(char *s)
{
char *spc=0, *p=s;
while (*p)
if (*p == ' ')
for (spc=p; *++p==' '; );
else
++p;
if (spc && p!=s && p[-1]==' ') *spc = 0;
return s;
}
int main()
{
char s[256];
cout << '"' << trimRight(strcpy(s, "")) << '"' << endl;
cout << '"' << trimRight(strcpy(s, "abc qwe zzz ")) << '"' << endl;
cout << '"' << trimRight(strcpy(s, "abc qwe zzz ")) << '"' << endl;
cout << '"' << trimRight(strcpy(s, "abc qwe zzz u")) << '"' << endl;
return 0;
}
Альтернативный вариант - поиск последнего не пробельного символа для уменьшения количества сравнений:
void Trim_Naive(char * p_char)
{
auto p_begin_or_last_non_ws{p_char};
for(;;)
{
switch(*p_char)
{
case '\0':
{
break;
}
case ' ':
{
++p_char;
continue;
}
default:
{
p_begin_or_last_non_ws = p_char;
++p_char;
continue;
}
}
break;
}
if(' ' == *p_begin_or_last_non_ws)
{
p_begin_or_last_non_ws[0] = '\0';
}
else
{
p_begin_or_last_non_ws[1] = '\0';
}
return;
}
Поглядим на производительность.:
chars count = 64000000
trailing spaces_percent = 1
spaces percent = 20
strlen 63999999 3342
strlen naive 63999999 21940
OP 3321
Q 136068
naive 27858
chars count = 64000000
trailing spaces_percent = 50
spaces percent = 20
strlen 63999999 3105
strlen naive 63999999 22620
OP 20668
Q 77093
naive 27658
chars count = 64000000
trailing spaces_percent = 99
spaces percent = 20
strlen 63999999 3064
strlen naive 63999999 22692
OP 41996
Q 20818
naive 24656
Выводы:
strlen
оптимизирован и работает в разы быстрее наивной реализации. По возможности сравниваем с пробелом не по байту, а целыми словами
// trim tail spaces from `char str[]`
// return str
// and it's new length in second argument
char *
trim2 (char str[], size_t *len)
{
size_t dummy;
if (!len)
len = &dummy;
char *t = str + strlen(str) - 1;
size_t mask = sizeof(char *) - 1,
blank = (sizeof(char *) == 4) ? 0x20202020 : 0x2020202020202020ULL;
while (t >= str) {
if (*t != ' ')
return t[1] = 0, *len = t - str + 1, str;
if (((size_t)t & mask) == 0 && t - str > mask) {
// the address is aligned and the length is sufficient
// compare by words
size_t *p = (size_t *)(t - (mask + 1));
while (p >= (size_t *)str) {
if (*p != blank)
break; // somewhere in this word there is no space
p--;
}
// again compare each byte
t = (char *)p + mask;
continue;
}
t--;
}
// empty
return *str = 0, *len = 0, str;
}
void TrimRight(char* s) {
char* space = null; // Изначально пробелов нет
// цикл до конца строки
while (*s != '\0') {
if (*s == ' ') { // если нашли пробел
// и до этого пробелов не было
if (space == null)
space = s; // запомнили позицию
} else // если нашли не пробел
space = null; // забыли, что видели пробел
s++;
}
// если таки нашли пробел
if (space != null)
*space = '\0'; // обрезали строку
}
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Вывести на экран таблицу значений функции Y(x) и ее разложения в ряд S(x) с точностью ε (табл8
https://wandboxorg/permlink/fNyh3Nj0LroooFFq