Como faço para aparar espaços em branco iniciais / finais de maneira padrão?

Existe um método limpo, de preferência padrão para aparar os espaços em branco iniciais e finais de uma string em C? Eu mudaria o meu próprio, mas eu acho que isso é um problema comum com uma solução igualmente comum.

Se você pode modificar a string:

// Note: This function returns a pointer to a substring of the original string. // If the given string was allocated dynamically, the caller must not overwrite // that pointer with the returned value, since the original pointer must be // deallocated using the same allocator with which it was allocated. The return // value must NOT be deallocated using free() etc. char *trimwhitespace(char *str) { char *end; // Trim leading space while(isspace((unsigned char)*str)) str++; if(*str == 0) // All spaces? return str; // Trim trailing space end = str + strlen(str) - 1; while(end > str && isspace((unsigned char)*end)) end--; // Write new null terminator character end[1] = '\0'; return str; } 

Se você não pode modificar a string, então você pode usar basicamente o mesmo método:

 // Stores the trimmed input string into the given output buffer, which must be // large enough to store the result. If it is too small, the output is // truncated. size_t trimwhitespace(char *out, size_t len, const char *str) { if(len == 0) return 0; const char *end; size_t out_size; // Trim leading space while(isspace((unsigned char)*str)) str++; if(*str == 0) // All spaces? { *out = 0; return 1; } // Trim trailing space end = str + strlen(str) - 1; while(end > str && isspace((unsigned char)*end)) end--; end++; // Set output size to minimum of trimmed string length and buffer size minus 1 out_size = (end - str) < len-1 ? (end - str) : len-1; // Copy trimmed string and add null terminator memcpy(out, str, out_size); out[out_size] = 0; return out_size; } 

Aqui está um que muda a string para a primeira posição do seu buffer. Você pode desejar esse comportamento para que, se você alocar dinamicamente a sequência, ainda possa liberá-la no mesmo ponteiro que trim () retorna:

 char *trim(char *str) { size_t len = 0; char *frontp = str; char *endp = NULL; if( str == NULL ) { return NULL; } if( str[0] == '\0' ) { return str; } len = strlen(str); endp = str + len; /* Move the front and back pointers to address the first non-whitespace * characters from each end. */ while( isspace((unsigned char) *frontp) ) { ++frontp; } if( endp != frontp ) { while( isspace((unsigned char) *(--endp)) && endp != frontp ) {} } if( str + len - 1 != endp ) *(endp + 1) = '\0'; else if( frontp != str && endp == frontp ) *str = '\0'; /* Shift the string so that it starts at str so that if it's dynamically * allocated, we can still free it on the returned pointer. Note the reuse * of endp to mean the front of the string buffer now. */ endp = str; if( frontp != str ) { while( *frontp ) { *endp++ = *frontp++; } *endp = '\0'; } return str; } 

Teste para correção:

 int main(int argc, char *argv[]) { char *sample_strings[] = { "nothing to trim", " trim the front", "trim the back ", " trim one char front and back ", " trim one char front", "trim one char back ", " ", " ", "a", "", NULL }; char test_buffer[64]; int index; for( index = 0; sample_strings[index] != NULL; ++index ) { strcpy( test_buffer, sample_strings[index] ); printf("[%s] -> [%s]\n", sample_strings[index], trim(test_buffer)); } /* The test prints the following: [nothing to trim] -> [nothing to trim] [ trim the front] -> [trim the front] [trim the back ] -> [trim the back] [ trim one char front and back ] -> [trim one char front and back] [ trim one char front] -> [trim one char front] [trim one char back ] -> [trim one char back] [ ] -> [] [ ] -> [] [a] -> [a] [] -> [] */ return 0; } 

O arquivo de origem era trim.c Compilado com ‘cc trim.c -o trim’.

Minha solução. String deve ser alterável. A vantagem acima de algumas das outras soluções é que ele move a parte não espacial para o início, para que você possa continuar usando o ponteiro antigo, caso precise liberá-lo mais tarde.

 void trim(char * s) { char * p = s; int l = strlen(p); while(isspace(p[l - 1])) p[--l] = 0; while(* p && isspace(* p)) ++p, --l; memmove(s, p, l + 1); } 

Esta versão cria uma cópia da string com strndup () em vez de editá-la no lugar. strndup () requer _GNU_SOURCE, então talvez você precise fazer seu próprio strndup () com malloc () e strncpy ().

 char * trim(char * s) { int l = strlen(s); while(isspace(s[l - 1])) --l; while(* s && isspace(* s)) ++s, --l; return strndup(s, l); } 

Aqui está a minha tentativa de uma function de ajuste simples, mas correta no local.

 void trim(char *str) { int i; int begin = 0; int end = strlen(str) - 1; while (isspace((unsigned char) str[begin])) begin++; while ((end >= begin) && isspace((unsigned char) str[end])) end--; // Shift all characters back to the start of the string array. for (i = begin; i < = end; i++) str[i - begin] = str[i]; str[i - begin] = '\0'; // Null terminate string. } 

Aqui está a minha biblioteca C mini para cortar esquerda, direita, ambos, todos, no lugar e separados, e cortar um conjunto de caracteres especificados (ou espaço em branco por padrão).

conteúdo de strlib.h:

 #ifndef STRLIB_H_ #define STRLIB_H_ 1 enum strtrim_mode_t { STRLIB_MODE_ALL = 0, STRLIB_MODE_RIGHT = 0x01, STRLIB_MODE_LEFT = 0x02, STRLIB_MODE_BOTH = 0x03 }; char *strcpytrim(char *d, // destination char *s, // source int mode, char *delim ); char *strtriml(char *d, char *s); char *strtrimr(char *d, char *s); char *strtrim(char *d, char *s); char *strkill(char *d, char *s); char *triml(char *s); char *trimr(char *s); char *trim(char *s); char *kill(char *s); #endif 

conteúdo de strlib.c:

 #include  char *strcpytrim(char *d, // destination char *s, // source int mode, char *delim ) { char *o = d; // save orig char *e = 0; // end space ptr. char dtab[256] = {0}; if (!s || !d) return 0; if (!delim) delim = " \t\n\f"; while (*delim) dtab[*delim++] = 1; while ( (*d = *s++) != 0 ) { if (!dtab[0xFF & (unsigned int)*d]) { // Not a match char e = 0; // Reset end pointer } else { if (!e) e = d; // Found first match. if ( mode == STRLIB_MODE_ALL || ((mode != STRLIB_MODE_RIGHT) && (d == o)) ) continue; } d++; } if (mode != STRLIB_MODE_LEFT && e) { // for everything but trim_left, delete trailing matches. *e = 0; } return o; } // perhaps these could be inlined in strlib.h char *strtriml(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_LEFT, 0); } char *strtrimr(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_RIGHT, 0); } char *strtrim(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_BOTH, 0); } char *strkill(char *d, char *s) { return strcpytrim(d, s, STRLIB_MODE_ALL, 0); } char *triml(char *s) { return strcpytrim(s, s, STRLIB_MODE_LEFT, 0); } char *trimr(char *s) { return strcpytrim(s, s, STRLIB_MODE_RIGHT, 0); } char *trim(char *s) { return strcpytrim(s, s, STRLIB_MODE_BOTH, 0); } char *kill(char *s) { return strcpytrim(s, s, STRLIB_MODE_ALL, 0); } 

A única rotina principal faz tudo isso. Ele apara no lugar se src == dst , caso contrário, funciona como as rotinas strcpy . Ela apara um conjunto de caracteres especificado no delimitador de cadeia ou espaço em branco se nulo. Ela apara esquerda, direita, ambas e todas (como tr). Não há muito a fazer, e itera na sequência apenas uma vez. Algumas pessoas podem se queixar de que o corte direito começa à esquerda, no entanto, nenhum strlen é necessário, que começa à esquerda de qualquer maneira. (De uma forma ou de outra, você tem que chegar ao final da string para o corte direito, então você pode fazer o trabalho como você vai.) Pode haver argumentos a serem feitos sobre pipelining e tamanhos de cache e tal – quem sabe . Como a solução funciona da esquerda para a direita e só repete uma vez, ela também pode ser expandida para funcionar em streams. Limitações: não funciona em strings unicode .

Aqui está uma solução semelhante à rotina de modificação no local @ adam-rosenfields, mas sem recorrer desnecessariamente a strlen (). Como @jkramer, a string é ajustada à esquerda dentro do buffer para que você possa liberar o mesmo ponteiro. Não é ideal para strings grandes, pois não usa o memmove. Inclui os operadores ++ / – que @ jfm3 menciona. Testes de unidade baseados em FCTX incluídos.

 #include  void trim(char * const a) { char *p = a, *q = a; while (isspace(*q)) ++q; while (*q) *p++ = *q++; *p = '\0'; while (p > a && isspace(*--p)) *p = '\0'; } /* See http://fctx.wildbearsoftware.com/ */ #include "fct.h" FCT_BGN() { FCT_QTEST_BGN(trim) { { char s[] = ""; trim(s); fct_chk_eq_str("", s); } // Trivial { char s[] = " "; trim(s); fct_chk_eq_str("", s); } // Trivial { char s[] = "\t"; trim(s); fct_chk_eq_str("", s); } // Trivial { char s[] = "a"; trim(s); fct_chk_eq_str("a", s); } // NOP { char s[] = "abc"; trim(s); fct_chk_eq_str("abc", s); } // NOP { char s[] = " a"; trim(s); fct_chk_eq_str("a", s); } // Leading { char s[] = " ac"; trim(s); fct_chk_eq_str("ac", s); } // Leading { char s[] = "a "; trim(s); fct_chk_eq_str("a", s); } // Trailing { char s[] = "ac "; trim(s); fct_chk_eq_str("ac", s); } // Trailing { char s[] = " a "; trim(s); fct_chk_eq_str("a", s); } // Both { char s[] = " ac "; trim(s); fct_chk_eq_str("ac", s); } // Both // Villemoes pointed out an edge case that corrupted memory. Thank you. // http://stackoverflow.com/questions/122616/#comment23332594_4505533 { char s[] = "a "; // Buffer with whitespace before s + 2 trim(s + 2); // Trim " " containing only whitespace fct_chk_eq_str("", s + 2); // Ensure correct result from the trim fct_chk_eq_str("a ", s); // Ensure preceding buffer not mutated } // doukremt suggested I investigate this test case but // did not indicate the specific behavior that was objectionable. // http://stackoverflow.com/posts/comments/33571430 { char s[] = " foobar"; // Shifted across whitespace trim(s); // Trim fct_chk_eq_str("foobar", s); // Leading string is correct // Here is what the algorithm produces: char r[16] = { 'f', 'o', 'o', 'b', 'a', 'r', '\0', ' ', ' ', 'f', 'o', 'o', 'b', 'a', 'r', '\0'}; fct_chk_eq_int(0, memcmp(s, r, sizeof(s))); } } FCT_QTEST_END(); } FCT_END(); 

Outro, com uma linha fazendo o trabalho real:

 #include  int main() { const char *target = " haha "; char buf[256]; sscanf(target, "%s", buf); // Trimming on both sides occurs here printf("< %s>\n", buf); } 

Tarde para a festa de encerramento

Características:
1. Apare o começo rapidamente, como em várias outras respostas.
2. Depois de ir para o final, aparando o direito com apenas 1 teste por loop. Como @ jfm3, mas funciona para uma string toda em espaço em branco)
3. Para evitar um comportamento indefinido quando char é um char assinado, casting *s para unsigned char .

Tratamento de caracteres “Em todos os casos, o argumento é um int , cujo valor deve ser representado como um unsigned char ou igual ao valor da macro EOF . Se o argumento tiver outro valor, o comportamento é indefinido.” C11 §7.4 1

 #include  // Return a pointer to the trimmed string char *string_trim_inplace(char *s) { while (isspace((unsigned char) *s)) s++; if (*s) { char *p = s; while (*p) p++; while (isspace((unsigned char) *(--p))); p[1] = '\0'; } return s; } 

Eu não gostei da maioria dessas respostas porque eles fizeram um ou mais dos seguintes …

  1. Retornou um ponteiro diferente dentro da string do ponteiro original (uma espécie de dor para manipular dois pointers diferentes para a mesma coisa).
  2. Fiz uso gratuito de coisas como strlen () que pré-iteram toda a string.
  3. Utilizou funções lib específicas do SO não portáteis.
  4. Backscanned.
  5. Usou a comparação para ” em vez de isspace () para que TAB / CR / LF sejam preservados.
  6. Memória desperdiçada com grandes buffers estáticos.
  7. Ciclos desperdiçados com funções de alto custo como sscanf / sprintf .

Aqui está a minha versão:

 void fnStrTrimInPlace(char *szWrite) { const char *szWriteOrig = szWrite; char *szLastSpace = szWrite, *szRead = szWrite; int bNotSpace; // SHIFT STRING, STARTING AT FIRST NON-SPACE CHAR, LEFTMOST while( *szRead != '\0' ) { bNotSpace = !isspace((unsigned char)(*szRead)); if( (szWrite != szWriteOrig) || bNotSpace ) { *szWrite = *szRead; szWrite++; // TRACK POINTER TO LAST NON-SPACE if( bNotSpace ) szLastSpace = szWrite; } szRead++; } // TERMINATE AFTER LAST NON-SPACE (OR BEGINNING IF THERE WAS NO NON-SPACE) *szLastSpace = '\0'; } 

A maneira mais fácil de pular espaços iniciais em uma string é, imho,

 #include  int main() { char *foo=" teststring "; char *bar; sscanf(foo,"%s",bar); printf("String is >%s< \n",bar); return 0; } 

Muito tarde para a festa …

Solução de digitalização avançada de passagem única sem retrocesso. Cada caractere na string de origem é testado exatamente uma vez. (Portanto, deve ser mais rápido que a maioria das outras soluções aqui, especialmente se a string de origem tiver muitos espaços à direita.)

Isso inclui duas soluções, uma para copiar e aparar uma string de origem em outra string de destino e outra para aparar a string de origem no lugar. Ambas as funções usam o mesmo código.

A string (modificável) é movida no local, portanto, o ponteiro original permanece inalterado.

 #include  #include  char * trim2(char *d, const char *s) { // Sanity checks if (s == NULL || d == NULL) return NULL; // Skip leading spaces unsigned const char * p = (unsigned const char *)s; while (isspace(*p)) p++; // Copy the string unsigned char * dst = (unsigned char *)d; // d and s can be the same unsigned char * end = dst; while (*p != '\0') { if (!isspace(*dst++ = *p++)) end = dst; } // Truncate trailing spaces *end = '\0'; return d; } char * trim(char *s) { return trim2(s, s); } 

Use uma biblioteca de strings , por exemplo:

 Ustr *s1 = USTR1(\7, " 12345 "); ustr_sc_trim_cstr(&s1, " "); assert(ustr_cmp_cstr_eq(s1, "12345")); 

… como você diz que isso é um problema “comum”, sim você precisa include um #include ou algo assim e ele não está incluído no libc mas não invente seu próprio hack job armazenando pointers randoms e size_t é desse jeito buffer overflows.

 #include "stdafx.h" #include "malloc.h" #include "string.h" int main(int argc, char* argv[]) { char *ptr = (char*)malloc(sizeof(char)*30); strcpy(ptr," Hel lo wo rl d G eo rocks!!! by shahil sucks big tim e"); int i = 0, j = 0; while(ptr[j]!='\0') { if(ptr[j] == ' ' ) { j++; ptr[i] = ptr[j]; } else { i++; j++; ptr[i] = ptr[j]; } } printf("\noutput-%s\n",ptr); return 0; } 

s foi extremamente útil, eu queria dizer que estava feliz que este post estava disponível e mostrar o que eu era capaz de fazer com os exemplos. Eu precisei tokenizar uma string maior, e então pegar a (s) substring (s) e encontrar a última – então eu poderia remover uma nova linha da chamada fgets () e também remover o espaço em branco da frente daquela token – então eu poderia Compare-o facilmente com uma string estática. O primeiro exemplo no post acima me levou até lá, então obrigada. Aqui está como eu usei as amostras de código e a saída que obtive.

 int _tmain(int argc, _TCHAR* argv[]) { FILE * fp; // test file char currDBSStatstr[100] = {"/0"}; char *beg; char *end; char *str1; char str[] = "Initializing DBS Configuration"; fp = fopen("file2-1.txt","r"); if (fp != NULL) { printf("File exists.\n"); fgets(currDBSStatstr, sizeof(currDBSStatstr), fp); } else { printf("Error.\n"); exit(2); } //print string printf("String: %s\n", currDBSStatstr); //extract first string str1 = strtok(currDBSStatstr, ":-"); //print first token printf("%s\n", str1); //get more tokens in sequence while(1) { //extract more tokens in sequence str1 = strtok(NULL, ":-"); //check to see if done if (str1 == NULL) { printf("Tokenizing Done.\n"); exit(0); } //print string after tokenizing Done printf("%s\n", str1); end = str1 + strlen(str1) - 1; while((end > str1) && (*end == '\n')) { end--; *(end+1) = 0; beg = str1; while(isspace(*str1)) str1++; } printf("%s\n", str1); if (strcmp(str, str1) == 0) printf("Strings are equal.\n"); } return 0; 

}

Saída

O arquivo existe.

String: Estado do DBS: Inicialização do DBS – Inicializando a Configuração do DBS

Estado DBS

Inicialização do DBS

Inicialização do DBS

Inicializando a Configuração do DBS

Inicializando a Configuração do DBS

Cordas são iguais.

Tokenizing Feito.

Se você estiver usando glib , então você pode usar g_strstrip

Apenas para manter esse crescimento, mais uma opção com uma string modificável:

 void trimString(char *string) { size_t i = 0, j = strlen(string); while (j > 0 && isspace((unsigned char)string[j - 1])) string[--j] = '\0'; while (isspace((unsigned char)string[i])) i++; if (i > 0) memmove(string, string + i, j - i + 1); } 

Eu sei que tem muitas respostas, mas eu postei minha resposta aqui para ver se minha solução é boa o suficiente.

 // Trims leading whitespace chars in left `str`, then copy at almost `n - 1` chars // into the `out` buffer in which copying might stop when the first '\0' occurs, // and finally append '\0' to the position of the last non-trailing whitespace char. // Reture the length the trimed string which '\0' is not count in like strlen(). size_t trim(char *out, size_t n, const char *str) { // do nothing if(n == 0) return 0; // ptr stop at the first non-leading space char while(isspace(*str)) str++; if(*str == '\0') { out[0] = '\0'; return 0; } size_t i = 0; // copy char to out until '\0' or i == n - 1 for(i = 0; i < n - 1 && *str != '\0'; i++){ out[i] = *str++; } // deal with the trailing space while(isspace(out[--i])); out[++i] = '\0'; return i; } 

Pessoalmente, eu mudaria o meu próprio. Você pode usar strtok, mas precisa tomar cuidado ao fazer isso (particularmente se estiver removendo os caracteres iniciais) que sabe qual é a memory.

Livrar-se de espaços à direita é fácil e bastante seguro, já que você pode colocar 0 no canto superior do último espaço, contando a partir do final. Livrar-se dos espaços principais significa movimentar as coisas. Se você quiser fazê-lo no lugar (provavelmente sensato), você pode continuar mudando tudo de volta um personagem até que não haja espaço na liderança. Ou, para ser mais eficiente, você pode encontrar o índice do primeiro caractere não espacial e mudar tudo de volta nesse número. Ou, você poderia apenas usar um ponteiro para o primeiro caractere não-espacial (mas você precisa ser cuidadoso da mesma forma que faz com strtok).

Não tenho certeza do que você considera “indolor”.

C cordas são muito dolorosas. Podemos encontrar a primeira posição do caracter não-whitespace trivialmente:

 while (isspace (* p)) p ++;

Podemos encontrar a última posição de personagem que não é espaço em branco com dois movimentos triviais semelhantes:

 while (* q) q ++;
 fazer {q--;  } while (isspace (* q));

(Eu poupei você da dor de usar os operadores * e ++ ao mesmo tempo.)

A questão agora é o que você faz com isso? O tipo de dado em questão não é realmente uma String abstrata robusta e grande que seja fácil de se pensar, mas sim muito pouco mais que uma matriz de bytes de armazenamento. Na falta de um tipo de dados robusto, é impossível escrever uma function que faça o mesmo que a function chomp de PHperytonby. O que essa function em C retornaria?

Um pouco atrasado para o jogo, mas vou jogar minhas rotinas na briga. Eles provavelmente não são os mais eficientes, mas eu acredito que eles estão corretos e são simples (com rtrim() empurrando o envelope de complexidade):

 #include  #include  /* Public domain implementations of in-place string trim functions Michael Burr michael.burr@nth-element.com 2010 */ char* ltrim(char* s) { char* newstart = s; while (isspace( *newstart)) { ++newstart; } // newstart points to first non-whitespace char (which might be '\0') memmove( s, newstart, strlen( newstart) + 1); // don't forget to move the '\0' terminator return s; } char* rtrim( char* s) { char* end = s + strlen( s); // find the last non-whitespace character while ((end != s) && isspace( *(end-1))) { --end; } // at this point either (end == s) and s is either empty or all whitespace // so it needs to be made empty, or // end points just past the last non-whitespace character (it might point // at the '\0' terminator, in which case there's no problem writing // another there). *end = '\0'; return s; } char* trim( char* s) { return rtrim( ltrim( s)); } 

A maioria das respostas até agora faz um dos seguintes:

  1. Backtrack no final da string (ou seja, encontrar o final da string e, em seguida, procurar para trás até que um caractere não-espaço seja encontrado) ou
  2. Chame strlen() primeiro, fazendo uma segunda passagem por toda a string.

Esta versão faz apenas uma passagem e não recua. Portanto, ele pode ter um desempenho melhor do que os outros, embora apenas se for comum ter centenas de espaços à direita (o que não é incomum quando se lida com a saída de uma consulta SQL).

 static char const WHITESPACE[] = " \t\n\r"; static void get_trim_bounds(char const *s, char const **firstWord, char const **trailingSpace) { char const *lastWord; *firstWord = lastWord = s + strspn(s, WHITESPACE); do { *trailingSpace = lastWord + strcspn(lastWord, WHITESPACE); lastWord = *trailingSpace + strspn(*trailingSpace, WHITESPACE); } while (*lastWord != '\0'); } char *copy_trim(char const *s) { char const *firstWord, *trailingSpace; char *result; size_t newLength; get_trim_bounds(s, &firstWord, &trailingSpace); newLength = trailingSpace - firstWord; result = malloc(newLength + 1); memcpy(result, firstWord, newLength); result[newLength] = '\0'; return result; } void inplace_trim(char *s) { char const *firstWord, *trailingSpace; size_t newLength; get_trim_bounds(s, &firstWord, &trailingSpace); newLength = trailingSpace - firstWord; memmove(s, firstWord, newLength); s[newLength] = '\0'; } 

Esta é a implementação mais curta possível que eu possa imaginar:

 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 } 

These functions will modify the original buffer, so if dynamically allocated, the original pointer can be freed.

 #include  void rstrip(char *string) { int l; if (!string) return; l = strlen(string) - 1; while (isspace(string[l]) && l >= 0) string[l--] = 0; } void lstrip(char *string) { int i, l; if (!string) return; l = strlen(string); while (isspace(string[(i = 0)])) while(i++ < l) string[i-1] = string[i]; } void strip(char *string) { lstrip(string); rstrip(string); } 

What do you think about using StrTrim function defined in header Shlwapi.h.? It is straight forward rather defining on your own.
Details can be found on:
http://msdn.microsoft.com/en-us/library/windows/desktop/bb773454(v=vs.85).aspx

Se você tem
char ausCaptain[]="GeorgeBailey ";
StrTrim(ausCaptain," ");
This will give ausCaptain as "GeorgeBailey" not "GeorgeBailey " .

To trim my strings from the both sides I use the oldie but the gooody 😉 It can trim anything with ascii less than a space, meaning that the control chars will be trimmed also !

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

I’m only including code because the code posted so far seems suboptimal (and I don’t have the rep to comment yet.)

 void inplace_trim(char* s) { int start, end = strlen(s); for (start = 0; isspace(s[start]); ++start) {} if (s[start]) { while (end > 0 && isspace(s[end-1])) --end; memmove(s, &s[start], end - start); } s[end - start] = '\0'; } char* copy_trim(const char* s) { int start, end; for (start = 0; isspace(s[start]); ++start) {} for (end = strlen(s); end > 0 && isspace(s[end-1]); --end) {} return strndup(s + start, end - start); } 

strndup() is a GNU extension. If you don’t have it or something equivalent, roll your own. Por exemplo:

 r = strdup(s + start); r[end-start] = '\0'; 

Here i use the dynamic memory allocation to trim the input string to the function trimStr. First, we find how many non-empty characters exist in the input string. Then, we allocate a character array with that size and taking care of the null terminated character. When we use this function, we need to free the memory inside of main function.

 #include #include char *trimStr(char *str){ char *tmp = str; printf("input string %s\n",str); int nc = 0; while(*tmp!='\0'){ if (*tmp != ' '){ nc++; } tmp++; } printf("total nonempty characters are %d\n",nc); char *trim = NULL; trim = malloc(sizeof(char)*(nc+1)); if (trim == NULL) return NULL; tmp = str; int ne = 0; while(*tmp!='\0'){ if (*tmp != ' '){ trim[ne] = *tmp; ne++; } tmp++; } trim[nc] = '\0'; printf("trimmed string is %s\n",trim); return trim; } int main(void){ char str[] = " s ta ck ove r fl ow "; char *trim = trimStr(str); if (trim != NULL )free(trim); return 0; } 

Aqui está como eu faço isso. It trims the string in place, so no worry about deallocating a returned string or losing the pointer to an allocated string. It may not be the shortest answer possible, but it should be clear to most readers.

 #include  #include  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'; } } 
 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; } 

Here is a function to do what you want. It should take care of degenerate cases where the string is all whitespace. You must pass in an output buffer and the length of the buffer, which means that you have to pass in a buffer that you allocate.

 void str_trim(char *output, const char *text, int32 max_len) { int32 i, j, length; length = strlen(text); if (max_len < 0) { max_len = length + 1; } for (i=0; i=0; j--) { if ( (text[j] != ' ') && (text[j] != '\t') && (text[j] != '\n') && (text[j] != '\r')) { break; } } length = j + 1 - i; strncpy(output, text + i, length); output[length] = 0; } 

The if statements in the loops can probably be replaced with isspace(text[i]) or isspace(text[j]) to make the lines a little easier to read. I think that I had them set this way because there were some characters that I didn’t want to test for, but it looks like I’m covering all whitespace now 🙂