Gobble up pudding

プログラミングの記事がメインのブログです。

MENU

C++らしい入出力、数値・文字列相互変換まとめ

スポンサードリンク


まとめるつもりはなかったのですが、
たまたま目にとまったメールで問題が書いてあって
おお、なんかサンプルを書くには良さそうと思い、
CodeZineのメールマガジンに書いてあったサンプルを利用させていただきます。
よくあるTopCoderのようなあのレベルの問題ではなく、
これ解けないとやばいだろ…って程度の問題しか出てません。
しかし、どういうわけか、効率的に速いコードを書かないとダメ
という謎の暗黙ルールがあるようです。

というわけで今回は
C++らしい入出力、数値・文字列相互変換まとめ

C++を使ってるのにfopen()やらsprintf()を使いたくないですよね。
まぁ、実態としてはそれが多いのですが、まぁそれでもいいんですけどね。
それにしてもiostream, fstream, sstreamの人気のなさはなんなんでしょう。
やっぱり似たような不思議な名前と妙な演算子を使っているからでしょうか。
このC++流儀のやり方は後続の言語、JavaやC#を見ると流行ってないっぽいですね。
一方JavaやC#の入出力系は名前的にわかりやすいのですが、
クラス名長い……Bufferedとか書くとfとrの数はあっているかとか思うわけで…
いやフツーIDE使うから関係ないか。
また、数値→文字列はsprintf(), 文字列→数字はatoi()ですよね。
atoiの問題点はintの範囲を超えたらダメなんでかわりになんでか見た目が全然違う
strtol()やその亜種をつかうことになります。。。が
C++らしいやり方を覚えると幸せになれます。たぶん。覚えんのめんどくさいけど。
このへんもC#は優れていますよね。
int.ToString(), int.Parse(string)なんてわかりやすい書き方できますから。
Javaはラッパークラスがあってアレだけど…いやなんでもない。

C++の入出力クラス

なんだか名前が紛らわしいけど
ヘッダーとクラスはこんな構成になっています。

http://www.cplusplus.com/reference/ios/

数値・文字列相互変換

http://www.cplusplus.com/reference/sstream/istringstream/
http://www.cplusplus.com/reference/sstream/ostringstream/
istringstream → atoi()などの代わり
ostringstream → sprintf()などのかわり

サンプル問題の出所


CodeZine(コードジン)
CodeZine News号外 2014-09-24

サンプル1

問題

1からnまで連続する正の整数があります。
それらの中に「7」がいくつあるか数えてください。

ん…全角で数字を書いているのは何か意図があるのかと勘ぐってしまいますが、
とりあえずフツーに解きましょう。
ちなみに模範解答はこれらしいです。
https://codeiq.jp/wp/feedbacksample/
模範解答見て気づきましたが、例題がでかい数のようでした。
なら、そう書いとけよと、でかい数でも早く解けるようにと。
そういう前提がなければ「悪いコード」は別に悪いコードでないはず。
ちなみに僕のものは早く答えを出せるようには書いてません。

解答例(というかC++の入出力と数値文字列相互変換例)


サンプル2

問題

【元になる数列】
5, 6, 7, 8, 9, 10, 11, 12, 13, ...
のように、5からはじまる連続した整数があります。
このとき、10以降は2桁以上の数が続きますが、これらの数をすべて1桁ずつ区切っていきます。

5, 6, 7, 8, 9, 1, 0, 1, 1, 1, 2, 1, 3, ...

このような数列について考えてください。

【問題】
上記の数列について、前からn番目の数字を効率よく求めるプログラムを書いてください。
(先頭を1番目とします)

ん?線形探索以外になんか方法あるのかな?30分じゃちょっと思いつかない…
と思って問題を見てみると、
今気づきました。解答はn番目の数字を求めるのだそうです。
問題の出し方が悪すぎるので勘違いしました。
この後に続きがあって
数字を1ケタで1文字ずつ改行でファイル出力
してくれというように書いています。
それが回答だと勘違いしてましたのでそれを解答とします(笑)
例によって回答は楽に書くことをモットーとしていて巨大な数値は想定していません。

解答例(というかC++の入出力と数値文字列相互変換例)