大学でC++ builder を使った授業を受けておりましたが、いつも早く終わっていた(教科書を写すだけなのでタイピングが早ければすぐ終わる)のをC++が得意と勘違いされ、試験を免除する代わりにテキストマイニングに関連するソフトを作るという課題を言い渡されました。
テキストマイニングの意味は大体理解し、掲示板などからとってきたテキストデータの中にある「美味しい」と「不味い」の文字列の個数を数え上げるプログラムを作ろうと考えていますが、やり方が全くわかりません。授業では「学生のためのC++builder」という主に数値計算を扱った教科書の例題を実行するというもので、テキストデータの扱い方はほぼまったくしていません。
今までにやった中でファイルを扱ったようなものとしては
void __fastcall TForm1::Button1Click(TObject *Sender)
{
OpenDialog1->Execute();
//入力ファイル用ストリームのオブジェクト(fin)を生成する
ifstream fin;
fin.open(OpenDialog1->FileName.c_str());
//エラー対策
if(!fin){
ShowMessage("ファイルのオープンに失敗しました!!");
exit(1);
}
double sintyo;
char name[20];
//ファイルから氏名、身長データを読み込む
fin>>name>>sintyo;
while(!fin.eof()){
StringGrid1->Cells[0][n]=(String)name;
StringGrid1->Cells[1][n]=FormatFloat("###0.0",sintyo);
data[n]=sintyo;
n++;
fin>>name>>sintyo;
}
fin.close();
}
だけであり、それを元にして改良するということができそうにありません。
最初からチェックしていって、「美味い」など指定文字列があればdに1を加えるなど、アルゴリズムを考えること自体はできるとは思います。
しかも期限は一週間となっています。
どなたか方法をお教えいただけませんでしょうか。
No.3ベストアンサー
- 回答日時:
完全に答えですけどプログラム作ってみました。
***実行前に行う事***
実行ファイルと同じフォルダに
test.txt
というファイルを置いてください。
これは検索の対象となる文章を書いたファイルです。
よくわからない場合は以下の手順にそって行ってください。
まず
「C言語入門。C言語について学んでいます。」
と書いて
test.txt
という名前で保存。(保存する場所は実行ファイルと同じフォルダ)
以下のプログラムをコンパイル
#include <stdio.h>
#include <string.h>
#define BUFFER_SIZE 10000
char string[BUFFER_SIZE];
void kensaku(void){
struct s{
char st[100];
int counter;
};
struct s string2[100];
int i=0,j=0,n,count=0,h_count=0;
char string3[100];
printf("検索終了を示す文章を入力してください。(この文章は検索出来ません)\n");
scanf("%s",&string3);
printf("設定完了。検索終了時には「%s」と入力してください。\n",string3);
while(1){
printf("\n*********************************************\n");
printf("検索したい文章は?(終了は「%s」と入力)\n",string3);
scanf("%s",&string2[h_count].st);
if(strcmp(string2[h_count].st,string3)==0)
break;
n = strlen(string2[h_count].st);
while(string[i]!='\0'){
if(string[i]==string2[h_count].st[j]){
j++;
if(j==n)
count++;
}
else{
j=0;
}
i++;
}
printf("「%s」の検索ヒット数[%d]回\n\n",string2[h_count].st,count);
string2[h_count].counter=count;
h_count++; i=0; count=0;
}
printf("検索終了\n\n");
i=0;
while(i<h_count){
printf("「%s」\tの検索ヒット数\t[%d]回\n",string2[i].st,string2[i].counter);
i++;
}
return;
}
void main(){
char string2[BUFFER_SIZE];
FILE *fp;
fp = fopen("test.txt", "r");
if ( !fp )
printf("ファイルオープンエラー\n");
else{
while( fscanf(fp, "%s" , string2) != EOF){
strcat(string,string2);
}
}
kensaku();
fclose(fp);
}
コンパイル画面に最初
「検索終了を示す文章を入力してください。(この文章は検索出来ません)」
と出ますから何か自分で決めたキーワードを入力してください。
(例:finish)
次に
「検索したい文章は?」
と出ますから、そしたら
例えば「言語」と入力してエンター押します。
すると
「言語」の検索ヒット数[2]回
と表示されます。また
「検索したい文章は?」
と出ますから連続で検索したい場合はまた、続けます。
終わりたい場合は最初に決めた文字列を入力。例ではfinish。
すると検索結果一覧が表示され、終了します。
一度コンパイルしてみて、実行できるかどうか試してください。
注意:なお、プログラムは見やすいように、tabインデント(字下げ)が全角スペースに置換してありますから、
お使いのソフトで全角スペースをtabインデントなどに置換してからコンパイルしてください。
全角文字があるとエラーになると思うので。
コンパイルできなかった場合や、解らない事があった場合はまた聞いてください。
No.5
- 回答日時:
BorlandC++Builderを使ってるならAnsiStringを使うという選択肢もありますね。
int SearchWordInString( const AnsiString& src, const AnsiString& word )
//srcからwordを検索しその数を返す
{
int count = 0, at = 0, len = word.Length();
while ( int pos = AnsiString(src.c_str()+at).AnsiPos(word) )
{
++count;
at += pos-1+len; //AnsiString::AnsiPosは1始まり
}
return count;
}
//呼び出し関数(どこかのイベントハンドラ)内で
String word1 = "美味しい", word2 = "不味い"; //TEditあたりで取得可
TStringList* list = new TStringList;
list->LoadFromFile( "sorce.txt" ); //ファイル名はTOpenDialogで取得可
int count1 = SearchWordInString( list->Text, word1 );
int count2 = SearchWordInString( list->Text, word2 );
ShowMessage( word1 + "の検索結果:" + count1 );
ShowMessage( word2 + "の検索結果:" + count2 );
delete list;
C++で文字列を扱う場合、複数の選択肢があります。
1.Cで標準的なchar*を使う No.3の方の回答
2.C++標準ライブラリのstd::stringを使う No.2の方の回答
3.開発環境独自の文字列オブジェクトを使う
BorlandC++Builderの場合、これがAnisString(String)
C++でプログラミングをする以上、2.か3.で考えるべきです。
1.も扱えるように勉強したほうが良いのですが1週間の期限内では無理でしょう。
2.3.にせよ1週間で全てをマスターすることは土台無理がありますから、とりあえずはテキストマイニングを実装する上で必要な機能だけを理解するしかないでしょう。
おそらく初心者にとって楽なのは3.
しかしC++標準ライブラリの使い方がある程度身についているのなら2.の方が効率的なコードが書けると思います。
この辺はご自分で判断してください。
あとは分からないことがあれば
「このライブラリを使って、このような文字列に対してこのような操作をしたい。どうすればよいか?」
と具体的に質問してください。
文字列操作について1から10まで全てレクチャーするのは回答者側としても不可能です。
No.4
- 回答日時:
↓下にプログラムを投稿した者です。
文字列の扱いやファイルオープンなど基本的な事も難しいようですので、1から説明していきますね。
投稿は下の投稿から先にお読みください。
#include <stdio.h>
#include <string.h>
//BUFFER_SIZEはただの定義で書かなくても直接かいてもOK
#define BUFFER_SIZE 10000
char string[BUFFER_SIZE];
//検索するための関数です。
void kensaku(void){
//構造体を使っています。もしも構造体についてわからなければ別に聞いてください。
struct s{
char st[100];
int counter;
};
struct s string2[100];
int i=0,j=0,n,count=0,h_count=0;
char string3[100];
printf("検索終了を示す文章を入力してください。(この文章は検索出来ません)\n");
//検索終了を示すキーワードを格納
scanf("%s",&string3);
printf("設定完了。検索終了時には「%s」と入力してください。\n",string3);
while(1){
printf("\n*********************************************\n");
printf("検索したい文章は?(終了は「%s」と入力)\n",string3);
//検索する言葉を格納
scanf("%s",&string2[h_count].st);
//入力された言葉が検索終了のキーワードと同じなら終了
if(strcmp(string2[h_count].st,string3)==0)
break;
//検索する言葉の文字列の長さを調べる
n = strlen(string2[h_count].st);
//検索対象が終わりになるまで調べる
while(string[i]!='\0'){
//検索対象の中に検索する言葉と同じデータがあれば
if(string[i]==string2[h_count].st[j]){
j++;
if(j==n)
//もしも検索する言葉と同じながさだけデータが一致すれば検索する言葉があったことを示すため
カウントする
count++;
}
else{
j=0;
}
i++;
}
printf("「%s」の検索ヒット数[%d]回\n\n",string2[h_count].st,count);
//検索ヒット数がいくらあったか構造体に格納
string2[h_count].counter=count;
//初期化
h_count++; i=0; count=0;
}
printf("検索終了\n\n");
i=0;
//検索結果を一覧表に表示
while(i<h_count){
printf("「%s」\tの検索ヒット数\t[%d]回\n",string2[i].st,string2[i].counter);
i++;
}
return;
}
void main(){
char string2[BUFFER_SIZE];
FILE *fp;
//ファイルオープン
fp = fopen("test.txt", "r");
//開けなかったら
if ( !fp )
printf("ファイルオープンエラー\n");
//開けたら
else{
//1行ずつ読み込み配列に文字列を格納
while( fscanf(fp, "%s" , string2) != EOF){
//読み込んだ文字列を全部一つの配列に連結させる
strcat(string,string2);
}
}
//検索する関数を呼ぶ。
kensaku();
fclose(fp);
}
以上です。何かわからないことがあれば遠慮なく聞いてください。
No.2
- 回答日時:
# そのまま提出しても質問攻めを喰らうでしょう
/*
* 標準入力から得られた文字列から
* "美味しい"と"不味い"を検索し
* それぞれの個数を出力する
*/
#include <string>
#include <iostream>
#include <sstream>
int count_str(const std::string& source, const std::string& target) {
std::string src(source);
int result = 0;
std::string::size_type pos;
while ( (pos = src.find(target)) != std::string::npos ) {
++result;
src.erase(0, pos+target.size());
}
return result;
}
int main() {
std::ostringstream ostream;
ostream << std::cin.rdbuf();
std::string source = ostream.str();
std::string target;
target = "美味しい";
std::cout << "contains " << count_str(source, target) << " of " << target << std::endl;
target = "不味い";
std::cout << "contains " << count_str(source, target) << " of " << target << std::endl;
}
お礼が遅くなり、誠に申し訳ありません。
オブジェクト指向の意味すらわからず、理解できませんでした。
今では、include の後に using namespace std; をつければstd:を省略できることもわかるようになりました。
ありがとうございました。
No.1
- 回答日時:
Cが専門なのでC++はあまり分からないのですが、
ヒントになるのであればと思ってアドバイスさせていただきます。
「最初からチェックしていって・・・」というのはできるということなので、それを前提に進めます。
要は最初からチェックしてく方法と同じ事を各変数毎にやればいいのです。
サンプルだと
fin>>name>>sintyo;の後に比較すればいいかと思います。
ただ、サンプルのやり方だと掲示板データの様な固定長でないものでも大丈夫なのでしょうか?(前述したとおり、私はC++がわからないのです・・・)
各項目が固定長でないとダメな気がします。
ダメなのなら、「最初からチェックしていって・・・」のやり方でやるか、デリミタ(区切り文字)を読み取って変数に格納して比較・・・とやらなければいけません。
ネットで「C++ ファイル操作」「C++ 文字列比較」で検索すればサンプルが沢山出てくると思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
初めて自分の家と他人の家が違う、と意識した時
子供の頃、友達の家に行くと「なんか自分の家と匂いが違うな?」って思いませんでしたか?
-
フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
あなたが普段思っている「これまだ誰も言ってなかったけど共感されるだろうな」というあるあるを教えてください
-
映画のエンドロール観る派?観ない派?
映画が終わった後、すぐに席を立って帰る方もちらほら見かけます。皆さんはエンドロールの最後まで観ていきますか?
-
海外旅行から帰ってきたら、まず何を食べる?
帰国して1番食べたくなるもの、食べたくなるだろうなと思うもの、皆さんはありますか?
-
天使と悪魔選手権
悪魔がこんなささやきをしていたら、天使のあなたはなんと言って止めますか?
-
AnsiStringについて
C言語・C++・C#
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
Ç言語でファイルサイズを変更す...
-
C言語で複数列のデータを1列の...
-
空白を含んだ文字列がうまく格...
-
【C言語】全角文字の配列を、全...
-
HANDLEのエラー
-
WinInetのInternetOpenUrl関数...
-
#pragma warning(disable: 4996...
-
フレーム画像の連続保存について
-
2÷3などの余りについて
-
信頼区間の1.96や1.65ってどこ...
-
「Aに対するBの割合」と「Aに対...
-
C言語での引数の省略方法
-
O(n log n)について2
-
マイナスからプラスへ転じた時...
-
41.59のどちらを割っても余りが...
-
テキストカーソル位置の取得
-
fgetsなどのときのstdinのバッ...
-
プログラミング初心者です。 Py...
-
プログラムでの数字につく”f”の...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
printf による16進表示について
-
#defineが使用するメモリ領域に...
-
C言語で複数列のデータを1列の...
-
C言語のプログラムで、途中で止...
-
reallocでエラー
-
【C言語】全角文字の配列を、全...
-
構造体メンバの初期化
-
char型2つを結合し、short型に...
-
空白を含んだ文字列がうまく格...
-
VC++でSQLへSELECT文を送ったの...
-
C言語でのCSVファイルの読み出...
-
エラーについて質問です。
-
setjmp・longjmpに関しまして
-
矢印キーを押下してコンソール...
-
タイムカードのシステムを作り...
-
大量のファイルを読み込み、そ...
-
C言語、ファイル操作、fgets()...
-
Cでファイルの行数をカウントす...
-
リストの作成と出力(C言語)
おすすめ情報