weemiee
@weemiee (weemiee)

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

【C++】C++でstrchr()を使いたい

Q&A

5個の数値を入力し、それぞれに「0が含まれていれば10で割り、5が含まれていれば5で割る」作業を行い (int型・小数部分は切り捨てる) 、それらの合計を求めて出力表示するプログラムを作ろうとしています。例えば、15, 66, 51, 70, 149を入力すると、3 + 66 + 10 + 7 + 149 より235が出力されます。
しかし、次のように書いたプログラムは実行に失敗し、エディタではwhile文内のchar* str = buffer;の部分にエラーが出ていました。

間違ったプログラム
#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;   //エラーになった部分
		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];
		}
		j++;
	}
	cout << sum << endl;
	
}

しかし、to_string()やC++のstrchr()の使い方等、思い当たる箇所について色々と調べてみたものの、結局どこが間違っていたのかがどうしても分かりませんでした。
strを定義する部分でエラーになったのは何故なのでしょうか?

0

3Answer

直接的な問題点を理解するための回答はすでに出ていますので別の観点から言うならこの場面ではそもそも strchr を使おうとするのがあまり好ましくないです。 C++ はかなり C を踏襲していますが、互換性のための抜け道だったり歴史的な名残(なご)りでしかないものも多く、そういったものを使おうとすると様々な制限や回りくどさに直面します。

C では文字列とはバイト列のことであり、あるバイト列が文字列であるかどうかはプログラマが文字列として扱うかどうかです。 C++ ではより抽象度の高い文字列のための型 std::string を用意し、内部でどのような構造を持っているか意識しないで済むように覆われています。 (実際にはそれほど理想的に抽象化できているわけではありませんが。)

std::string に対して strchr を使おうとする例は、そうやって覆われているものをあらためて剥がさないといけないということです。 覆われているものはなるべく覆われているままにすべき (いわゆるカプセル化の考え方) です。 特定の文字を探すという目的について std::string はメンバ関数 find を持っているのでこれを使うとよいでしょう。 あるいはコンテナ一般に対して使える非メンバ関数 std::find を使ったほうが良い場合もあるかもしれません。

念のために申し添えておきますが、互換性が保たれていることや (不格好でも) C の資産と連携できることも C++ の強みではあるのでその部分を否定するものではありません。 ただ、その分の面倒なところをプログラマが引き受けなければならなくなるので必要でないなら避けたほうがよいということです。

6Like

エラーになったのは何故なのでしょうか?

質問にエラーメッセージを書いていないということは内容をあまり気にしていないのだと思いますが、理由はそこに書いてあることがほとんどですよ。手元でコンパイルすると以下のエラーが出ました。

input.cxx:17:9: error: no viable conversion from 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to 'char *'
                char* str = buffer;   //エラーになった部分
                      ^     ~~~~~~

std::string 型の値を char * 型に変換することができないという意味です。解決方法はエラーメッセージで検索すると出てきます。

2Like

私たちは血液型に感心があるのに、変数型には何故、無頓着なのでしょう?
 また、エラーメッセージの検索は国語や英語の辞書を引くのと似ています。辞書が手垢で黒くなったら一人前です。

良い解説があったので紹介します。

正しく変数の型を理解するのは大変ですがファイトです。

さて、
この問題、文字列処理の方向へミスリードされていませんか?
 そもそも、数値のみで解けませんか?
x % 10 ...残念、出来ませんね!
再帰定義でできる? 5がムズいかも?

暇人x in 電車

1Like

Your answer might help someone💌