【C++】constを使用・C言語スタイルの文字列をポインタとして取得

５個の数値を入力し、それぞれに「０が含まれていれば１０で割り、５が含まれていれば５で割る」作業を行い (int型・小数部分は切り捨てる) 、それらの合計を求めて出力表示するプログラムを作ります。例えば

:::note info
15 34
66 77
51 83
70 11
149 38
:::

上のように入力すると
（判定する数, 割られる数）＝（15, 34）（66, 77）（51, 83）（70, 11）（149, 38）
とペア分けされ、それぞれのペアの割られる数の方を指定された数で割って (割らない場合もある) 足し合わせるので、6 + 77 + 16 + 1 + 38 より 138 が出力されるはずです。

まずは次のようにプログラムを作りました。

```:間違ったプログラム
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int main(){
	
	int date[100], part[100];
	for(int i = 0; i < 5; i++){
		cin >> date[i];
		cin >> part[i];
	}
	
	int j = 0, sum = 0;
	while(j < 5){
		string buffer = to_string(date[j]);
		char* str = buffer.c_str();
		char* p_0 = strchr(str,'0');
		char* p_5 = strchr(str,'5');
		if(p_0 != NULL){
			part[j] /= 10;
			sum += part[j];
		}else if(p_5 != NULL){
			part[j] /= 5;
			sum += part[j];
		}else{
			sum += part[j];
		}
		j++;
	}
	cout << sum << endl;
	
}
```

出てきた数値が違うといった問題でなく、そもそもコンパイルが出来ませんでした。エディタではwhile文内の`char* str = buffer;`の部分にエラーが出ていました。

### エラー箇所の修正
![(C++) _ ブラウザでプログラミング・実行ができる「オンライン実行環境」_ paiza.IO および他 10 ページ - 個人 - Microsoft​ Edge 2022_11_08 9_14_06.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2610341/9f7552e8-8e99-c0c6-21a1-880fea81939e.png)
要するに、`std::string`から`char*`への変換が出来ないらしい。

charはC言語形式なので、C++ → C に対応する型変換が必要になります。
参考：

https://marycore.jp/prog/cpp/convert-string-to-char/#std%3A%3Astring%20%E2%86%92%20const%20char%2A

着目したのは、**const**を使用した変換「**std::string → const char***」です。この方法は[C言語スタイルの文字列をポインタとして取得する](https://marycore.jp/prog/cpp/convert-string-to-char/#std%3A%3Astring%20%E2%86%92%20const%20char%2A:~:text=C%E8%A8%80%E8%AA%9E%E3%82%B9%E3%82%BF%E3%82%A4%E3%83%AB%E3%81%AE%E6%96%87%E5%AD%97%E5%88%97%E3%82%92%E3%83%9D%E3%82%A4%E3%83%B3%E3%82%BF%E3%81%A8%E3%81%97%E3%81%A6%E5%8F%96%E5%BE%97%E3%81%99%E3%82%8B)のに使うらしいです。
strchrはC言語の文字列でお馴染みのchar型にしか扱えない (と思っている) ので、今回のようなケースにピッタリかもしれないと、上の変換方法を選択しました。

:::note warn
ただ、「std::string → const char*」が何故「C言語形式の文字列へ変換」になるのか、イマイチよく分かりません。
単純に「関数でのポインタ引数に対する書き換えから保護する」ならまだ分かります。しかし………………
変数の値を変更せず定数として宣言する際に使う修飾子としての役割を持つconstの事を考えると、「なぜ今constなのか？ここでのconstはどう働きかけているのか？」となおさら疑問に感じてしまいます。
:::

上のサイトをお手本にさせて頂くと、こんな感じでしょうか。自分のプログラムでconstを使ったのは、今回が初めてです。

```c++
		string buffer = to_string(date[j]);
		const char* str = buffer.c_str();
		const char* p_0 = strchr(str,'0');
		const char* p_5 = strchr(str,'5');
```

**初期化時の変数の値を書き換え禁止 (読み取り専用) にする事**で知られる「const」。僕の場合、constは「[渡された構造体の内容を変更しないという事を明示するために指定するもの](https://qiita.com/weemiee/questions/0b9bbd20c6c351fddccd#:~:text=%E6%B8%A1%E3%81%95%E3%82%8C%E3%81%9F%E6%A7%8B%E9%80%A0%E4%BD%93%E3%81%AE%E5%86%85%E5%AE%B9%E3%82%92%E5%A4%89%E6%9B%B4%E3%81%97%E3%81%AA%E3%81%84%E3%81%A8%E3%81%84%E3%81%86%E3%81%93%E3%81%A8%E3%82%92%E6%98%8E%E7%A4%BA%E3%81%99%E3%82%8B%E3%81%9F%E3%82%81%E3%81%ABconst%E3%82%92%E6%8C%87%E5%AE%9A)」として初めて知る事になりました。

ただ、前にも述べた通り、僕はconstに対しての理解が未だ浅いため、あまり表に出ない隠れた役目は何なのか悩んでいます。

参考：

https://monozukuri-c.com/langc-funclist-const/


https://qiita.com/pink_bangbi/items/a36617bf1d5923743d69

https://qiita.com/mizcii/items/35df2bceac67a75f75dd

ひとまず、プログラムを仕上げます。

```c++:完成プログラム
#include <iostream>
#include <string>
#include <cstring>
using namespace std;

int main(){
	
	int date[100], part[100];   //date：調査する数値 (配列) , part：同じ要素番目のdateに対応する”割られる数”(配列)
	for(int i = 0; i < 5; i++){
		cin >> date[i];
		cin >> part[i];
	}
	
	int j = 0, sum = 0;
	while(j < 5){
		string buffer = to_string(date[j]);
		const char* str = buffer.c_str();
		const char* p_0 = strchr(str,'0');
		const char* p_5 = strchr(str,'5');
		if(p_0 != NULL){
			part[j] /= 10;
			sum += part[j];
		}else if(p_5 != NULL){
			part[j] /= 5;
			sum += part[j];
		}else{
			sum += part[j];
		}
		j++;
	}
	cout << sum << endl;
	
}
```

僕の期待通りに動きました。出力画面では 138 のみを表示させている状態です。

### まとめ
今回僕にとって大きかったのは、constに触った事です。今まで簡単なプログラムしか書いていなく、「関数や変数の型が複雑になる」とconstを厄介払いしてきたので、今回こうして使わざるを得ない状況に立たされて、仕組みを理解出来るよう調べているところです。
プログラムの方は問題なさそうなので、constについてまた新しい発見をしたら記事を更新します。