Cの文字列からスペースを削除する最も簡単で効率的な方法は何ですか?
最も簡単で最も効率的なのは、通常一緒に行かないことです...
考えられる解決策は次のとおりです。
void remove_spaces(char* s) {
const char* d = s;
do {
while (*d == ' ') {
++d;
}
} while (*s++ = *d++);
}
これは非常にコンパクトですが、完全に正しいバージョンです。
do while(isspace(*s)) s++; while(*d++ = *s++);
そして、ここでは、私の娯楽のために、完全に正しいわけではなく、コメンターを怒らせるコードゴルフバージョンがあります。
いくつかの未定義の動作を危険にさらすことができ、空の文字列を持たない場合は、本文を削除できます。
while(*(d+=!isspace(*s++)) = *s);
ちなみに、スペースで言うと、単にスペース文字を意味する場合:
while(*(d+=*s++!=' ')=*s);
本番環境では使用しないでください:)
投稿された回答からわかるように、これは驚くほど簡単な作業ではありません。このようなタスクに直面したとき、多くのプログラマーは、思い付く可能性のある最もあいまいなスニペットを作成するために、常識を窓から外すことを選択しているように思われます。
考慮事項:
' '
。私がすること:
void remove_spaces (char* restrict str_trimmed, const char* restrict str_untrimmed)
{
while (*str_untrimmed != '\0')
{
if(!isspace(*str_untrimmed))
{
*str_trimmed = *str_untrimmed;
str_trimmed++;
}
str_untrimmed++;
}
*str_trimmed = '\0';
}
このコードでは、ソース文字列「str_untrimmed」はそのまま残ります。これは、適切なconstの正確性を使用することで保証されます。ソース文字列にnull終了のみが含まれている場合、クラッシュしません。宛先文字列は常にnullで終了します。
メモリの割り当ては呼び出し元に任されています。アルゴリズムは、意図された作業を行うことにのみ焦点を当てるべきです。すべての空白が削除されます。
コードには微妙なトリックはありません。 1行で可能な限り多くの演算子を絞り込もうとはしません。 [〜#〜] ioccc [〜#〜] の非常に貧弱な候補になります。それでも、より曖昧なワンライナーバージョンとほぼ同じマシンコードが生成されます。
ただし、何かをコピーするときは、両方のポインターをrestrict
として宣言することでビットを最適化できます。これは、プログラマーとコンパイラーの間の契約です。 、彼らが指しているデータは、そのポインタを介してのみアクセスされ、他のポインタを介してはアクセスされない)。これにより、コンパイラは一時メモリなしでソースから宛先に直接コピーできるため、より効率的な最適化が可能になります。
Cでは、一部の文字列をインプレースで置き換えることができます。たとえば、strdup()によって返される文字列です。
char *str = strdup(" a b c ");
char *write = str, *read = str;
do {
if (*read != ' ')
*write++ = *read;
} while (*read++);
printf("%s\n", str);
コード内で宣言された文字列など、他の文字列は読み取り専用です。これらを新しく割り当てられたメモリ領域にコピーし、スペースをスキップしてコピーを埋める必要があります。
char *oldstr = " a b c ";
char *newstr = malloc(strlen(oldstr)+1);
char *np = newstr, *op = oldstr;
do {
if (*op != ' ')
*np++ = *op;
} while (*op++);
printf("%s\n", newstr);
人々が他の言語を発明した理由を見ることができます;)
文字列からスペースを削除する最も簡単なand最も効率的な方法は、単に文字列リテラルからスペースを削除することです。たとえば、エディタを使用して「検索して置換」_"hello world"
with "helloworld"
、およびプレスト!
わかりました、それはあなたが意図したものではないことを知っています。すべての文字列が文字列リテラルに由来するわけではありませんか?スペースを削除したいこの文字列が文字列リテラルに由来しないと仮定すると、string...のソースと宛先を考慮する必要があります...アルゴリズム全体を考慮する必要があります、最も簡単で最適な方法を提案するために、解決しようとしている実際の問題。
おそらく、あなたの文字列はファイル(例:stdin
)から来ており、別のファイル(例:stdout
)に書き込まれるようにバインドされています。その場合、最初に文字列をにする必要がある理由を疑問に思うでしょう。それが文字の流れであるかのように扱うだけで、あなたがそれらに遭遇したときにスペースを捨てます...
#include <stdio.h>
int main(void) {
for (;;) {
int c = getchar();
if (c == EOF) { break; }
if (c == ' ') { continue; }
putchar(c);
}
}
文字列を保存する必要をなくすことで、プログラム全体が大幅にmuch短くなるだけでなく、理論的にははるかに効率的になります。
まだ興味がある場合は、この関数は文字列の先頭からスペースを削除し、コードで機能させただけです。
void removeSpaces(char *str1)
{
char *str2;
str2=str1;
while (*str2==' ') str2++;
if (str2!=str1) memmove(str1,str2,strlen(str2)+1);
}
#include <ctype>
char * remove_spaces(char * source, char * target)
{
while(*source++ && *target)
{
if (!isspace(*source))
*target++ = *source;
}
return target;
}
ノート;
#include<stdio.h>
#include<string.h>
main()
{
int i=0,n;
int j=0;
char str[]=" Nar ayan singh ";
char *ptr,*ptr1;
printf("sizeof str:%ld\n",strlen(str));
while(str[i]==' ')
{
memcpy (str,str+1,strlen(str)+1);
}
printf("sizeof str:%ld\n",strlen(str));
n=strlen(str);
while(str[n]==' ' || str[n]=='\0')
n--;
str[n+1]='\0';
printf("str:%s ",str);
printf("sizeof str:%ld\n",strlen(str));
}
それは私が考えることができる最も簡単な(テスト済み)であり、動作します!!
char message[50];
fgets(message, 50, stdin);
for( i = 0, j = 0; i < strlen(message); i++){
message[i-j] = message[i];
if(message[i] == ' ')
j++;
}
message[i] = '\0';
C文字列は固定メモリにあるため、スペースを置き換える場合はすべての文字をシフトする必要があります。
最も簡単なのは、新しい文字列を作成して元の文字列を反復処理し、スペース以外の文字のみをコピーすることです。