Как стандартным способом обрезать начальные / конечные пробелы? - PullRequest
162 голосов
/ 23 сентября 2008

Существует ли чистый, желательно стандартный метод обрезания начальных и конечных пробелов из строки в C? Я бы бросил свой, но я бы подумал, что это общая проблема с таким же распространенным решением.

Ответы [ 37 ]

0 голосов
/ 13 января 2016

C ++ STL стиль

std::string Trimed(const std::string& s)
{
    std::string::const_iterator begin = std::find_if(s.begin(),
                                                 s.end(),
                                                 [](char ch) { return !std::isspace(ch); });

    std::string::const_iterator   end = std::find_if(s.rbegin(),
                                                 s.rend(),
                                                 [](char ch) { return !std::isspace(ch); }).base();
    return std::string(begin, end);
}

http://ideone.com/VwJaq9

0 голосов
/ 15 июня 2018

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

#include <ctype.h>
#include <string.h>
void trim_str(char *s)
{
    const size_t s_len = strlen(s);

    int i;
    for (i = 0; i < s_len; i++)
    {
        if (!isspace( (unsigned char) s[i] )) break;
    }

    if (i == s_len)
    {
        // s is an empty string or contains only space characters

        s[0] = '\0';
    }
    else
    {
        // s contains non-space characters

        const char *non_space_beginning = s + i;

        char *non_space_ending = s + s_len - 1;
        while ( isspace( (unsigned char) *non_space_ending ) ) non_space_ending--;

        size_t trimmed_s_len = non_space_ending - non_space_beginning + 1;

        if (s != non_space_beginning)
        {
            // Non-space characters exist in the beginning of s

            memmove(s, non_space_beginning, trimmed_s_len);
        }

        s[trimmed_s_len] = '\0';
    }
}
0 голосов
/ 10 февраля 2016
void trim(char* const str)
{
    char* begin = str;
    char* end = str;
    while (isspace(*begin))
    {
        ++begin;
    }
    char* s = begin;
    while (*s != '\0')
    {
        if (!isspace(*s++))
        {
            end = s;
        }
    }
    *end = '\0';
    const int dist = end - begin;
    if (begin > str && dist > 0)
    {
        memmove(str, begin, dist + 1);
    }
}

Изменяет строку на месте, так что вы все равно можете ее удалить.

Не использует функции библиотеки необычных штанов (если только вы не считаете, что это мемо).

Обрабатывает перекрытие строк.

Обрезки спереди и сзади (не средний, извините).

Быстро, если строка большая (memmove часто пишется на ассемблере).

Перемещает символы только при необходимости (я нахожу это истинным в большинстве случаев, потому что строки редко имеют начальные пробелы и часто не имеют хвостовых пробелов)

Я хотел бы проверить это, но я опаздываю. Наслаждайтесь поиском ошибок ...: -)

0 голосов
/ 07 августа 2018
char* strtrim(char* const str)
{
    if (str != nullptr)
    {
        char const* begin{ str };
        while (std::isspace(*begin))
        {
            ++begin;
        }

        auto end{ begin };
        auto scout{ begin };
        while (*scout != '\0')
        {
            if (!std::isspace(*scout++))
            {
                end = scout;
            }
        }

        auto /* std::ptrdiff_t */ const length{ end - begin };
        if (begin != str)
        {
            std::memmove(str, begin, length);
        }

        str[length] = '\0';
    }

    return str;
}
0 голосов
/ 23 февраля 2016

Чтобы обрезать мои струны с обеих сторон, я использую старое, но доброе;) Он может обрезать что угодно с ascii меньше пробела, что означает, что управляющие символы также будут обрезаны!

char *trimAll(char *strData)
{
  unsigned int L = strlen(strData);
  if(L > 0){ L--; }else{ return strData; }
  size_t S = 0, E = L;
  while((!(strData[S] > ' ') || !(strData[E] > ' ')) && (S >= 0) && (S <= L) && (E >= 0) && (E <= L))
  {
    if(strData[S] <= ' '){ S++; }
    if(strData[E] <= ' '){ E--; }
  }
  if(S == 0 && E == L){ return strData; } // Nothing to be done
  if((S >= 0) && (S <= L) && (E >= 0) && (E <= L)){
    L = E - S + 1;
    memmove(strData,&strData[S],L); strData[L] = '\0';
  }else{ strData[0] = '\0'; }
  return strData;
}
0 голосов
/ 18 октября 2013

Что вы думаете об использовании функции StrTrim, определенной в заголовке Shlwapi.h.? Это прямолинейно, скорее, самоопределение.
Подробности можно найти на:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb773454(v=vs.85).aspx

Если у вас есть
char ausCaptain[]="GeorgeBailey ";
StrTrim(ausCaptain," ");
Это даст ausCaptain как "GeorgeBailey", а не "GeorgeBailey ".

0 голосов
/ 20 февраля 2013

Это кратчайшая возможная реализация, о которой я могу подумать:

static const char *WhiteSpace=" \n\r\t";
char* trim(char *t)
{
    char *e=t+(t!=NULL?strlen(t):0);               // *e initially points to end of string
    if (t==NULL) return;
    do --e; while (strchr(WhiteSpace, *e) && e>=t);  // Find last char that is not \r\n\t
    *(++e)=0;                                      // Null-terminate
    e=t+strspn (t,WhiteSpace);                           // Find first char that is not \t
    return e>t?memmove(t,e,strlen(e)+1):t;                  // memmove string contents and terminator
}
...