graficas - strlen
Recortar una cadena en C (15)
Esta pregunta ya tiene una respuesta aquí:
Brevemente:
Busco el equivalente de String.Trim
en C de .NET utilizando C api de Win32 y estándar (compilando con MSVC2008, así que tengo acceso a todas las cosas de C ++ si es necesario, pero solo estoy tratando de recortar un char*
).
Dado que hay strchr
, strchr
y todo tipo de otras funciones de cadena, seguramente debería haber una función de recorte, o una que se pueda reutilizar ...
Gracias
Aquí está mi implementación, comportándose como las funciones de cadena incorporadas en libc (es decir, espera una cadena de caracteres, la modifica y la devuelve al llamador).
Recorta espacios iniciales y desplaza los caracteres restantes hacia la izquierda, ya que analiza la cadena de izquierda a derecha. Luego marca un nuevo final de cadena y comienza a analizarlo hacia atrás, reemplazando los espacios finales con ''/ 0''s hasta que encuentra un carácter no espacial o el comienzo de la cadena. Creo que esas son las iteraciones mínimas posibles para esta tarea en particular.
// ----------------------------------------------------------------------------
// 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;
}
Esto me hizo querer escribir el mío, no me gustaron los que me proporcionaron. Me parece que debería haber 3 funciones.
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));
}
Lo más fácil de hacer es un simple bucle. Voy a suponer que quieres que la cuerda recortada vuelva a su lugar.
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 */
}
Esto también elimina los espacios en blanco incrustados, si String.Trim no necesita un poco más de lógica.
Me gusta cuando el valor de retorno siempre es igual al argumento. De esta forma, si la matriz de cadenas ha sido asignada con malloc()
, puede volver a ser free()
manera segura.
/* 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;
}
No es la mejor manera, pero funciona
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;
}
No hay una función de biblioteca estándar para hacer esto, pero no es demasiado difícil de implementar. Existe una pregunta existente sobre SO sobre cómo hacer esto que fue respondida con el código fuente.
Puede usar la función estándar isspace() en ctype.h para lograr esto. Simplemente compare los caracteres iniciales y finales de su matriz de caracteres hasta que ambos extremos ya no tengan espacios.
Los "espacios" incluyen:
'''' (0x20) espacio (SPC)
Pestaña horizontal ''/ t'' (0x09) (TAB)
''/ n'' (0x0a) nueva línea (LF)
Pestaña vertical ''/ v'' (0x0b) (VT)
''/ f'' (0x0c) feed (FF)
''/ r'' (0x0d) retorno de carro (CR)
aunque no hay ninguna función que haga todo el trabajo por usted, tendrá que rodar su propia solución para comparar cada lado de la matriz de caracteres dada repetidamente hasta que no queden espacios.
Editar:
Como tiene acceso a C ++, Boost tiene una implementación de recorte esperando que haga su vida mucho más fácil.
Qué tal esto ... Solo requiere una iteración sobre la cadena (no usa strlen, que itera sobre la cadena). Cuando la función retorna, obtienes un puntero al comienzo de la cadena recortada que termina en nulo. La cuerda se recorta de los espacios de la izquierda (hasta que se encuentre el primer carácter). La cadena también se recorta de todos los espacios finales después del último carácter no espacial.
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;
}
}
Sorprendido de ver tales implementaciones. Suelo recortar así:
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;
}
Es rápido y confiable, me sirve muchos años.
#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));
}
Salida:
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
/* 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);
}
/* 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;
}
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);
}
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++;
}
}
}
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);
}