質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

2回答

2446閲覧

ファイルを読み込み,正規表現で条件を絞った時の単語出現頻度を出力するプログラムを作成したい

wagashi_157

総合スコア51

ファイル

ファイルとは、文字列に基づいた名前又はパスからアクセスすることができる、任意の情報のブロック又は情報を格納するためのリソースです。

正規表現

正規表現とは特定の文字列によるパターンマッチングを行う際に用いられる宣言型プログラミングです。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/06/25 15:39

###実行したいプログラム・問題点
コマンドラインで指定したファイルを読み込んで,正規表現でアルファベットと+の文字だけから構成される単語のみを抽出して,出現回数を数え,stringの小さい順に出力するプログラムを作成したいのですが,コンパイルはできるものの思ったような結果が出てきません。
ちなみに以下の通りにプログラムを作成しようと考えています。
(1)ファイル内の⽂章には,句読点や数字や記号が含まれるが,正規表現を使って,上の条件の単語のみを抽出する(トークンの取得を利用する(std::regex_token_iterator)。
(2)さらに抽出した単語の出現回数を調べるために,mapを使って,単語と出現回数をpairにして,格納する。
(3)ファイルを全て読み終わったら,単語と出現回数をアルファベット順に表⽰する。
(4)また,ファイルの⾏数,単語の総数,出現した単語の種類数を表⽰する。
(5)mapは,第⼀引数(単語)の順(アルファベット順)に表⽰されるが,出現回数順にソートして,出現回数の多い上位10位までの単語を表⽰したい。これを実現するため,mapのデータを,std::pair< 単語,出現回数>を要素に持つ,vectorにコピーする,次に,vectorをSTLのsortを使って,出現回数の多い順に並べ替え,上位10位までの単語を,出現回数とともに,表⽰する.
※(5)は方法すら分からないので教えていただきたいです。
どこに原因があるのか教えてください。宜しくお願いします。
###実行結果・プログラム

---- Read file : C++.txt : 14 ---------- Total line num : 1628828596 Total word count : 6804778 map.size : 35 ----------

C++

1#include<iostream> 2#include<map> 3#include<cctype> 4#include<regex> 5#include<utility> 6#include<fstream> 7using std::cout,std::string; 8auto normalize(string s) { 9 if (!std::isalpha(s.back())) 10 s=s.substr(0,s.size()-1); 11 return s; 12} 13int main(int argc,char *argv[]) { 14 string filename{argc>1?argv[1]:"C++.txt"}; 15 std::ifstream fin(filename.c_str()); 16 string s; 17 auto sb{s.cbegin()},se{s.cend()}; 18 std::regex r{"[a-z+]*"}; 19 cout<<"---- Read file : "<<argv[1]<<"\n"; 20 std::sregex_token_iterator p{sb,se,r,0}; 21 std::sregex_token_iterator e; 22 std::map<string,int> words; 23 int line,word; 24 for (;getline(fin,s);) { 25 ++line; 26 ++words[normalize(s)]; 27 } 28 for (; p!=e; ++p) { 29 auto c{words.find(*p)}; 30 cout<<c->first<<": "<<c->second<<"\n"; 31 word+=c->second; 32 } 33 cout<<"----------\n"; 34 cout<<"Total line num : "<<line<<"\n"; 35 cout<<"Total word count : "<<word<<"\n"; 36 cout<<"map.size : "<<words.size()<<"\n"; 37 cout<<"----------\n"; 38}

######C++.txt

C++ (/ˌsiːˌplʌsˈplʌs/) is a general-purpose programming language created by Bjarne Stroustrup as an extension of the C programming language, or "C with Classes". ... As of 2021 C++ ranked fourth on the TIOBE index, a measure of the popularity of programming languages, after C, Java, and Python.[26]

###試したこと
まず,正規表現に間違いがあると思い,見直しました。*pだけ出力させてみたところ何も出力されませんでした。
###補足
C++17を利用しています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

とりあえず、正常動作しない原因(コードの誤り)を列挙しておきます。

これだと長さ0でもマッチしてしまいます。また、英大文字がヒットしません。

C++

1 std::regex r{"[a-z+]*"};

空文字列sに対して正規表現による検索処理の準備をしていますが、この状態でsを書き換えても、書き換えられたsに対する検索処理を実施してくれるわけではありません。sが書き換わるたびに毎回pを作り直す必要があります。

C++

1 string s; 2 auto sb{s.cbegin()},se{s.cend()}; 3 std::regex r{"[a-z+]*"}; 4 std::sregex_token_iterator p{sb,se,r,0}; 5 std::sregex_token_iterator e;

linewordも初期化されていないので、どのような値になるのかわかりません。

C++

1 int line,word;

wordsに単語ではなく行を登録してしまっています。

C++

1 for (;getline(fin,s);) { 2 ++line; 3 ++words[normalize(s)]; 4 }

wordsには行が登録されているので、検索した単語をfindしても見つかることはありません。

C++

1 for (; p!=e; ++p) { 2 auto c{words.find(*p)}; 3 cout<<c->first<<": "<<c->second<<"\n"; 4 word+=c->second; 5 }

投稿2021/06/25 22:47

actorbug

総合スコア2431

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

C++

1#include <iostream> 2#include <map> 3#include <vector> 4#include <algorithm> 5#include <regex> 6#include <utility> 7#include <fstream> 8 9using std::cout, std::string; 10 11int main(int argc, char* argv[]) { 12 string filename{ argc > 1 ? argv[1] : "C++.txt" }; 13 std::ifstream fin(filename); 14 std::map<string, int> words; 15 16 string s; 17 while ( getline(fin, s) ) { 18 std::regex r{ "[a-zA-Z+]+" }; 19 std::sregex_token_iterator p{ s.cbegin(), s.cend(), r, 0 }; 20 std::sregex_token_iterator e; 21 for ( ; p != e; ++p ) { 22 ++words[p->str()]; 23 } 24 } 25 26 std::vector<std::pair<string,int>> hist(words.begin(), words.end()); 27 std::partial_sort(hist.begin(), hist.begin()+10, hist.end(), 28 [](const auto& x, const auto& y) { return x.second > y.second; }); 29 for_each(hist.begin(), hist.begin()+10, 30 [](const auto& item) { std::cout << item.second << " : " 31 << item.first << std::endl; }); 32}

投稿2021/06/25 21:42

編集2021/06/25 21:57
episteme

総合スコア16612

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問