#include <iostream>
#include <memory>
#include <chrono>
#include <cassert>
#include <cstddef>
#include <cstring>
#include <cstdlib>
#include <ctime>
class muTimer
{
using Clock = std::chrono::high_resolution_clock;
bool active = false;
Clock::duration duration_;
Clock::time_point start_ = Clock::now(), stop_ = Clock::now();
muTimer(const muTimer&) = delete;
muTimer& operator=(const muTimer&) = delete;
public:
using ns = std::chrono::nanoseconds;
using mks = std::chrono::microseconds;
using ms = std::chrono::milliseconds;
muTimer() { reset(); start(); }
~muTimer() = default;
muTimer& reset()
{
duration_ = std::chrono::nanoseconds(0);
active = false;
return *this;
}
muTimer& start()
{
if (!active)
{
start_ = Clock::now();
active = true;
}
return *this;
}
muTimer& stop()
{
if (active)
{
stop_ = Clock::now();
duration_ += stop_ - start_;
active = false;
}
return *this;
}
template<typename T = mks>
unsigned long long duration()
{
return static_cast<unsigned long long>
(std::chrono::duration_cast<T>(stop_-start_).count());
}
};
#ifdef _MSC_VER
#define VTT_NO_INLINE __declspec(noinline)
#else
#define VTT_NO_INLINE __attribute__((noinline))
#endif
void VTT_NO_INLINE 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';
}
}
void VTT_NO_INLINE qrimRight(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';
}
void VTT_NO_INLINE 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;
}
::std::size_t VTT_NO_INLINE StrlenNaive(char * const psz_text)
{
char * p_char{psz_text};
for(;;)
{
if('\0' == *p_char)
{
break;
}
++p_char;
}
return(static_cast<::std::size_t>(p_char - psz_text));
}
void test
(
int const spaces_percent
, ::std::size_t const trailing_spaces_percent
, ::std::size_t const chars_count = 64'000'000
)
{
::std::size_t const trailing_spaces_count{(chars_count * trailing_spaces_percent) / ::std::size_t{100}};
auto str_a{::std::make_unique<char[]>(chars_count)};
auto str_b{::std::make_unique<char[]>(chars_count)};
auto str_c{::std::make_unique<char[]>(chars_count)};
{
size_t i{};
for(; i < (chars_count - trailing_spaces_count); ++i)
{
str_a[i] = str_b[i] = str_c[i] = ((::std::rand() % 100) < spaces_percent) ? ' ' : (' ' + 1 + (::std::rand() % 87));
}
for(; i < (chars_count - 1); ++i)
{
str_a[i] = str_b[i] = str_c[i] = ' ';
}
str_a[i] = str_b[i] = str_c[i] = '\0';
}
::std::cout << "chars count = " << chars_count << ::std::endl;
::std::cout << "trailing spaces_percent = " << trailing_spaces_percent << ::std::endl;
::std::cout << "spaces percent = " << spaces_percent << ::std::endl;
{
muTimer mt;
auto const len = strlen(str_c.get());
mt.stop();
::std::cout << "strlen " << len << " " << mt.duration() << ::std::endl;
}
{
muTimer mt;
auto const len = StrlenNaive(str_c.get());
mt.stop();
::std::cout << "strlen naive " << len << " " << mt.duration() << ::std::endl;
}
{
muTimer mt;
TrimRight(str_a.get());
mt.stop();
::std::cout << "OP " << mt.duration() << ::std::endl;
}
{
muTimer mt;
qrimRight(str_b.get());
mt.stop();
::std::cout << "Q " << mt.duration() << ::std::endl;
}
{
muTimer mt;
Trim_Naive(str_c.get());
mt.stop();
::std::cout << "naive " << mt.duration() << ::std::endl;
}
::std::cout << "cmp:"
" " << ::std::strcmp(str_a.get(), str_b.get()) <<
" " << ::std::strcmp(str_a.get(), str_c.get()) << ::std::endl;
}
int main(int argc, const char * argv[])
{
::std::srand(::std::time(nullptr));
test(20, 1);
test(20, 50);
test(20, 99);
return 0;
}