■ポインタの何が便利か?
寿限無落語の文字列を関数引数で受け渡す歳に
strcpy版とpointer版を比較して、
ポインタの便利さを学習しましょう。
●strcpy版
#include <stdio.h>
#include <string.h>
//長い寿限無落語
static char input[] =
"Jugemu Jugemu,"
"Gokō no Surikire,"
"Kaijarisuigyo no Suigyōmatsu,"
"Ungyōmatsu,"
"Fūraimatsu,"
"Kuunerutokoro ni Sumutokoro,"
"Yaburakōji no Burakōji,"
"Paipo Paipo,"
"Paipo no Shūringan,"
"Shūringan no Gūrindai,"
"Gūrindai no Ponpokopī no Ponpokona no Chōkyūmei,"
"Chōkyūmei no Chōsuke";
void use_strcpy(char *output)
{
puts("■例えば:長い寿限無落語のCDの内容をコピーするのがstrcpy板");
printf("%sは%zu byte の転送命令が生成されます\n",__func__,sizeof(input));
strcpy(output,input);
}
int main(void){
char buf[1024] ={0};
use_strcpy(buf);
printf("%s\n",buf);
}
●寿限無落語の文字列を全部丸々コピーするので処理時間が掛かります。
●pointer版
#include <stdio.h>
#include <string.h>
//長い寿限無落語
static char input[] =
"Jugemu Jugemu,"
"Gokō no Surikire,"
"Kaijarisuigyo no Suigyōmatsu,"
"Ungyōmatsu,"
"Fūraimatsu,"
"Kuunerutokoro ni Sumutokoro,"
"Yaburakōji no Burakōji,"
"Paipo Paipo,"
"Paipo no Shūringan,"
"Shūringan no Gūrindai,"
"Gūrindai no Ponpokopī no Ponpokona no Chōkyūmei,"
"Chōkyūmei no Chōsuke";
void use_pointer(char **output)
{
puts("■例えば:長い寿限無落語のCDの置き場所をコピーするのがポインタ板");
printf("%sは%zu byte の転送命令が生成されます\n",__func__,sizeof(&input[0]));
*output = &input[0];
}
int main(void){
char *pointer = NULL;
use_pointer(&pointer);
printf("%s\n",pointer);
}
●寿限無落語の文字列のアドレスだけコピーするので処理時間が早いです。
注:コンピュータは早いのでstrcpy版とpointer版の速さの違いはこのサンプルだけでは体感できませんね。
■ポインタが分からないので無駄にstrcpyをしている例
#include <stdio.h>
#include <string.h>
#include <assert.h>
void 西暦干支変換(int 西暦,char *干支){
switch ( 西暦%12 ) {
case 0: strcpy(干支,"申(さる)"); break;
case 1: strcpy(干支,"酉(とり)"); break;
case 2: strcpy(干支,"戌(いぬ)"); break;
case 3: strcpy(干支,"亥(い)"); break;
case 4: strcpy(干支,"子(ね)"); break;
case 5: strcpy(干支,"丑(うし)"); break;
case 6: strcpy(干支,"寅(とら)"); break;
case 7: strcpy(干支,"卯(う)"); break;
case 8: strcpy(干支,"辰(たつ)"); break;
case 9: strcpy(干支,"巳(み)"); break;
case 10: strcpy(干支,"午(うま)"); break;
case 11: strcpy(干支,"未(ひつじ)"); break;
default: assert(!"ここには来ない"); break;
}
}
int main(void){
const int 今年=2024;
for(int 西暦 = 今年;西暦<=今年+12;西暦++){
char 干支[256];
西暦干支変換(西暦,干支);
printf("%4d年の干支は%s\n",西暦,干支);
}
}
意図した動きをしますが
記述量が多くて、
処理速度も遅いです。。
strcpyで文字列を出力配列に
わざわざコピーしていますが無駄です。
■文字列のアドレスを直接使う
#include <stdio.h>
#include <string.h>
#include <assert.h>
char *西暦干支変換(int 西暦){
switch ( 西暦%12 ) {
case 0: return "申(さる)";
case 1: return "酉(とり)";
case 2: return "戌(いぬ)";
case 3: return "亥(い)";
case 4: return "子(ね)";
case 5: return "丑(うし";
case 6: return "寅(とら)";
case 7: return "卯(う)";
case 8: return "辰(たつ)";
case 9: return "巳(み)";
case 10: return "午(うま)";
case 11: return "未(ひつじ)";
default: assert(!"ここには来ない");
}
}
int main(void){
const int 今年=2024;
for(int 西暦 = 今年;西暦<=今年+12;西暦++){
char *干支 = 西暦干支変換(西暦);
printf("%4d年の干支は%s\n",西暦,干支);
}
}
strcpyで文字列を全部コピーしないで
文字列のアドレスだけを返却しているので
strcpy版より効率が良いです。
■ポインタポインタを使う
#include <stdio.h>
#include <string.h>
#include <assert.h>
void 西暦干支変換(int 西暦,char **干支){
switch ( 西暦%12 ) {
case 0: *干支 = "申(さる)"; break;
case 1: *干支 = "酉(とり)"; break;
case 2: *干支 = "戌(いぬ)"; break;
case 3: *干支 = "亥(い)"; break;
case 4: *干支 = "子(ね)"; break;
case 5: *干支 = "丑(うし"; break;
case 6: *干支 = "寅(とら)"; break;
case 7: *干支 = "卯(う)"; break;
case 8: *干支 = "辰(たつ)"; break;
case 9: *干支 = "巳(み)"; break;
case 10: *干支 = "午(うま)"; break;
case 11: *干支 = "未(ひつじ)";break;
default: assert(!"ここには来ない");
}
}
int main(void){
const int 今年=2024;
for(int 西暦 = 今年;西暦<=今年+12;西暦++){
char *干支 = NULL ;
西暦干支変換(西暦,&干支);
printf("%4d年の干支は%s\n",西暦,干支);
}
}
●ポインタポインタ**を使った例です。
ちょっと難解です。
■配列を使う
#include <stdio.h>
#include <string.h>
#include <assert.h>
char *西暦干支変換(int 西暦){
static char *干支[] ={
[0]="申(さる)" ,
[1]="酉(とり)" ,
[2]="戌(いぬ)" ,
[3]="亥(い)" ,
[4]="子(ね)" ,
[5]="丑(うし)" ,
[6]="寅(とら)" ,
[7]="卯(う)" ,
[8]="辰(たつ)" ,
[9]="巳(み)" ,
[10]="午(うま)" ,
[11]="未(ひつじ)"
};
return 干支[西暦%12] ;
}
int main(void){
const int 今年=2024;
for(int 西暦 = 今年;西暦<=今年+12;西暦++){
char *干支 = 西暦干支変換(西暦);
printf("%4d年の干支は%s\n",西暦,干支);
}
}
●switch文が不要になりました。
このコードは記述量も少なく、
処理速度も多分最速です。