前提・実現したいこと
大相撲の勝敗が書かれたファイルを読み込んで計算をし,成績の良い順にソートした結果のファイルを吐き出すプログラムを作成したい。
発生している問題・エラーメッセージ
今,大相撲の勝敗が書かれたファイルを読み込み,勝敗を計算して成績の良い順にソートした結果のファイルを吐き出す(白星の数が同じならばそのうち黒星の数が少ない方を上に持って行く)プログラムを作成しているのですが,コンパイルできるのにも関わらず,結果を出力しようとしたらエラーが出てしまいました。以前ファイルの読み込みに関するご指摘をもとに修正したのですが,それでもSegmentation faultが表示されます。どこに原因があるのか分からないので,教えてください。特にファイルの読み込み方・クラスへの格納に自信がないので宜しくお願いします。
Segmentation fault
読み込むテキスト
######higashi.txt(一部表示)
Yokozuna Hakuhou Shiroboshi Shiroboshi Fusenpai Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Yasumi Daieishou Takarafuji Ounoshou OOzeki Shoudai Kuroboshi Shiroboshi Shiroboshi Kuroboshi Kuroboshi Kuroboshi Shiroboshi Shiroboshi Kuroboshi Shiroboshi Shiroboshi Shiroboshi Kuroboshi Kuroboshi Kuroboshi Mitakeumi Ounoshou Takarafuji Hokutofuji Wakatakakage Meisei Shimanoumi Kiribayama Daieishou Myougiryu Takayasu Takanoshou Terunofuji Takakeishou Asanoyama ...... Maegashira_Jurokumaime Kaisei Kuroboshi Shiroboshi Shiroboshi Shiroboshi Shiroboshi Kuroboshi Kuroboshi Kuroboshi Shiroboshi Kuroboshi Shiroboshi Kuroboshi Shiroboshi Shiroboshi Kuroboshi Hidenoumi Akua Tsurugishou Chiyoshouma Daiamami Akiseyama Toyoyama Chiyonoou Kagayaki Houshouryu Terutsuyoshi Kotoekou Midorifuji Chiyotairyu Tobizaru
該当のソースコード
C++
1#include<iostream> 2#include<fstream> 3#include<vector> 4#include<iomanip> 5 6class Record{ //番付, 力士の名前, 成績, 対戦相手を格納するクラス 7 std::string rank, name; 8 std::vector<std::string> score, aite; 9 public: 10 /*コンストラクタを定義*/ 11 int shiro(){ 12 int shiro{0}; 13 /*白星または不戦勝の数を計算*/ 14 for (int i=0; i<score.size(); i++){ 15 if (score[i]=="Shiroboshi"||score[i]=="Fusenshou") 16 shiro++; 17 } 18 return shiro; 19 } 20 int kuro(){ 21 int kuro{0}; 22 /*黒星または不戦敗の数を計算*/ 23 for (int i=0; i<score.size(); i++){ 24 if (score[i]=="Kuroboshi"||score[i]=="Fusenpai") 25 kuro++; 26 } 27 return kuro; 28 } 29 int yasumi(){ 30 int yasumi{0}; 31 /*やすみの数を計算*/ 32 for (int i=0; i<score.size(); i++){ 33 if (score[i]=="yasumi") 34 yasumi++; 35 } 36 return yasumi; 37 } 38 39 std::string get_r(){/*rankに対するゲッター*/return rank;} 40 std::string get_n(){/*nameに対するゲッター*/return name;} 41 std::vector<std::string> get_s(){/*scoreに対するゲッター*/return score;} 42 std::vector<std::string> get_a(){/*aiteに対するゲッター*/return aite;} 43 void set_r(std::string r){/*rankに対するセッター*/rank=r;} 44 void set_n(std::string n){/*nameに対するセッター*/name=n;} 45 void set_s(std::vector<std::string> s){/*scoreに対するセッター*/score=s;} 46 void set_a(std::vector<std::string> a){/*aiteに対するセッター*/aite=a;} 47 48 void print(){ 49 std::cout<<"Banzuke:"<<rank<<std::endl; 50 std::cout<<"Shikona:"<<name<<std::endl; 51 std::cout<<"Seiseki:"; 52 for(auto e: score) 53 std::cout<<e<<" "; 54 std::cout<<std::endl; 55 std::cout<<"Taisen_aite:"; 56 for(auto e: aite) 57 std::cout<<e<<" "; 58 std::cout<<std::endl; 59 } 60}; 61 62class Table{ //Recordをvectorに格納するクラス 63 friend Record; 64 std::vector<Record> v; 65 public: 66 void add(Record r){ 67 /*vにrを追加*/ 68 for (size_t i=0; i<v.size(); i++){ 69 v[i].set_r(r.get_r()); 70 v[i].set_n(r.get_n()); 71 v[i].set_s(r.get_s()); 72 v[i].set_a(r.get_a()); 73 v.push_back(r); 74 } 75 } 76 void print(){ 77 for(auto e : v){ 78 e.print(); 79 } 80 } 81 void sort(){ 82 for(size_t i=0;i<v.size()-1;i++){ 83 size_t max{i}; 84 for(size_t j=i+1;j<v.size();j++) { 85 /*勝敗(白星,不戦勝,黒星,不戦敗)によってvをソートする(選択ソート) */ 86 if (v[j].shiro()>v[max].shiro()) max=j; 87 if (v[j].shiro()==v[max].shiro()) 88 if (v[j].kuro()<v[max].kuro()) max=j; 89 } 90 std::swap(v[i],v[max]); 91 } 92 } 93 94 void result(std::ofstream& fout){ 95 for(auto e : v){ 96 if(e.yasumi()>0) 97 fout<<std::setw(22)<<e.get_r()<<std::setw(20)<<e.get_n()<<std::setw(5)<<e.shiro()<<"Shou"<<std::setw(5)<<e.kuro()<<"Hai"<<std::setw(5)<<e.yasumi()<<"Kyu"<<std::endl; 98 else 99 fout<<std::setw(22)<<e.get_r()<<std::setw(20)<<e.get_n()<<std::setw(5)<<e.shiro()<<"Shou"<<std::setw(5)<<e.kuro()<<"Hai"<<std::endl; 100 } 101 } 102}; 103 104 105 106std::vector<std::string> split(std::string s, char sep=' ', char sep2='\t'){ 107 std::vector<std::string> v; 108 auto iter{s.begin()}; 109 while(iter!=s.end()){ 110 /*空白(sep=' ')またはタブ(sep2='\t')で区切られているsの要素をvに格納.string(iter_first,iter)でiter_firstとiterで指定された文字の一部抽出ができる*/ 111 auto last=iter; 112 while (last!=s.end()&&(*last!=sep||*last!=sep2)) 113 ++last; 114 v.push_back(std::string(iter,last)); 115 if (last!=s.end()) 116 ++last; 117 iter=last; 118 } 119 return v; 120} 121 122void import(std::ifstream& fin,Table& table){//力士ファイルの取り込み 123 Record record; 124 int n{0}; 125 std::string rank, name, score, aite, blank; 126 while(fin){ 127 if(n%5==0){ 128 /*finからrankを取り出しrecordに格納*/ 129 getline(fin,rank); 130 record.set_r(rank); 131 } 132 else if(n%5==1){ 133 /*finからnameを取り出しrecordに格納*/ 134 getline(fin,name); 135 record.set_n(name); 136 } 137 else if(n%5==2){ 138 /*finからscoreを取り出しrecordに格納. その際split関数を用いる*/ 139 getline(fin,score); 140 split(score,' ','\t').push_back(score); 141 record.set_s(split(score,' ','\t')); 142 } 143 else if(n%5==3){ 144 /*finからaiteを取り出しrecordに格納.その際split関数を用いる*/ 145 /*recordをtableに追加*/ 146 getline(fin,aite); 147 split(aite,' ','\t').push_back(aite); 148 record.set_a(split(aite,' ','\t')); 149 table.add(record); 150 } 151 else{ 152 getline(fin,blank); 153 } 154 n++; 155 } 156} 157 158int main(){ 159 std::ifstream fin("higashi.txt"); 160 std::ofstream fout("result.txt"); 161 162 Table table; 163 import(fin,table); 164 table.print(); 165 table.sort(); 166 table.result(fout); 167 return 0; 168}
試したこと
クラス型のvectorの表し方に問題がないか見直しました。選択ソートの際,size_t n=v.size()を利用せずに表しました。そして,ファイルの読み込みではそれぞれの行から出力されるようにvectorの値に注意しながらプログラムを作成しました。行単位でファイルを読み込む際にgetline()関数を利用してプログラムを作成しました。
補足情報(FW/ツールのバージョンなど)
C++17を使用しています。
回答2件
あなたの回答
tips
プレビュー