web-dev-qa-db-fra.com

Couper une chaîne en C

Brièvement: 

Je recherche l'équivalent du String.Trim en .NET de .NET en utilisant les API win32 et C standard (en compilant avec MSVC2008, j'ai donc accès à tous les éléments C++ si nécessaire, mais j'essaie simplement de couper un char*). 

Étant donné qu'il existe strchr, strtok et toutes sortes d'autres fonctions de chaîne, il devrait sûrement y avoir une fonction de rognage, ou une fonction qui peut être réutilisée ...

Merci

20
Orion Edwards

Il n’existe pas de fonction de bibliothèque standard pour le faire, mais ce n’est pas trop difficile de lancer la vôtre. Il existe une question existante sur SO à propos de cette opération, à laquelle le code source a répondu.

21
Andrew Grant

Cela m'a donné envie d'écrire le mien - je n'aimais pas ceux qui avaient été fournis. Il me semble qu'il devrait y avoir 3 fonctions.

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)); 
}
12
JRL

Vous pouvez utiliser la fonction standard isspace () dans ctype.h pour y parvenir. Il suffit de comparer les caractères de début et de fin de votre tableau de caractères jusqu'à ce que les deux extrémités ne disposent plus d'espaces.

"espaces" comprennent:

'' (0x20) espace (SPC)

'\ t' (0x09) onglet horizontal (TAB)

'\ n' (0x0a) nouvelle ligne (LF)

Onglet vertical '\ v' (0x0b) (VT)

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

'\ r' (0x0d) retour chariot (CR)

bien qu'aucune fonction ne fasse tout le travail à votre place, vous devrez lancer votre propre solution pour comparer chaque côté du tableau de caractères donné de manière répétée jusqu'à ce qu'il ne reste plus d'espaces.

Modifier:

Depuis que vous avez accès au C++, Boost a une implémentation précise vous attend pour vous rendre la vie beaucoup plus facile.

10
John T

Surpris de voir de telles implémentations. J'ai l'habitude de couper comme ça:

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;
}

Il est rapide et fiable - me sert de nombreuses années.

4
qrdl
/* 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);
}
3
Mahant
#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));  
} 

Sortie:

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
2
Maddy
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);
}
1
Nitinkumar Ambekar
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);
}
1
roy

J'aime quand la valeur de retour est toujours égale à l'argument. Ainsi, si le tableau de chaînes a été alloué avec malloc(), il peut à nouveau être free() en toute sécurité.

/* 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;
}
1
Philip

Pas le meilleur moyen mais ça marche

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;
}
0
Baranovskiy Dmitry
/* 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;
}
0
xiujie_cn

Voici mon implémentation, qui se comporte comme les fonctions de chaîne intégrées dans libc (c’est-à-dire qu’elle attend une chaîne c, elle la modifie et la renvoie à l’appelant).

Il supprime les espaces de début et décale les caractères restants vers la gauche, car il analyse la chaîne de gauche à droite. Il marque ensuite une nouvelle fin de chaîne et commence à l'analyser en arrière, en remplaçant les espaces de fin par des\0 jusqu'à ce qu'il trouve un caractère non-espace ou le début de la chaîne. Je crois que ce sont les itérations minimales possibles pour cette tâche particulière.

// ----------------------------------------------------------------------------
// trim leading & trailing spaces from string s (return modified string s)
// alg:
// - skip leading spaces, via cp1
// - shift remaining *cp1's 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;
}
0
Harry K.

Que diriez-vous de cela ... Il ne nécessite qu'une seule itération sur la chaîne (n'utilise pas strlen, qui itère sur la chaîne). Lorsque la fonction retourne, vous obtenez un pointeur sur le début de la chaîne coupée, qui est terminée par un zéro. La chaîne est coupée des espaces de la gauche (jusqu'à ce que le premier caractère soit trouvé). La chaîne est également coupée de tous les espaces à la fin du dernier caractère non-espace.

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;
    }
}
0
user303357