web-dev-qa-db-ja.com

文字列の文字を置き換える

可能性のある複製:
Cの文字列を置き換える関数は何ですか?

文字列内の特定の文字を複数の文字に置き換えようとしています。これが私がやろうとしていることの例です。

「aaabaa」という文字列があるとします

文字「b」のすべての出現箇所を5つの「c」で置き換えたい。

だから終わったら「aaabaa」が「aaacccccaa」になる

私は次のコードを書きました:

#include <stdio.h>
#include <string.h>
int main(void)
{
    char s[20] = "aaabaa";
    int i, j;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            for (j=0; j<5; j++)
            {
                s[i+j] = 'c';
            }
        }
    }
    printf("%s\n", s);
}

この関数の出力は "aaaccccc"です。最後の2つのaをcで上書きするだけのようです。これらの最後のaが上書きされないようにする方法はありますか?

6
me45

あなたの問題は、 "ccccc"を元の文字列に置き換えて、置換したい文字の後に残りの文字を上書きすることです...新しい文字列にコピーし、2つのインデックス(それぞれ1つ)を追跡する必要があります。

そして、あなたがchar s[20]元の文字列のサイズと置換値の合計よりも大きい。そうしないと、重要なログインシステムにバッファオーバーフローの脆弱性が生じます:-)

乾杯、

5

バッファのサイズを設定することを心配せずにこれを一般的に行う場合は、結果を保持するのに十分な大きさの新しい文字列をmallocする必要があります。

/* return a new string with every instance of ch replaced by repl */
char *replace(const char *s, char ch, const char *repl) {
    int count = 0;
    const char *t;
    for(t=s; *t; t++)
        count += (*t == ch);

    size_t rlen = strlen(repl);
    char *res = malloc(strlen(s) + (rlen-1)*count + 1);
    char *ptr = res;
    for(t=s; *t; t++) {
        if(*t == ch) {
            memcpy(ptr, repl, rlen);
            ptr += rlen;
        } else {
            *ptr++ = *t;
        }
    }
    *ptr = 0;
    return res;
}

使用法:

int main() {
    char *s = replace("aaabaa", 'b', "ccccc");
    printf("%s\n", s);
    free(s);
    return 0;
}
10
nneonneo
#include <stdio.h>
#include <string.h>

int main(void)
{
    char temp[20];
    char s[20] = "aaabaa";
    int i, j;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            strcpy(temp,s[i+1]); //copy rest of the string in this case 'aa'
            for (j=0; j<5; j++)
            {
                s[i+j] = 'c';
            }
            s[i+j] = '\0';   // here we get s = "aaaccccc"
            strcat(s,temp); // concat rest of the string (temp = "aa") after job is done. 
                           //  to this point s becomes s = "aaacccccaa"
        }
    }
    printf("%s\n", s); //s = "aaacccccaa". 
}

ここでは、バッファ(temp)を使用して、置換する文字の後の文字列の残りを格納しています。置換が完了したら、最後に追加します。

s = "aaacccccaa"になります

1
VishalDevgire

2番目のchar配列を宣言する必要があります。以下のコードでは、条件が失敗したときに配列sの内容をs1にコピーするだけです。

#include <stdio.h>
#include <string.h>
int main(void)
{
  char s[20] = "aaabaa";
  char s1[1024];
  int i, j, n;
  for (i=0, n = 0; s[i]!= '\0'; i++)
  {
    if (s[i] == 'b')
    {
        for (j=0; j<5; j++)
        {
            s1[n] = 'c';
            n++;
        }
    }
    else
    {
        s1[n] = s[i];
        n++;
    }
}
s1[n] = '\0';
printf("%s\n", s1);
}
1
Riskhan

別の変数を使用できます

#include <stdio.h>
#include <string.h>
int main(void)
{
    char s[20] = "aaabaa";
    char temp[20]="";
    int i, j,k;
    k=0;
    for (i=0; s[i]!= '\0'; i++)
    {
        if (s[i] == 'b')
        {
            for (j=0; j<5; j++)
            {
                temp[k] = 'c';
                k++;
            }
        }
        else
        {
            temp[k]=s[i];
            k++
        }
    }
    printf("%s\n", temp);
}
1
Bhavik Shah

まあ、配列を動的に割り当てる場合は、おそらく2番目の配列を割り当てる必要があります。文字列sには固定量のメモリしか割り当てられていないため、これが必要です。

したがって、forループ内の文字を上書きするのではなく、新しい配列の大きさを示すカウンターを増やすことをお勧めします。カウンターは、元の文字列のサイズから開始し、「b」のインスタンスが見つかるたびに4ずつ増加します。次に、変更された文字列をsize [counter]の新しいcharバッファに適切にコピーする関数を記述し、「b」が見つかるたびに5つのcを挿入します。

0