C++サンプル集

【第1部】C言語(K&R検証)編

0029.文字列をコピーする

 今項のサンプルは、char型ポインタを使って、文字列をコピーするサンプルです。

ソース紹介

CPPファイルに記述
#include <iostream>
#include <cstdio>
using namespace std;

/*
文字列をtからsにコピーする(配列添え字版)
*/
void strcpy2(char* s,const char* t) {
    int i = 0;
    while ((s[i] = t[i]) != '\0') {
        i++;
    }
}

/*
strcpy2のテスト
*/
int main()
{
    char buff[100];
    strcpy2(buff, "hello");
    cout << buff << endl;
    return 0;
}
出力
hello

サンプル説明

 K&Rではこのサンプルはstrcpy()関数として紹介されています。
 しかしVS2019で実装した場合標準ライブラリのstrcpy()関数がデフォルトで見えちゃってるためにエラーになります。
 なのでstrcpy2()関数と別名で実装しました。
 また、コピー元はconstを付けないとエラーになります。これはセキュリティ強化の観点です。
 このように引数を配列ではなくポインタを使う場合、いろんな場所でK&Rの時代と変わってきた部分があります。
 もう一つ、このサンプルには重要なポイントがあります。
 呼び出し側main()関数を見てください。
    strcpy2(buff, "hello");
 とありますコピー元"hello"と記載されています。
 これはC/C++文字列リテラル(つまり " と " にはさまれた記述)その先頭のポインタをあらわすという文法があるからです。
 ですから
"abcde"[2]
 という記述が可能です(あんまり意味はないですが)。これは、文字cをあらわします。
 続いてポインタ版strcpy2()関数を紹介します。

ソース紹介

CPPファイルに記述
/*
文字列をtからsにコピーする(ポインタ版)
*/
void strcpy2(char* s,const char* t) {
    while ((*s = *t) != '\0') {
        s++;
        t++;
    }
}

サンプル説明

 このバージョンはポインタは変数であるという特徴を生かしています。
 変数なので加算が可能です。また添え字の i は、もう必要ではありません。
 さらに、もう一歩進んだバージョンを紹介します。

ソース紹介

CPPファイルに記述
/*
文字列をtからsにコピーする(ポインタ版2)
*/
void strcpy2(char* s,const char* t) {
    while ((*s++ = *t++) != '\0')
        ;
}

サンプル説明

 このバージョンは後置インクリメントを使うことで、コード行数を減らしています。
 さらにさらに、C/C++ではwhile文などの条件式では真か偽かのみが問われます。そして、偽は0に評価される値で、真は偽でないものという定義があります。ここはJavaやC#と大きく違うところです。(JavaやC#は条件式はboolもしくはbooleanでなければならない)
 ですので、以下の様に書けます。
CPPファイルに記述
/*
文字列をtからsにコピーする(ポインタ版3)
*/
void strcpy2(char* s,const char* t) {
    while (*s++ = *t++)
        ;
}
 ちょっとびっくりですよね。

K&Rでの記述

 元になったのは第5章:ポインタと配列に記述されています。文字ポインタと関数の説明のところです。