Подтвердить что ты не робот

Обрежьте строку в C

Вкратце:

Я получил эквивалент .NET String.Trim в C, используя win32 и стандартную C api (компиляция с MSVC2008, поэтому при необходимости я имею доступ ко всем материалам С++, но я просто пытаюсь обрезать char*).

Учитывая, что существует strchr, strtok и всевозможные другие строковые функции, обязательно должна быть функция триммера или одна, которая может быть перепрограммирована...

Спасибо

4b9b3361

Ответ 1

Для этого нет стандартной библиотечной функции, но она не слишком сложна для самостоятельной работы. Существует существующий вопрос о том, как это сделать, на что был дан ответ с исходным кодом.

Ответ 2

Это заставило меня хотеть написать свое - мне не нравились те, которые были предоставлены. Кажется, что должно быть 3 функции.

char *ltrim(char *s)
{
    while(isspace(*s)) s++;
    return s;
}

char *rtrim(char *s)
{
    char* back = s + strlen(s);
    while(isspace(*--back));
    *(back+1) = '\0';
    return s;
}

char *trim(char *s)
{
    return rtrim(ltrim(s)); 
}

Ответ 3

Для достижения этой цели вы можете использовать стандартную isspace() функцию ctype.h. Просто сравните начальные и конечные символы вашего массива символов, пока оба конца больше не будут иметь пробелы.

"пробелы" включают:

'' (0x20) пространство (SPC)

'\ t' (0x09) горизонтальная вкладка (TAB)

'\n' (0x0a) newline (LF)

'\ v' (0x0b) вертикальная вкладка (VT)

'\ f' (0x0c) feed (FF)

'\ r' (0x0d) возврат каретки (CR)

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

Edit:

Поскольку у вас есть доступ к С++, Boost имеет реализацию обрезки, ожидая, что вы значительно облегчите свою жизнь.

Ответ 4

Удивлен, увидев такие реализации. Обычно я делаю так:

char *trim(char *s) {
    char *ptr;
    if (!s)
        return NULL;   // handle NULL string
    if (!*s)
        return s;      // handle empty string
    for (ptr = s + strlen(s) - 1; (ptr >= s) && isspace(*ptr); --ptr);
    ptr[1] = '\0';
    return s;
}

Это быстро и надежно - служит мне много лет.

Ответ 5

/* Function to remove white spaces on both sides of a string i.e trim */

void trim (char *s)
{
    int i;

    while (isspace (*s)) s++;   // skip left side white spaces
    for (i = strlen (s) - 1; (isspace (s[i])); i--) ;   // skip right side white spaces
    s[i + 1] = '\0';
    printf ("%s\n", s);
}

Ответ 6

#include "stdafx.h"
#include <string.h>
#include <ctype.h>

char* trim(char* input);


int _tmain(int argc, _TCHAR* argv[])
{
    char sz1[]="  MQRFH  ";
    char sz2[]=" MQRFH";
    char sz3[]="  MQR FH";
    char sz4[]="MQRFH  ";
    char sz5[]="MQRFH";
    char sz6[]="M";
    char sz7[]="M ";
    char sz8[]=" M";
    char sz9[]="";
    char sz10[]="        ";

    printf("sz1:[%s] %d\n",trim(sz1), strlen(sz1));
    printf("sz2:[%s] %d\n",trim(sz2), strlen(sz2));
    printf("sz3:[%s] %d\n",trim(sz3), strlen(sz3));
    printf("sz4:[%s] %d\n",trim(sz4), strlen(sz4));
    printf("sz5:[%s] %d\n",trim(sz5), strlen(sz5));
    printf("sz6:[%s] %d\n",trim(sz6), strlen(sz6));
    printf("sz7:[%s] %d\n",trim(sz7), strlen(sz7));
    printf("sz8:[%s] %d\n",trim(sz8), strlen(sz8));
    printf("sz9:[%s] %d\n",trim(sz9), strlen(sz9));
    printf("sz10:[%s] %d\n",trim(sz10), strlen(sz10));

    return 0;
}

char *ltrim(char *s) 
{     
    while(isspace(*s)) s++;     
    return s; 
}  

char *rtrim(char *s) 
{     
    char* back;
    int len = strlen(s);

    if(len == 0)
        return(s); 

    back = s + len;     
    while(isspace(*--back));     
    *(back+1) = '\0';     
    return s; 
}  

char *trim(char *s) 
{     
    return rtrim(ltrim(s));  
} 

Вывод:

sz1:[MQRFH] 9
sz2:[MQRFH] 6
sz3:[MQR FH] 8
sz4:[MQRFH] 7
sz5:[MQRFH] 5
sz6:[M] 1
sz7:[M] 2
sz8:[M] 2
sz9:[] 0
sz10:[] 8

Ответ 7

static inline void ut_trim(char * str) {
   char * start = str;
   char * end = start + strlen(str);

   while (--end >= start) {   /* trim right */
      if (!isspace(*end))
         break;
   }
   *(++end) = '\0';

   while (isspace(*start))    /* trim left */
      start++;

   if (start != str)          /* there is a string */
      memmove(str, start, end - start + 1);
}

Ответ 8

Мне нравится, когда возвращаемое значение всегда равно аргументу. Таким образом, если строковый массив был выделен с помощью malloc(), он может безопасно быть free() снова.

/* Remove leading whitespaces */
char *ltrim(char *const s)
{
        size_t len;
        char *cur;

        if(s && *s) {
                len = strlen(s);
                cur = s;

                while(*cur && isspace(*cur))
                        ++cur, --len;

                if(s != cur)
                        memmove(s, cur, len + 1);

        }

        return s;
}

/* Remove trailing whitespaces */
char *rtrim(char *const s)
{
        size_t len;
        char *cur;

        if(s && *s) {
                len = strlen(s);
                cur = s + len - 1;

                while(cur != s && isspace(*cur))
                        --cur, --len;

                cur[isspace(*cur) ? 0 : 1] = '\0';
        }

        return s;
}

/* Remove leading and trailing whitespaces */
char *trim(char *const s)
{
        rtrim(s);  // order matters
        ltrim(s);

        return s;
}

Ответ 9

void ltrim(char str[PATH_MAX])
{
        int i = 0, j = 0;
        char buf[PATH_MAX];
        strcpy(buf, str);
        for(;str[i] == ' ';i++);

        for(;str[i] != '\0';i++,j++)
                buf[j] = str[i];
        buf[j] = '\0';
        strcpy(str, buf);
}

Ответ 10

Как насчет этого... Это требует только одной итерации по строке (не использует strlen, который выполняет итерацию по строке). Когда функция возвращается, вы получаете указатель на начало обрезанной строки, которая завершается нулем. Строка обрезается пробелами слева (до тех пор, пока не будет найден первый символ). Строка также обрезается из всех конечных пробелов после последнего символа пробела.

char* trim(char* input) {
    char* start = input;
    while (isSpace(*start)) { //trim left
        start++;
    }

    char* ptr = start;
    char* end = start;
    while (*ptr++ != '\0') { //trim right
        if (!isSpace(*ptr)) { //only move end pointer if char isn't a space
            end = ptr;
        }
    }

    *end = '\0'; //terminate the trimmed string with a null
    return start;
}

bool isSpace(char c) {
    switch (c) {
        case ' ':
        case '\n':
        case '\t':
        case '\f':
        case '\r':
            return true;
            break;
        default:
            return false;
            break;
    }
}

Ответ 11

/* iMode 0:ALL, 1:Left, 2:Right*/
char* Trim(char* szStr,const char ch, int iMode)
{
    if (szStr == NULL)
        return NULL;
    char szTmp[1024*10] = { 0x00 };
    strcpy(szTmp, szStr);
    int iLen = strlen(szTmp);
    char* pStart = szTmp;
    char* pEnd = szTmp+iLen;
    int i;
    for(i = 0;i < iLen;i++){
        if (szTmp[i] == ch && pStart == szTmp+i && iMode != 2)
            ++pStart;
        if (szTmp[iLen-i-1] == ch && pEnd == szTmp+iLen-i && iMode != 1)
            *(--pEnd) = '\0';
    }
    strcpy(szStr, pStart);
    return szStr;
}

Ответ 12

Здесь моя реализация, ведущая себя как встроенные строковые функции в libc (т.е. ожидает c-строку, она изменяет ее и возвращает ее вызывающему).

Он выравнивает ведущие пробелы и сдвигает остальные символы влево, поскольку он анализирует строку слева направо. Затем он отмечает новый конец строки и начинает его разворачивать назад, заменяя конечные пробелы "\ 0", пока не найдет не-пробел char или начало строки. Я считаю, что это минимально возможные итерации для этой конкретной задачи.

// ----------------------------------------------------------------------------
// trim leading & trailing spaces from string s (return modified string s)
// alg:
// - skip leading spaces, via cp1
// - shift remaining *cp1 to the left, via cp2
// - mark a new end of string
// - replace trailing spaces with '\0', via cp2
// - return the trimmed s
//
char *s_trim(char *s)
{
    char *cp1;                              // for parsing the whole s
    char *cp2;                              // for shifting & padding

    // skip leading spaces, shift remaining chars
    for (cp1=s; isspace(*cp1); cp1++ )      // skip leading spaces, via cp1
        ;
    for (cp2=s; *cp1; cp1++, cp2++)         // shift left remaining chars, via cp2
        *cp2 = *cp1;
    *cp2-- = 0;                             // mark new end of string for s

    // replace trailing spaces with '\0'
    while ( cp2 > s && isspace(*cp2) )
        *cp2-- = 0;                         // pad with '\0's

    return s;
}

Ответ 13

Не лучший способ, но он работает

char* Trim(char* str)
{
    int len = strlen(str);
    char* buff = new char[len];
    int i = 0;
    memset(buff,0,len*sizeof(char));
    do{
        if(isspace(*str)) continue;
        buff[i] = *str; ++i;
    } while(*(++str) != '\0');
    return buff;
}

Ответ 14

void inPlaceStrTrim(char* str) {
    int k = 0;
    int i = 0;
    for (i=0; str[i] != '\0';) {
        if (isspace(str[i])) {
            // we have got a space...
            k = i;
            for (int j=i; j<strlen(str)-1; j++) {
                str[j] = str[j+1];
            }
            str[strlen(str)-1] = '\0';
            i = k; // start the loop again where we ended..
        } else {
            i++;
        }
    }
}

Ответ 15

Простейшая вещь - простой цикл. Я предполагаю, что вы хотите, чтобы обрезанная строка вернулась на место.

char *
strTrim(char * s){
    int ix, jx;
    int len ;
    char * buf 
    len = strlen(s);  /* possibly should use strnlen */
    buf = (char *) malloc(strlen(s)+1);

    for(ix=0, jx=0; ix < len; ix++){
       if(!isspace(s[ix]))
          buf[jx++] = s[ix];

    buf[jx] = '\0';
    strncpy(s, buf, jx);  /* always looks as far as the null, but who cares? */
    free(buf);            /* no good leak goes unpunished */
    return s;             /* modifies s in place *and* returns it for swank */
 }

Это также избавляет от встроенных заготовок, если String.Trim не делает этого, ему требуется немного больше логики.