c++でconst char*型の文字列をテンプレート関数で連結したい

投稿者: user28203

c++はstring型を使ってやれば文字列を簡単に扱えると思うのですが、あえてconst char*型を使って文字列を扱おうと思うのですが、どうすればconst char*型の文字列を連結できるのですか?

例: “abc” “abcc” の二つのconst char*型を連結して “abcabcc” と一つのconst char*型に入れたいです。調べてこの関数を使って入れたのですが、rsize_t型とsize_t型の違いについても教えていただけますでしょうか?

template<typename type> type f(type a,type b) {
    cout << "テンプレート関数n";
    return a + b;
}

template<> const char* f<const char*>(const char* x, const char* y) {
    //cout << "明示的特殊化n";
    char* xx = const_cast<char*>(x);
    rsize_t t = sizeof(xx);
    strcat_s(xx, strlen(xx), y);  //ここの関数で書き込みアクセスエラーが出ます。
    cout << xx;
    return  "a";
}

int main() {
    cout << f<const char*>("abc", "abcc");
    _getch();
    return 0;
}

解決

2つ誤りがあると考えます。

  1. 呼び出し元で渡している引数"abc"には結合後の文字列"abcabcc"“を格納するだけのサイズがない可能性があります。
  2. 呼び出し元では文字列定数を渡していますが、多くのコンパイラでは文字列定数を変更不能なメモリ領域に配置することが多いため、結合する際にアクセスエラーになる可能性があります。

動作させるには、次の2つのどちらかの修正を行うとよいと思います。

#一長一短です。後者はメモリリークの可能性があるので、前者の方が比較的よいと思います。

  1. 呼び出し元で"abc"を結合後の文字数以上の配列に格納してテンプレート関数を呼び出す

追記
コメントの指摘通り、案1のコード例で配列zのサイズ計算が間違ってました。例を訂正します。
(sizeof(xx)だとsizeof(const char*)なので、期待通りになりません)

    int main() {
        const char xx[] = "abc";
        const char yy[] = "abcc";
        // 必要最小限のサイズより大きくなるのは割り切りです。
        char z[sizeof(xx) + sizeof(yy)] = "abc";
        cout << f<const char*>(&z[0], &yy[0]);
        // 以下、略
    }
  1. テンプレート関数内で動的に結果配列を生成しそれを返す

    template<> const char* f<const char*>(const char* x, const char* y) {
        char* z = new char[strlen(x) + strlen(y) + 1];
        strcpy(z, x);
        strcat(z, y);
        // zは呼び出し元でdeleteする必要がある。
        return z;
    }
    

また、rsize_tsize_tの違いですが、机上で確認した限りだと、

  1. RSIZE_MAXという現実的な上限値が規定されている。
  2. rsize_tの値を返す関数はRSIZE_MAXを超える結果の場合0を返すことができる。

という違いがあるように見えました。
ただし、これはC言語の規格(「C11」の規格)であり、C++言語では規格化されていないように見えましたので、コンパイラ(処理系)によっては対応していないかも知れません。

回答者: Anonymous

Leave a Reply

Your email address will not be published. Required fields are marked *