sscanfで数字交じりの文字列から数字を取り出す

週末、C++でコードを書こうとして、文法がおぼつかないことに気がつきました。鈍器本のおかげでちょっと読めるようになった気がしても、書いてみないことには書けないものですね。当たり前でした。

練習に、TopCoderの過去問をC++で解いてみることにしました。

文字列操作や配列操作などのプリミティブな操作に慣れるかも?(期待)

SRM209 div2 (250)

問題

移動平均の問題。vectorでhh:mm:ss形式のタイムを複数与える。タイムn個ずつの平均を計算し、vectorで返す。

自分の解答
#include <vector>
#include <string>

class MovingAverages{
public:
	std::vector<int> calculate(std::vector<std::string> times, int n);
};

std::vector<int> calcu_times(std::vector<std::string> times)
{
	std::vector<int> results;

	for(int i = 0; i < times.size(); ++i){
		std::string str = times[i].substr(0, 2);
		const char* ch_hour = str.c_str();
		int hour = std::atoi(ch_hour) * 60 * 60;

		str = times[i].substr(3, 2);
		const char* ch_min = str.c_str();
		int min = std::atoi(ch_min) * 60;

		str = times[i].substr(6, 2);
		const char* ch_sec = str.c_str();
		int sec = std::atoi(ch_sec);

		results.push_back(hour + min + sec);
	}
	return results;
}

std::vector<int> MovingAverages::calculate(std::vector<std::string> times, int n)
{
	std::vector<int> results;
	std::vector<int> temp = calcu_times(times);

	for(int i = 0; i + n < times.size() + 1; ++i){
		int sum = 0;
		for(int j = 0; j < n; ++j){
			sum += temp[i];
			++i;
		}
		results.push_back(sum / n);
		i -= n;
	}

	return results;
}
人様のコードを読んで思ったこと

hh:mm:ssというフォーマットを秒に変換するために、数字交じり文字列から数字を取り出します。

これには、sscanfを使えばよかったようです。

sscanf({文字列}, "%d:%d:%d", &hour, &min, &sec);

sscanfが思いつかなかったので、文字列から文字を切り出してはatoi関数を適用するという、不恰好なことをしていました。

(ただ、これはC++というよりCの知識な気がする・・・)

C++で回答した人のコードをいくつか見たところ、defineマクロで宇宙語をしゃべっている人が多くて、面食らいました。