stringの終端って何があるの?

投稿者: | 2017年11月15日

サークル活動でやることがないということで、CpawCTFの問題をときました。

CTFって?

CTFとは? Capture The Flag(旗取りゲーム)の略. 情報セキュリティの技術を競う競技・ゲーム. 隠された答え(Flag)をセキュリティのスキルを用いて. 探し、答えをサーバへ送信するクイズ形式が多い.

有名所だと、
ksnctf
CpawCTF
などがあります。
私がやったことは上の2つだけなので、経験が殆どないといいですが、初心者ならCpawCTFのほうが簡単かなあと思います。
今回、サークルでは延々と問題を解くというのをやってました。その中で、string使う時使えるかなあと言うのが合ったのでメモ。

その問題は、”Q14.[PPC]並べ替えろ!”です。
[blogcard url=”https://ctf.cpaw.site/questions.php?qnum=14″]
実装することは簡単、”降順にソートする”だけです。
降順にソートするなら、algorithmをincludeしてgreater使って降順にsortすればいい。
やることは単純なので、私が何で躓いたか。
“与えられる数列にカンマ(,)が入るからvectorに簡単には入れれない”
まあ、カンマがあるからダメなら、カンマ消して空白入れて一個ずつvectorにpush_backすればいい。
それもめんどくさいので、”カンマを読み込むまでstringに足していって、カンマ読み込んだらstringの中身をvectorにpush_backすればいい”と考えたわけです。
通ったコードは以下のとおりです。
[cpp]
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
using namespace std;
int main(int argc, char const *argv[]) {
string s;
cin>>s;
vector<int> v;
string num;
for(int i=0;i<=s.size();i++){
if(s[i]!=’,’) num+=s[i];
if(s[i]==’,’||s[i]==’\0’){
int n=stoi(num);
v.push_back(n);
num="";
}
}
sort(v.begin(),v.end(),greater<int>());
for(int i=0;i<v.size();i++){
cout<<v[i];
}
cout<<endl;
return 0;
}
[/cpp]
さて、問題となったのは以下の部分。
[cpp]
string s;
cin>>s;
vector<int> v;
string num;
for(int i=0;i<=s.size();i++){
if(s[i]!=’,’) num+=s[i];
if(s[i]==’,’||s[i]==’\0’){
int n=stoi(num);
v.push_back(n);
num="";
}
}
[/cpp]
最初flag作った時、if(s[i]==’,’||s[i]==’\0′)の部分のs[i]==’\0’がありませんでした。
するとどうなるか。
問題の数列を入れると、207がvectorに入らずに、flagが間違えるわけです。
それもそのはず、カンマを読み込まないとvectorに入らないような記述なわけで。
では、どうしたらいいのか。
答えは上に書いたとおりですが、何を考えたかというと、「stringの末尾って何があるんだ?」ってことです。
ググれば速攻で出てきます。
答えはヌル文字があります。
なんで文字列の最後に”\0″あると書いちゃえばstringの最後だってわかるわけですね。
まあ、文字列操作関数は次のような仕様になってるらしいので、当然なんですが・・・。
[blogcard url=”http://edu.clipper.co.jp/pg-2-16.html”]
アセンブリ言語でも、文字列の表示のとき、INT21h命令では$(24h)を読み込むまで文字列を表示っていうのがありましたね・・・。
まあこんなことで6時間ぐらい(warframeしてた時間が5時間)使いました。
うん・・・設計図落ちねえなあ・・・。

コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください