Cで先頭と末尾のスペースを削除するための最良のアプローチは何ですか?
16 に答える
Linuxカーネルがstrstrip()と呼ばれるトリミングを行う方法は次のとおりです。
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;
}
その基本的には、前のポスターが言ったことをより適切にフォーマットし、エラーチェックしたバージョンです。
この質問は宿題の質問のように見えるので、斜めに答えます: isspace(3) と strlen(3) のマニュアルページを調べて、ポインター演算を使用してください。また、目前の問題によっては、結果のスペースを保持するために malloc(3) が必要になる場合があります。
C 文字列の表現には末尾の 0 バイトが含まれていることを忘れないでください。これは多くの場合、'\0' と書かれますが、これは文字列の長さの一部としてカウントされません。
isspace を使用したバージョンは次のとおりです。
char * trim(char *c) {
char * e = c + strlen(c) - 1;
while(*c && isspace(*c)) c++;
while(e > c && isspace(*e)) *e-- = '\0';
return c;
}
これは完全に適切に行うことができます。
void stripLeadingAndTrailingSpaces(char* string){
assert(string);
/* First remove leading spaces */
const char* firstNonSpace = string;
while(*firstNonSpace != '\0' && isspace(*firstNonSpace))
{
++firstNonSpace;
}
size_t len = strlen(firstNonSpace)+1;
memmove(string, firstNonSpace, len);
/* Now remove trailing spaces */
char* endOfString = string + len;
while(string < endOfString && isspace(*endOfString))
{
--endOfString ;
}
*endOfString = '\0';
}
char *strstrip(char *s)
{
char *end;
while ( (*s) && isspace( *s))
s++;
if(!( *s) )
return s;
end = s;
while( ! *end)
end++;
end--;
while (end ! = s && isspace( *end))
end--;
*(end + 1) = '\0';
return s;
}
これは基本的に、より最適化されたコードです (速度とコードサイズの点で)。
メモリ空間を保持する必要がある場合は、
void strstrip(char *s)
{
char *start;
char *end;
start = s;
while ( (*start) && isspace( *start))
start++;
if(!( *start) )
{
*s='\0';
return ;
}
end = start;
while( ! *end)
end++;
end--;
while (end ! = start && isspace( *end))
end--;
*(end + 1) = '\0';
memmove(s, start, end-start+1);
return;
}
以下は、lakshmanaraj の最初の関数のより簡潔で安全なバージョンです。
#include <ctype.h>
char *mytrim(char *s)
{
if(s) { /* Don't forget to check for NULL! */
while(*s && isspace(*s))
++s;
if(*s) {
register char *p = s;
while(*p)
++p;
do {
--p;
} while((p != s) && isspace(*p));
*(p + 1) = '\0';
}
}
return(s);
}
上記の別の投稿の改良。
void strstrip( char *s )
{
char *start;
char *end;
// Exit if param is NULL pointer
if (s == NULL)
return;
// Skip over leading whitespace
start = s;
while ((*start) && isspace(*start))
start++;
// Is string just whitespace?
if (!(*start))
{
*s = 0x00; // Truncate entire string
return;
}
// Find end of string
end = start;
while (*end)
end++;
// Step back from NUL
end--;
// Step backward until first non-whitespace
while ((end != start) && isspace(*end))
end--;
// Chop off trailing whitespace
*(end + 1) = 0x00;
// If had leading whitespace, then move entire string back to beginning
if (s != start)
memmove(s, start, end-start+1);
return;
}
末尾の空白には strtok を使用します。delimiter = " " を設定し、実行時に delimiter バイトを破棄して char * をトークンに返します
char *x;
char *y = "somestring ";
x = strtok(y," ");
結果 x = 「somestring」ではなく「somestring」へのポインター
int i = strlen(s) - 1;
while (isspace(s[i]))
s[i--] = '\0';
while (isspace(*s))
s++;
狂ったように文字列を台無しにすることを気にしない限り、そしてメモリリークを気にしない限り、それは問題を処理するはずです!
インプレースで実行できるはずです。空白を削除しても、文字列が大きくなることはありません。最初に文字列の長さをチェックしなくてもできるかもしれませんが、そうするのは不必要に「賢い」かもしれません。memmove()
@Norman Ramseyが言及したものに加えて、関数を調べる必要があります。
Linux/Windows を使用していて、ライブラリ glib がプログラムにリンクされている場合は、ルーチンを使用できますg_strstrip()
。
編集: zString ライブラリの最新バージョンに基づいてコードを更新しました。
このコードはライブラリに依存せず、ポインタ演算と整数のみに依存しています。トリム、左トリム、右トリムの 3 つの機能があります。(これらすべての関数をzString ライブラリに追加する必要があります:))
char *zstring_trim(char *s)
先頭と末尾の空白を削除しますchar *zstring_ltrim(char *s)
先頭の空白を削除しますchar *zstring_ltrim(char *s)
末尾の空白を削除します
これらの関数はすべて元の文字列を変更します
/* trim */
char *zstring_trim(char *str){
char *src=str; /* save the original pointer */
char *dst=str; /* result */
char c;
int is_space=0;
int in_word=0; /* word boundary logical check */
int index=0; /* index of the last non-space char*/
/* validate input */
if (!str)
return str;
while ((c=*src)){
is_space=0;
if (c=='\t' || c=='\v' || c=='\f' || c=='\n' || c=='\r' || c==' ')
is_space=1;
if(is_space == 0){
/* Found a word */
in_word = 1;
*dst++ = *src++; /* make the assignment first
* then increment
*/
} else if (is_space==1 && in_word==0) {
/* Already going through a series of white-spaces */
in_word=0;
++src;
} else if (is_space==1 && in_word==1) {
/* End of a word, dont mind copy white spaces here */
in_word=0;
*dst++ = *src++;
index = (dst-str)-1; /* location of the last char */
}
}
/* terminate the string */
*(str+index)='\0';
return str;
}
/* right trim */
char *zstring_rtrim(char *str){
char *src=str; /* save the original pointer */
char *dst=str; /* result */
char c;
int is_space=0;
int index=0; /* index of the last non-space char */
/* validate input */
if (!str)
return str;
/* copy the string */
while(*src){
*dst++ = *src++;
c = *src;
if (c=='\t' || c=='\v' || c=='\f' || c=='\n' || c=='\r' || c==' ')
is_space=1;
else
is_space=0;
if (is_space==0 && *src)
index = (src-str)+1;
}
/* terminate the string */
*(str+index)='\0';
return str;
}
/* left trim */
char *zstring_ltrim(char *str){
char *src=str; /* save the original pointer */
char *dst=str; /* result */
char c;
int index=0; /* index of the first non-space char */
/* validate input */
if (!str)
return str;
/* skip leading white-spaces */
while((c=*src)){
if (c=='\t' || c=='\v' || c=='\f' || c=='\n' || c=='\r' || c==' '){
++src;
++index;
} else
break;
}
/* copy rest of the string */
while(*src)
*dst++ = *src++;
/* terminate the string */
*(src-index)='\0';
return str;
}
char *strip(char *string)
{
char *start = string;
while(isblank(*start)) start++;
int end = strlen(start);
if(start != string) {
memmove(string, start, end);
string[end] = '\0';
}
while(isblank(*(string+end-1))) end--;
string[end] = '\0';
return string;
}
fpsgamer からの相関アルゴリズム (ISO C90 も有効):
void trimWhitespace(char *string) {
const char* firstNonSpace = string;
char* endOfString;
size_t len;
if (string[0] == '\0') {
return;
}
/* First remove leading spaces */
while(*firstNonSpace != '\0' && isspace(*firstNonSpace)) {
++firstNonSpace;
}
len = strlen(firstNonSpace) + 1;
memmove(string, firstNonSpace, len);
/* Now remove trailing spaces */
endOfString = string + len;
while(string < endOfString && (isspace(*endOfString) || *endOfString == '\0')) {
--endOfString ;
}
*(endOfString + 1) = '\0';
}