isspace - trim c#
¿Cómo recorto el espacio en blanco inicial/final de una manera estándar? (30)
Aquí está mi intento de una función de recorte en el lugar simple pero correcta.
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.
}
¿Existe un método limpio, preferiblemente estándar, para recortar los espacios en blanco iniciales y finales de una cuerda en C? Me gustaría ganar, pero creo que este es un problema común con una solución igualmente común.
Aquí está mi mini biblioteca C para recortar a la izquierda, a la derecha, a ambas, todas, en su lugar y separadas, y recortar un conjunto de caracteres especificados (o espacio en blanco de forma predeterminada).
contenido 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
contenidos de strlib.c:
#include <strlib.h>
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); }
La rutina principal lo hace todo. Ajusta en su lugar si src == dst , de lo contrario, funciona como las rutinas strcpy
. Recorta un conjunto de caracteres especificados en el delimitador de cadena, o espacio en blanco si es nulo. Ajusta a la izquierda, a la derecha, a ambos y a todos (como tr). No hay mucho para eso, e itera sobre la cadena solo una vez. Algunas personas pueden quejarse de que el ajuste derecho comienza a la izquierda, sin embargo, no se necesita ningún ajuste que comience a la izquierda de todos modos. (De una manera u otra, tiene que llegar al final de la cadena para los ajustes correctos, por lo que también puede hacer el trabajo sobre la marcha). Puede haber argumentos que se deben hacer sobre la canalización y los tamaños de la memoria caché, y quién sabe. . Dado que la solución funciona de izquierda a derecha y se repite solo una vez, también se puede expandir para trabajar en las transmisiones. Limitaciones: no funciona en cadenas Unicode .
Aquí hay una solución similar a la rutina de modificación in situ de @ adam-rosenfields, pero sin recurrir innecesariamente a strlen (). Al igual que @jkramer, la cadena se ajusta a la izquierda dentro del buffer para que pueda liberar el mismo puntero. No es óptimo para cadenas grandes ya que no usa memmove. Incluye los operadores ++ / - que menciona @ jfm3. Pruebas unitarias basadas en FCTX incluidas.
#include <ctype.h>
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[] = " a c"; trim(s); fct_chk_eq_str("a c", s); } // Leading
{ char s[] = "a "; trim(s); fct_chk_eq_str("a", s); } // Trailing
{ char s[] = "a c "; trim(s); fct_chk_eq_str("a c", s); } // Trailing
{ char s[] = " a "; trim(s); fct_chk_eq_str("a", s); } // Both
{ char s[] = " a c "; trim(s); fct_chk_eq_str("a c", s); } // Both
// Villemoes pointed out an edge case that corrupted memory. Thank you.
// http://.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://.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();
Aquí hay uno que cambia la cuerda a la primera posición de tu buffer. Es posible que desee este comportamiento para que, si asignó dinámicamente la cadena, aún pueda liberarlo en el mismo puntero que devuelve trim ():
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;
}
Prueba de corrección:
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;
}
El archivo fuente fue trim.c. Compilado con ''cc trim.c -o trim''.
Esta es la implementación más corta posible que puedo pensar:
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
}
Estas funciones modificarán el búfer original, por lo que si se asignan dinámicamente, se puede liberar el puntero original.
#include <string.h>
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);
}
La forma más fácil de omitir espacios principales en una cadena es, imho,
#include <stdio.h>
int main()
{
char *foo=" teststring ";
char *bar;
sscanf(foo,"%s",bar);
printf("String is >%s</n",bar);
return 0;
}
La mayoría de las respuestas hasta ahora hacen una de las siguientes:
- Retroceda al final de la cadena (es decir, busque el final de la cadena y luego busque hacia atrás hasta encontrar un carácter que no sea de espacio) o
- Llame a
strlen()
primero, haciendo un segundo pase a través de la cadena completa.
Esta versión solo hace una pasada y no retrocede. Por lo tanto, puede funcionar mejor que los demás, aunque solo si es común tener cientos de espacios finales (lo cual no es inusual cuando se trata del resultado de una 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'';
}
Mi solución. La cadena debe ser cambiable. La ventaja sobre algunas de las otras soluciones es que mueve la parte no espacial al principio para que pueda seguir usando el puntero anterior, en caso de que tenga que liberarlo () más 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 versión crea una copia de la cadena con strndup () en lugar de editarla en su lugar. strndup () requiere _GNU_SOURCE, por lo que tal vez necesites crear tu propio strndup () con malloc () y 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);
}
No estoy seguro de lo que consideras "sin dolor".
C cadenas son bastante dolorosas. Podemos encontrar la primera posición de personaje no blanco de forma trivial:
while (isspace(* p)) p++;
Podemos encontrar la última posición del personaje que no sea de espacio en blanco con dos movimientos triviales similares:
while (* q) q++; do { q--; } while (isspace(* q));
(Te evité el dolor de usar los operadores *
y ++
al mismo tiempo).
La pregunta ahora es ¿qué haces con esto? El tipo de datos a la mano no es realmente una String
abstracta grande y robusta en String
que sea fácil pensar, sino que en realidad apenas es más que una matriz de bytes de almacenamiento. Al carecer de un tipo de datos robusto, es imposible escribir una función que haga lo mismo que la función chomp
de PHperytonby. ¿Qué devolvería tal función en C?
No me gustó la mayoría de estas respuestas porque hicieron una o más de las siguientes ...
- Devolvió un puntero diferente dentro de la cadena del puntero original (una especie de dolor para hacer malabarismos con dos punteros diferentes a la misma cosa).
- Hizo uso gratuito de cosas como strlen () que pre-iteran toda la cadena.
- Usó funciones de lib específicas del sistema operativo no portátiles.
- Backscanned.
- Se usa la comparación con '''' en lugar de isspace () para que TAB / CR / LF se conserven.
- Memoria desperdiciada con grandes búfers estáticos.
- Ciclos perdidos con funciones de alto costo como sscanf / sprintf .
Aquí está mi versión:
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'';
}
Otro, con una línea haciendo el trabajo real:
#include <stdio.h>
int main()
{
const char *target = " haha ";
char buf[256];
sscanf(target, "%s", buf); // Trimming on both sides occurs here
printf("<%s>/n", buf);
}
Personalmente, yo haría mi propio. Puede usar strtok, pero debe tener cuidado al hacerlo (especialmente si está eliminando caracteres principales) para saber qué memoria es qué.
Deshacerse de los espacios finales es fácil y bastante seguro, ya que puede poner un 0 en la parte superior del último espacio, contando desde el final. Deshacerse de los espacios principales significa mover las cosas. Si quieres hacerlo en su lugar (probablemente sensato), puedes seguir cambiando todo un personaje hasta que no haya espacio principal. O bien, para ser más eficiente, podría encontrar el índice del primer carácter que no sea espacio, y cambiarlo todo por ese número. O bien, podría usar un puntero al primer carácter que no sea espacio (pero debe tener cuidado de la misma manera que lo hace con strtok).
Sé que hay muchas respuestas, pero publico mi respuesta aquí para ver si mi solución es lo suficientemente buena.
// 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;
}
Si puedes modificar la cadena:
// 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
*(end+1) = 0;
return str;
}
Si no puede modificar la cadena, puede usar básicamente el mismo 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;
}
Si usa glib
, puede usar g_strstrip
Solo para mantener esto creciendo, una opción más con una cadena modificable:
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);
}
Tarde a la fiesta de ajuste
caracteristicas:
1. Recorte el comienzo rápidamente, como en varias otras respuestas.
2. Después de ir al final, recorte el derecho con solo 1 prueba por ciclo. Like @ jfm3, pero funciona para una cadena de espacio en blanco)
3. Para evitar el comportamiento indefinido cuando char
es un char
firmado, use *s
para unsigned char
.
Manejo de caracteres "En todos los casos, el argumento es un
int
, cuyo valor debe ser representable como ununsigned char
o debe ser igual al valor del macroEOF
. Si el argumento tiene algún otro valor, el comportamiento no está definido". C11 §7.4 1
#include <ctype.h>
// 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;
}
Un poco tarde para el juego, pero lanzaré mis rutinas al combate. Probablemente no sean los más eficientes, pero creo que son correctos y son simples (con rtrim()
empujando la envolvente de la complejidad):
#include <ctype.h>
#include <string.h>
/*
Public domain implementations of in-place string trim functions
Michael Burr
[email protected]
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));
}
Use una biblioteca de cadenas , por ejemplo:
Ustr *s1 = USTR1(/7, " 12345 ");
ustr_sc_trim_cstr(&s1, " ");
assert(ustr_cmp_cstr_eq(s1, "12345"));
... como dices, este es un problema "común", sí, necesitas incluir un #include más o menos y no está incluido en libc pero no vas a inventar tu propio trabajo de hackeo almacenando punteros aleatorios y size_t''s de esa manera solo te lleva a desbordamientos de búfer.
s fue extremadamente útil, quería decir que estaba contento de que esta publicación estuviera disponible y de mostrar lo que pude hacer con los ejemplos. Necesitaba tokenizar una cadena más grande, y luego tomar la (s) subcadenas (s) y encontrar la última - para poder eliminar una nueva línea de la llamada de fgets (), y también eliminar el espacio en blanco del frente de esa ficha - para poder compararlo fácilmente con una cuerda estática. El primer ejemplo en la publicación anterior me llevó allí, así que gracias. Aquí es cómo utilicé las muestras de código y la salida que obtuve.
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;
}
Salida
El archivo existe.
Cadena: Estado de DBS: Inicio de DBS - Inicialización de la configuración de DBS
Estado de DBS
Inicio de DBS
Inicio de DBS
Inicializando la configuración de DBS
Inicializando la configuración de DBS
Las cadenas son iguales.
Tokenizing Hecho.
C++ STL style
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);
}
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<stdio.h>
#include<stdlib.h>
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 o w ";
char *trim = trimStr(str);
if (trim != NULL )free(trim);
return 0;
}
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<length; i++) {
if ( (text[i] != '' '') && (text[i] != ''/t'') && (text[i] != ''/n'') && (text[i] != ''/r'')) {
break;
}
}
if (i == length) {
// handle lines that are all whitespace
output[0] = 0;
return;
}
for (j=length-1; j>=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 :-)
Here is what I disclosed regarding the question in Linux kernel code:
/**
* skip_spaces - Removes leading whitespace from @s.
* @s: The string to be stripped.
*
* Returns a pointer to the first non-whitespace character in @s.
*/
char *skip_spaces(const char *str)
{
while (isspace(*str))
++str;
return (char *)str;
}
/**
* strim - Removes leading and trailing whitespace from @s.
* @s: The string to be stripped.
*
* Note that the first trailing whitespace is replaced with a %NUL-terminator
* in the given string @s. Returns a pointer to the first non-whitespace
* character in @s.
*/
char *strim(char *s)
{
size_t size;
char *end;
size = strlen(s);
if (!size)
return s;
end = s + size - 1;
while (end >= s && isspace(*end))
end--;
*(end + 1) = ''/0'';
return skip_spaces(s);
}
It is supposed to be bug free due to the origin ;-)
Mine one piece is closer to KISS principle I guess:
/**
* trim spaces
**/
char * trim_inplace(char * s, int len)
{
// trim leading
while (len && isspace(s[0]))
{
s++; len--;
}
// trim trailing
while (len && isspace(s[len - 1]))
{
s[len - 1] = 0; len--;
}
return s;
}
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 ejemplo:
r = strdup(s + start);
r[end-start] = ''/0'';
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;
}
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
Si usted tiene
char ausCaptain[]="GeorgeBailey ";
StrTrim(ausCaptain," ");
This will give ausCaptain
as "GeorgeBailey"
not "GeorgeBailey "
.
#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 b i g 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;
}
#include<stdio.h>
#include<ctype.h>
main()
{
char sent[10]={'' '','' '','' '',''s'',''t'',''a'',''r'',''s'','' '','' ''};
int i,j=0;
char rec[10];
for(i=0;i<=10;i++)
{
if(!isspace(sent[i]))
{
rec[j]=sent[i];
j++;
}
}
printf("/n%s/n",rec);
}