1

これは私が実装したstrcat関数ですが、行に移動するとセグメンテーション違反が発生し*dst++ = *src++;ます。そこから次の文字列を追加したいので、srcまでインクリメントしました。'\0'セグメンテーション違反が発生する理由を教えてください。私は何か論理的な間違いをしているの*dst++ = *src++;ですか?

char *strconcat(char *dst, char *src)
{
    char *fdst;
    fdst = dst;
    if (dst == '\0' || src == '\0')
    return fdst;

    while (*dst != '\0')
        dst++;
    while (*src != '\0')
        *dst++ = *src++;

    return fdst;
}

ねえ、私は以下に示す多くの解決策を経験し、次の変更を加えましたが、2つの文字列を連結し始めると、セグメンテーションの問題が発生します。これが私のコード全体です。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

char *strconcat(char *dst, const char *src);
void main()
{
    char *str1 = "Stack";
    char *str2 = "overflow";
    printf("MY CONCAT:%s\n",strconcat(str1, str2));
    printf("INBUILT CONCAT:%s\n",strcat(str1, str2));
}

char *strconcat(char *dst, const char *src)
{
    char *fdst;
    int dst_len = 0, src_len = 0;

    dst_len = strlen(dst);
    src_len = strlen(src);
    fdst = (char *) malloc(dst_len + src_len + 1);

    fdst = dst;
    if (src == NULL)
        return fdst;

    while(*dst)
    {
       dst++;
       fdst++;
    }
    while(*src)
       *fdst++ = *src++;
       *fdst = '\0';

    return fdst;
    }
4

7 に答える 7

2

慣用的な方法は

while (*dst++ = *src++);
于 2012-11-20T08:41:46.713 に答える
2

いくつかの観察:

  1. 終了をコピーせず、終了していない文字列をに残しますdst。これが実際の問題の原因です。
  2. これif(dst == '\0'||src == '\0')は奇妙なことです。意図が比較対象であるNULL場合は、文字リテラルを使用せずに、より直接的に比較する必要があります。
  3. src引数は読み取り専用であるためconst char *です。const「入力」引数であるポインタに使用することは、プロトタイプのすぐそこに意図を伝えるため、非常に良い考えです。また、間違った文字列に誤って書き込むことを回避するのにも役立ちます。
  4. str「名前空間」が標準ライブラリ用に予約されている、で始まる関数を使用することはできません。
于 2012-11-20T08:42:08.097 に答える
1

考えられるクラッシュの原因:

dst1)との連結をサポートするのに十分ではない長さである可能性がありsrcますdst

2)割り当てられたメモリ(静的または動的)を指していない入力charポインタを使用して関数を呼び出した可能性があります

3)入力dstcharポインタが定数文字列を指している可能性があります。

2番目の後にdst文字列を終了する必要がある別の発言'\0'while

 while (*src != '\0')
        *dst++ = *src++;
 *dst='\0';
于 2012-11-20T08:57:09.780 に答える
1

これを試して:

while(*original)
  original++;
while(*add)
{
  *original = *add;
  add++;
  original++;
}
*original = '\0';

役に立つかもしれません。

于 2012-11-20T09:06:31.843 に答える
1

コードにはかなりのエラーがあります。

  1. if (dst == '\0' || src == '\0')これをチェックして何をしようとしているのか。まず第一に、これは明確な状態ではありません-使用するif (dst == NULL || src == NULL)if (*dst == '\0' || *src == '\0')、より正確にして、これをより明確にする必要があります。次に、この条件が正しい場合でも(if (*dst == '\0' || *src == '\0'))、連結が必要なことを達成していません。少なくとも、*src == '\0'おそらく元の文字列--dstを返す必要がある場合。
  2. dstが新しい文字列を格納するのに十分な長さであるかどうかを確認するか、dstとsrcの両方を保持するのに十分な大きさの新しいバッファを関数内に割り当てる必要があります( )-終了する「/ 0」文字を保持するためのmalloc (strlen(dst) + strlen(src) + 1追加の注意)+1
  3. 結果文字列を終了していません。

そしてあなたの質問への答え:セグメンテーション違反はおそらくあなたのdstがsrcとdstの両方を保持するのに十分な長さではないためです。ポイント2のヒントを使用してコードを変更するか、少なくともサイズを持つ関数の外部でより大きなバッファーを宣言することができます(strlen(dst) + strlen(src) + 1。もう1つの理由は、charなどの定数文字列を使用してこの関数を呼び出すことである可能性があります*str = "string";。この場合、おそらく文字列は定数であり、変更することはできません(ほとんどのオペレーティングシステムでは、これはプログラムの変更不可能な部分にあり、この場所へのポインタしかありません)。

于 2012-11-20T09:11:02.903 に答える
1

ここでの複数の問題:

問題-私

mallocで割り当てられたメモリ

    fdst = (char *) malloc(dst_len + src_len + 1);

後でこれを行うと、いくつかの行が失われます。

    fdst = dst;

'fdst'のmallocによって返されたアドレスをターゲット文字列のアドレスに置き換えます。あなたが自分でそれを修正することを願っています、それはとても簡単です。

問題-II

上記の問題を修正した後、これを修正する必要があります。

while(*dst)
{
   dst++;
   fdst++;
}

インクリメントするだけでなく、文字をからにコピーする必要がdstありfdstます。これは連結された文字列になるためです。

問題-III

最後に、あなたはこれを最後にやっています.. !!

return fdst;

あなたはそこの間違いに気づきますよね?あなたがその世話をすることができることを願っています[ヒント:開始アドレスを保存し、インクリメントされたポインタではなく、最後にそれを返します;)]

注:最適化されたソリューションではありませんが、コードを修正します。

于 2012-11-21T06:01:41.850 に答える
0

あなたのコードは正しいです、説明のために以下を見てください!

呼び出し元のsrcおよびdst文字列にchar*を使用していると思います。

プログラムがでクラッシュしているので、そこで配列宣言を使用すると役立ちます

*dst++ = *src++;

dstとsrcは定数であり、変更できない文字列を指しているためです。

次のコードでは、mainを追加したばかりですが、関数は変更されていません。

#include<stdio.h>

char *strconcat(char *dst, char *src)
{
    char *fdst;
    fdst = dst;
    if (dst == '\0' || src == '\0')
        return fdst;

    while (*dst != '\0')
        dst++;
    while (*src != '\0')
        *dst++ = *src++;

    return fdst;
}

void main()
{
 char dest[10] = "one" ;
 char src[10] = "two" ;

printf("\n%s " , strconcat( dest , src ) ) ;
}

ifステートメントを次のように変更する必要がありますが

 if (*dst == '\0' || *src == '\0')
            return fdst;
于 2012-11-20T10:16:10.770 に答える