9

Bjarne Stroustrup によるThe C++ Programming Language の第 3 版を読んでいて、すべての演習を完了しようとしています。セクション 6.6 から演習 13 へのアプローチ方法がよくわからないので、洞察を得るためにスタック オーバーフローに目を向けようと思いました。問題の説明は次のとおりです。

2 つの C スタイルの文字列引数を取り、引数を連結した単一の文字列を返す関数cat()を作成します。結果のストアを見つけるにはnewを使用します。

これまでのコードは次のとおりです。何をすべきかわからない疑問符が付いています。

? cat(char first[], char second[])
{
    char current = '';
    int i = 0;

    while (current != '\0')
    {
        current = first[i];
        // somehow append current to whatever will eventually be returned
        i++;
    }

    current = '';
    i = 0;

    while (current != '\0')
    {
        current = second[i];
        // somehow append current to whatever will eventually be returned
        i++;
    }

    return ?
}

int main(int argc, char* argv[])
{
    char first[]  = "Hello, ";
    char second[] = "World!";

    ? = cat(first, second);

    return 0;
}

そして、ここに私の質問があります:

  1. newを使用してストアを検索するにはどうすればよいですか? 何か別の C スタイルの文字列を作成するためにnewstd::string* result = new std::string;を使用する必要がありますか?
  2. 前の質問に関連して、cat() から何を返す必要がありますか? newを使用する必要がある場合は、ポインターが必要になると思います。しかし、何へのポインタですか?
  3. この問題では、 deleteを使用してメモリを解放することについては言及していませんが、newを使用して割り当てを行っているため、使用すべきであることはわかっています。戻る直前に、メインの最後で削除する必要がありますか?
4

7 に答える 7

4

「実際の」プログラムでは、はい、std::string を使用します。この例では、代わりに C 文字列を使用する必要があるようです。

だから多分このようなもの:

char * cat(char first[], char second[])
{
    char *result = new char[strlen(first) + strlen(second) + 1];

...

Q: どのように「追加」しますか?

A: 「first」から「result」まで全て書いてください。

完了したらすぐに、「秒」ですべてを書き続けて結果を出します (中断したところから始めます)。完了したら、必ず最後に '\0' を追加してください。

于 2013-07-27T23:45:11.753 に答える
4

newを使用してストアを検索するにはどうすればよいですか? 何か別の C スタイルの文字列を作成するためにnewstd::string* result = new std::string;を使用する必要がありますか?

後者; このメソッドは C スタイルの文字列を受け取りますが、テキストには、それ以外のものを返す必要があることを示唆するものは何もありません。したがって、関数のプロトタイプは になりますchar* cat(char const*, char const*)。もちろん、これは通常の関数の書き方ではありません。手動のメモリ管理は、エラーが発生しやすいため、最新の C++ では完全にタブーです。

この問題では、delete を使用してメモリを解放することについては触れていませんが、new を使用して割り当てを行っているため、削除を使用する必要があることはわかっています。戻る直前に、メインの最後で削除する必要がありますか?

この演習では、はい。現実の世界では、いいえ: 上で述べたように、これは完全にタブーです。実際には、を使用してメモリを割り当てstd::string、を返します。手動でメモリを割り当てていることに気付いた場合(そしてそれが正当な理由であると仮定して)、そのメモリを raw ポインターではなくスマート ポインター (または.newstd::unique_ptrstd::shared_ptr

于 2013-07-27T23:45:21.053 に答える
3
  1. Cスタイルの文字列を返すことになっているため、使用できませんstd::string(または、少なくとも「質問の精神ではありません」)。はい、newC スタイルの文字列を作成するために使用する必要があります。
  2. 生成した C スタイルの文字列を返す必要があります...つまり、新しく作成した文字列の最初の文字へのポインターです。
  3. 正解です。最後に結果を削除する必要があります。この特定のケースでは、おそらくそれほど重要ではないため、無視される可能性があると思いますが、完全性/正確性のためには、無視する必要があります。
于 2013-07-27T23:46:20.337 に答える
3

しばらく前に私のプロジェクトから掘り起こした古いコードを次に示します。

char* mergeChar(char* text1, char* text2){
    //Find the length of the first text
    int alen = 0;
    while(text1[alen] != '\0')
        alen++;

    //Find the length of the second text
    int blen = 0;
    while(text2[blen] != '\0')
        blen++;

    //Copy the first text
    char* newchar = new char[alen + blen + 1];
    for(int a = 0; a < alen; a++){
            newchar[a] = text1[a];
    }

    //Copy the second text
    for(int b = 0; b < blen; b++)
        newchar[alen + b] = text2[b];

    //Null terminate!
    newchar[alen + blen] = '\0';
    return newchar;
}

ただし、一般に、「実際の」プログラムでは、を使用することが期待されますstd::string。後で確認してくださいdelete[] newchar

于 2013-07-27T23:48:54.220 に答える
2

演習が意味することは、newメモリを割り当てるために使用することです。「お店を探す」というと変な言い方をされますが、実際はその通りです。必要なストアの量を指定すると、使用可能な使用可能なメモリ ブロックが検出され、そのアドレスが返されます。

演習で std::string を使用する必要があるようには見えません。を返す必要があるようですchar*。したがって、関数プロトタイプは次のようになります。

char* cat(const char first[], const char second[]);

指定子に注意してくださいconst。文字列リテラルを引数として渡すことができるようにすることが重要です。

したがって、コードをすぐに提供することなく、結果のchar*文字列の大きさを決定し、 を使用して必要な量を割り当てnew、2 つのソース文字列を新しく割り当てられたスペースにコピーし、それを返す必要があります。

通常、C++ でこの種のメモリ管理を手動で行うことはありません (std::string代わりに使用します) が、それでも知っておくことは重要です。これが、この演習の理由です。

于 2013-07-27T23:48:23.497 に答える
0

new文字列にメモリを割り当ててからポインタを返すために使用する必要があるようです。したがって、 のreturnタイプはcatになります`char*

次のようなことができます。

int n = 0;
int k = 0;

//also can use strlen
while( first[n] != '\0' )
     n ++ ;
while( second[k] != '\0' )
     k ++ ;

//now, the allocation

char* joint = new char[n+k+1]; //+1 for a '\0'

//and for example memcpy for joining

memcpy(joint, first, n );
memcpy(joint+n, second, k+1); //also copying the null


return joint;
于 2013-07-27T23:57:33.313 に答える