Ваш код часто становится более читабельным, если вы разумно используете стандартные библиотечные функции - например, isspace ()
и memmove ()
особенно полезны здесь:
#include <string.h>
#include <ctype.h>
void trim(char *str)
{
char *start, *end;
/* Find first non-whitespace */
for (start = str; *start; start++)
{
if (!isspace((unsigned char)start[0]))
break;
}
/* Find start of last all-whitespace */
for (end = start + strlen(start); end > start + 1; end--)
{
if (!isspace((unsigned char)end[-1]))
break;
}
*end = 0; /* Truncate last whitespace */
/* Shift from "start" to the beginning of the string */
if (start > str)
memmove(str, start, (end - start) + 1);
}
Есть некоторые проблемы: lastc
можно использовать без инициализации. И вы можете использовать, например, цикл for вместо цикла while. Кроме того, функции обрезки / полосы обычно заменяют пробелы, табуляции и новые строки.
Вот решение с использованием указателей, которое я написал довольно давно:
void trim(char *str)
{
char *ptr = str;
while(*ptr == ' ' || *ptr == '\t' || *ptr == '\r' || *ptr == '\n') ++ptr;
char *end = ptr;
while(*end) ++end;
if(end > ptr)
{
for(--end; end >= ptr && (*end == ' ' || *end == '\t' || *end == '\r' || *end == '\n'); --end);
}
memmove(str, ptr, end-ptr);
str[end-ptr] = 0;
}
Я не знаю насчет чистоты, но мне трудно уследить за этим. Если бы мне нужно было это сделать, я бы сначала подумал об этом в двух фазах:
Затем я мог бы более внимательно рассмотреть однопроходное решение, которое вы, кажется, пытаетесь реализовать, но только в том случае, если возникла проблема со скоростью.
Кстати, вы, вероятно, захотите использовать isspace ()
, а не проверять только наличие пробела.
С этим кодом есть несколько проблем. Он только проверяет наличие места. Не вкладки или символы новой строки. Вы копируете всю непробельную часть строки. И вы используете lastc перед его настройкой.
Вот альтернативная версия (скомпилирована, но не протестирована):
char *trim(char *string)
{
char *start;
int len = strlen(string);
int i;
/* Find the first non whitespace char */
for (i = 0; i < len; i++) {
if (! isspace(string[i])) {
break;
}
}
if (i == len) {
/* string is all whitespace */
return NULL;
}
start = &string[i];
/* Remove trailing white space */
for (i = len; i > 0; i--) {
if (isspace(string[i])) {
string[i] = '\0';
} else {
break;
}
}
return start;
}
Вместо сравнения символа с пробелом '' я бы использовал функцию "isspace", которая, как мне кажется, определена в ctype.h.
Вот мое решение.
Короткое, простое, чистое, прокомментированное и слегка протестированное.
Оно использует функцию классификации "isspace", поэтому вы можете легко изменить определение "белого пространства" для обрезки.
void trim(char* String)
{
int dest;
int src=0;
int len = strlen(String);
// Advance src to the first non-whitespace character.
while(isspace(String[src])) src++;
// Copy the string to the "front" of the buffer
for(dest=0; src<len; dest++, src++)
{
String[dest] = String[src];
}
// Working backwards, set all trailing spaces to NULL.
for(dest=len-1; isspace(String[dest]); --dest)
{
String[dest] = '\0';
}
}
Он не выглядит чистым. Предполагая, что первый символ - это пробел, вы используете lastc
с неопределенным значением. Вы оставляете один пробел в конце (если в конце есть пробел, при его нажатии c
будет пробелом, а lastc
- нет).
Вы также не завершаете строку. Предполагая, что вы исправите проблему неинициализированного lastc
, вы преобразуете «abc» в «abcbc», поскольку он ни в коем случае не сокращается.
Код также сокращает несколько пробелов внутри строки. Это не то, что вы описали; это желаемое поведение?