La función strip () de Python de Mimic en C

Comencé en un pequeño proyecto de juguetes en C últimamente y me he estado rascando la cabeza sobre la mejor manera de imitar la funcionalidad de tira () que forma parte de los objetos de cadena de python.

La lectura de fscanf o sscanf indica que la cadena se procesa hasta el primer espacio en blanco que se encuentra.

fgets tampoco ayuda, ya que todavía tengo nuevas líneas por ahí. Intenté con un strchr () para buscar un espacio en blanco y establecer el puntero devuelto a ‘\ 0’ explícitamente, pero eso no parece funcionar.

No hay una implementación estándar de C para una función strip () o trim (). Dicho esto, aquí está el que está incluido en el kernel de Linux:

char *strstrip(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'; while (*s && isspace(*s)) s++; return s; } 

El método de strip cadenas de Python elimina tanto el espacio en blanco al final como el anterior. Las dos mitades del problema son muy diferentes cuando se trabaja en una “cadena” C (matriz de char, \ 0 terminado).

Para espacios en blanco al final: establezca un puntero (o índice equivalente) a la existente al final \ 0. Continúe disminuyendo el puntero hasta que toque el comienzo de la cadena o cualquier carácter que no sea blanco; establezca el \ 0 a la derecha después de este punto de escaneo de terminación hacia atrás.

Para espacios en blanco iniciales: establezca un puntero (o índice equivalente) al inicio de la cadena; siga incrementando el puntero hasta que toque un carácter que no sea blanco (posiblemente el final \ 0); memmove the rest-of-string para que el primer no blanco vaya al inicio de la cadena (y de manera similar para todo lo que sigue).

Parece que quieres algo como recortar, una búsqueda rápida en Google conduce a este hilo del foro.

Si desea eliminar, en su lugar , la nueva línea final de una línea, puede usar este fragmento de código:

 size_t s = strlen(buf); if (s && (buf[s-1] == '\n')) buf[--s] = 0; 

Para imitar fielmente el str.strip([chars]) Python (la forma en que interpreté su funcionamiento), debe asignar espacio para una nueva cadena, completar la nueva cadena y devolverla. Después de eso, cuando ya no necesite la cadena eliminada, necesitará liberar la memoria que solía no tener pérdidas de memoria.

O puede usar los punteros C, modificar la cadena inicial y lograr un resultado similar.
Supongamos que su cadena inicial es "____forty two____\n" y desea eliminar todos los guiones bajos y el ‘\ n’

 ____forty two___\n ^ ptr 

Si cambia ptr a ‘f’ y reemplaza el primer ‘_’ después de two con un '\0' el resultado es el mismo que "____forty two____\n".strip("_\n"); Python "____forty two____\n".strip("_\n");

 ____forty two\0___\n ^ptr 

Una vez más, esto no es lo mismo que Python. La cadena se modifica en su lugar, no hay una segunda cadena y no puede revertir los cambios (la cadena original se pierde).

Escribí el código C para implementar esta función. También escribí algunas pruebas triviales para asegurarme de que mi función hace cosas sensatas.

Esta función escribe en un búfer que proporciona, y nunca debe escribir más allá del final del búfer, por lo que no debe ser propensa a problemas de seguridad de desbordamiento de búfer.

Nota: solo Test () usa stdio.h, así que si solo necesita la función, solo necesita incluir ctype.h (para isspace ()) y string.h (para strlen ()).

 // strstrip.c -- implement white space stripping for a string in C // // This code is released into the public domain. // // You may use it for any purpose whatsoever, and you don't need to advertise // where you got it, but you aren't allowed to sue me for giving you free // code; all the risk of using this is yours. #include  #include  #include  // strstrip() -- strip leading and trailing white space from a string // // Copies from sIn to sOut, writing at most lenOut characters. // // Returns number of characters in returned string, or -1 on an error. // If you get -1 back, then nothing was written to sOut at all. int strstrip(char *sOut, unsigned int lenOut, char const *sIn) { char const *pStart, *pEnd; unsigned int len; char *pOut; // if there is no room for any output, or a null pointer, return error! if (0 == lenOut || !sIn || !sOut) return -1; pStart = sIn; pEnd = sIn + strlen(sIn) - 1; // skip any leading whitespace while (*pStart && isspace(*pStart)) ++pStart; // skip any trailing whitespace while (pEnd >= sIn && isspace(*pEnd)) --pEnd; pOut = sOut; len = 0; // copy into output buffer while (pStart <= pEnd && len < lenOut - 1) { *pOut++ = *pStart++; ++len; } // ensure output buffer is properly terminated *pOut = '\0'; return len; } void Test(const char *s) { int len; char buf[1024]; len = strstrip(buf, sizeof(buf), s); if (!s) s = "**null**"; // don't ask printf to print a null string if (-1 == len) *buf = '\0'; // don't ask printf to print garbage from buf printf("Input: \"%s\" Result: \"%s\" (%d chars)\n", s, buf, len); } main() { Test(NULL); Test(""); Test(" "); Test(" "); Test("x"); Test(" x"); Test(" x "); Test(" xyz "); Test("xyz"); } 

Hice una pregunta muy similar hace mucho tiempo. Ver aqui Hay formas de hacerlo tanto en el lugar como con una nueva copia.