
大学で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で質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) VBAのユーザーフォームのテキストボックスに入力制限をしたい 6 2022/11/15 08:28
- Visual Basic(VBA) 集めたシートのシート名を変更したい。 下記のコードでサブフォルダにあるファイルのSheet3を集めて 6 2022/08/23 10:38
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語 プログラムのエラー 1 2023/02/11 20:31
- C言語・C++・C# C#テキストボックスの文字を配列にいれてその後表示する 4 2022/07/17 04:47
- Visual Basic(VBA) ファイル全てを .xlsm に変更したところ、プログラムが途中で落ちてしまっています 17 2022/12/07 12:03
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- Visual Basic(VBA) サブフォルダ(データ)にある複数の.xlsxファイルのSheet3のA2セルの値で01から左側をB2 2 2022/08/14 15:46
- Excel(エクセル) Excelにて、フォルダ内のTextファイルをマクロで統合すると文字化けしてしまう時の解消コード 4 2023/01/01 07:32
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
strtok
-
csvファイルの読み取り
-
#defineが使用するメモリ領域に...
-
プログラミングの授業の課題です
-
配列から構造体へデータコピー
-
fatal error LNK1120: 外部参照...
-
C言語
-
空白を含んだ文字列がうまく格...
-
WinInetのInternetOpenUrl関数...
-
char型2つを結合し、short型に...
-
【C言語】全角文字の配列を、全...
-
C言語で複数列のデータを1列の...
-
数字以外が入力されたらエラー...
-
「Aに対するBの割合」と「Aに対...
-
10個出力で改行したいのですが...
-
C言語での引数の省略方法
-
複数桁10進数の*桁目だけを抽出...
-
Aの値からBの値を除するとは??
-
ラグランジュの補間法のCプログ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
Enterキーを押されたら次の処理...
-
【C言語】全角文字の配列を、全...
-
#defineが使用するメモリ領域に...
-
C言語で複数列のデータを1列の...
-
printf による16進表示について
-
char型2つを結合し、short型に...
-
空白を含んだ文字列がうまく格...
-
矢印キーを押下してコンソール...
-
C++で指定文字列のカウント方法...
-
コマンドファイルから、ビット...
-
C言語のプログラムで、途中で止...
-
終了条件Ctrl+zについて,結果表...
-
配列への文字列の格納について
-
困ってます!書き方がわかりま...
-
ファイルから数字列を16進数の...
-
fread(),fwrite()等について
-
0x8, スペース, 0x8をプログラ...
-
static付き宣言の初期化
-
構造体メンバの初期化
-
c言語で文書を読み込み、単語の...
おすすめ情報