文字列の保存と比較について

[戻る]
nomy 2004/09/04(土) 16:09:47
初めまして。nomyと申します。初心者に近いです・・・。
早速質問させていただきます。
今、テキストファイル(単語の羅列でスペースで区切られたもの)、例えば

A ○○
B △△
C ●●

を○○と△△があったらAとBを連結し、

AB ○○+△△
C ●●

と表示するプログラムに挑戦しています。
一番いい方法か分からないけど、テキストファイルを読み込み

A
○○
B
△△
C
●●

という形のファイルにして、それをchar型の配列で単語ごとに格納していき比較していこうと
思ったのですが上の状態のテキストの形状から格納することができません。何か方法はあります
でしょうか?

while (fin.getline(ss, 256)){cout << ss << '\n'}

というのが調べたらあったのでこれを改良したらできるかと思ったのですが上手くいきませんで
した。
また、stringというものを見つけ、使えそうかな?と思いstringでも挑戦しました。テキスト
ファイルに保存されている単語数は数が多いので無理だと判断してしまいました。stringを使
い配列みたいに単語を格納して比較するやり方はあるのでしょうか?

支離滅裂で申し訳ありませんが、こういうやり方もあるというヒントでもいいのでご回答お願い
いたします。

dairygoods 2004/09/04(土) 16:45:48
> A ○○
> B △△
> C ●●
これが、「単語の羅列でスペースで区切られたもの」の例に見えませんので、
結局どうしたいのか良く分かりません。

例えば、次のようなファイルだったらどうなるのですか?
apple orange grape strawberry melon

あと、環境を記載してください。

KING・王 2004/09/05(日) 12:58:05
> while (fin.getline(ss, 256)){cout << ss << '\n'}
>
>というのが調べたらあったのでこれを改良したらできるかと思ったのですが上手くいきません
でした。

どのように上手くいかなかったのですか?
あなたが何が出来ていないのかもわかりません。

まず、あなたが、
(A)どのようなことをしたいのか?
(B)そのために、どのような記述をしたのか?
(C)そしてどのような結果を期待したのか?
(D)しかし、実際にはどうなったのか?
を、明確にして下さい。
これらの情報がないと、的確の解答が得られません。

ある程度、(A)を予想して答えようと思いましたが、dairygoodsさんが、
> これが、「単語の羅列でスペースで区切られたもの」の例に見えませんので、
> 結局どうしたいのか良く分かりません。
と指摘されているように、前提条件がわからないため、(A)の予想もつきませんので、答えよう
がありません。

さらに、この前提条件がわからないため、
> また、stringというものを見つけ、使えそうかな?と思いstringでも挑戦しました。テキス> ファイルに保存されている単語数は数が多いので無理だと判断してしまいました。stringを
使
> い配列みたいに単語を格納して比較するやり方はあるのでしょうか?
とあっても、あなたが何をどのようにしたのかも予想がつかず、間違いや適切な方法の指摘しよ
うもありません。

再度、あなたがしたいことなどを整理して、質問しなおしてください。

nomy 2004/09/06(月) 11:00:48
説明不足が多くて申し訳ありません・・・。

A ○○
B △△
C ●●

Aは単語で、○○はAの説明文みたいなものです。なので、
> 例えば、次のようなファイルだったらどうなるのですか?
> apple orange grape strawberry melon
こういった単語の並びはありません。あるとすれば、

apple orange
grape strawberry
melon ・・・

という感じです。orangeという言葉を探している時、次の列でstrawberryがあれば

applegrape orange+strawberry
melon ・・・

となります。なければそのまま次の列へいきます。

**********************************************

> (A)どのようなことをしたいのか?
@テキストファイルを読み込む。
Aapple orange grape strawberry melon・・・の順番で配列に文字列を格納。
B探している文字列があった時は前の文字列と後ろの文字列を連結。
C全て連結され終わったらテキストファイルで保存。
が全体の流れです。

@〜Cをクラスを使い記述していきました。
@では
void keitaiso::file_nyuryoku(char ss[256], char filename[80])
{
    ifstream fin;
    cout << "ファイル名=";
    cin >> filename;
    fin.open(filename);
    if (!fin)
    {
        cout << "ファイルをオープンできません\n";
        return 1;
    }
    while (fin >> ss)
    {
        cout << ss << '\n';
    }
    fin.close();
    return 0;
}
という記述をしました。
apple 
orange 
grape 
strawberry 
melon
となるようにしたいのですが、この時点でエラーが出て「オーバーロードされたメイン関数
が'<Unknown>'にありません」と出ます。

Aですが、apple orange grape strawberry melonを格納するところが今行き詰っているとこ
ろです。2次元配列にすればできるんじゃないかと思ったので

void keitaiso::file_kakunou(char aa[][])
{
    ifstream fin;
    fin.open(filename);
    if (!fin)
    {
        cout << "ファイルをオープンできません\n";
        return 1;
    }
    while (fin.getline(ss,80))
    {
        char[][] << ss << '\n';
    }
        fin.close();
    return 0;
}

char[0][256] = void keitaiso::file_kakunou(char aa[])
{
    ifstream fin;
    
    fin.open(filename);
    if (!fin)
    {
        cout << "ファイルをオープンできません\n";
        return 1;
    }

    while (fin.getline(ss,80))
    {
        char aa[][]<< ss << '\n';
    }
    for(i = 0; i < fin; i++)
    {
            aa[i][256];
            fout << aa[i][256] << endl;
    }
    fin.close();
    return 0;
}

ここで目的としていることは

char[0][256] = apple
char[1][256] = orange
char[2][256] = grape 
char[3][256] = strawberry 
char[4][256] = melon

となることです。

whileの部分で格納しているつもりなのですが[][]の中をどう記述すればいいのか分かりません
でした。while


> あと、環境を記載してください。

nomy 2004/09/06(月) 11:06:14
間違えて送信してしまいました・・・。
(続きです)
whileの部分で格納しているつもりなのです。[][]の中をどう記述すればいいのか分かりません
でした。while以下が変なのはわかっているんですが・・・。

> あと、環境を記載してください。
環境というのはVC++6.0というので良いのでしょうか?

PATIO 2004/09/06(月) 11:49:13
char[0][256] = void keitaiso::file_kakunou(char aa[])
{

こういう記述が出てくると言うことは、C++の知識そのものが足りないと思います。
というか、C言語も多分ご存知ではないのではないかと思います。
プログラミングをするには少なくとも言語の知識と言うのが必要です。
C++言語でプログラミングをするのであれば、
少なくとも一度はC++言語の入門書を通読する事をお勧めします。
演習問題が付いているタイプの本であれば、それを全て解いてみたほうが良いです。
C++言語の基礎的な知識がある程度ついてからステップアップしていかないと
一足飛び、やろうとしても誤解したまま覚えてしまうかもしれません。

因みにVC++の入門書は開発環境の入門書なので言語の入門書としては適切では
ありません。言語の入門書は言語の入門書で別に必要です。

PATIO 2004/09/06(月) 11:51:02
あら、日本語が変。

誤)
一足飛び、やろうとしても誤解したまま覚えてしまうかもしれません。

正)
一足飛びにやろうとしても誤解したまま覚えてしまうかもしれません。

dairygoods 2004/09/06(月) 12:12:06
プログラムのロジックを考える以前に、
C/C++の文法を確かなものとする必要がありそうですね...

この場で文法について逐一解説する余裕はありませんので、
参考ソースだけ載せておきます。

#include <iostream>
#include <fstream>
#include <string>
#include <vector>

using namespace std;

struct entry
{
    string word;    // 単語
    string meaning; // 意味
};

void perform(const char* input_filename)
{
    vector<entry> entries;

    ifstream in(input_filename);
    while (true) {
        entry e;
        if (!getline(in, e.word, ' ') ||  // 空白まで読む
            !getline(in, e.meaning, '\n')) // 行末まで読む
            break;

        if (!entries.empty()) {
            entry& last = entries.back();
            if (last.meaning == "○○" && e.meaning == "△△") {
                // 一個前のデータにくっつける
                last.word += e.word;
                last.meaning += e.meaning;
                continue;
            }
        }
        entries.push_back(e);
    }

    for (int i = 0; i < entries.size(); ++i) 
        cout << entries[i].word << ' ' << entries[i].meaning << endl;

}

void main()
{
    perform("ファイル名");
}

Bosscat 2004/09/06(月) 12:51:25
う〜む、、、遣りたい事が良くわからない。
インプットとアウトプットを最初に書いて貰えると解り易いと思う。

質問が旨くなると良い回答がもらえますよ。。。

で、、質問の内容ですが以下の条件がハッキリしません。
[インプット側]
・必ずスペース区切り?
・改行の意味は?
[アウトプット側]
・1ワード毎に改行する?
[処理]
・並び替え条件に優先度は無い?

次に、何を質問しているのかが判りません。
・ファイル読み込み?
・ワードの特定アルゴリズム?
・並べ替えアルゴリズム?
・ファイル出力方法?
・コンパイルエラー?

以上

nomy 2004/09/06(月) 14:36:29
> char[0][256] = void keitaiso::file_kakunou(char aa[])
この記述はコピペした時のミスだと思います。自分でもC,C++の知識がかなり乏しいことは分か
っているのですが・・・。

> で、、質問の内容ですが以下の条件がハッキリしません。
> [インプット側]
> ・必ずスペース区切り?
はいそうです。
> ・改行の意味は?
テキストファイルが二つの文字列ごとに改行されている意味ということでしょうか?それとも前
半のソースで文字列ごとに改行して表示しようとしていることでしょうか?これは、getlineを
使えば格納しやすくなるかと思ったからです。
> [アウトプット側]
> ・1ワード毎に改行する?
○○(スペース)△△(改行)
●●(スペース)▲▲(改行)
・
・
・
という感じで出力できるようにしたいのです。
> [処理]
> ・並び替え条件に優先度は無い?

> 次に、何を質問しているのかが判りません。
@テキストファイルの文字列を配列に格納するのはどのようにしたらいいか。
A「オーバーロードされたメイン関数が'<Unknown>'にありません」というエラーは何が原因と
考えられるか。

dairygoodsさん、参考ソースをできる限り理解してみようと思います。

文章能力がなくて本当にすみません。

Bosscat 2004/09/06(月) 16:28:52
@ 
dairygoodsさんのコードの通り
stringのままで問題無いと思いますが、
配列にしたいのならmemcpyすれば良い。

直接配列に読みたかったらこんな感じ
char buf[適当]; // 読み込みバッファ
fstream fsi;
fsi.open(filename,ios::in);
for(int i=0;!fsi.eof();i++){
    int num = fsi.read(buf,適当).gcount();
    本当のバッファにコピー
}
fsi.close();


ただ、「ファイルポインタ」「シークポイント」なんてキーワードを
理解していないのならば
fopen()-> fseek()-> fread()-> fclose() 辺りを勉強した方が良いと思います。

A
原因はmain() or WinMain()が無い。
ちゃんと有るのに・・・って場合は、もっと他にエラーがあるでしょうから、
そっちを潰せば消えます。

KING・王 2004/09/07(火) 08:37:50
Aに関しては、エラーメッセージが、
error C2511: 'funcA' : オーバーロードされたメンバ関数が '<Unknown>' にありません。
の間違えではないでしょうか?

下記のようなプログラムをコンパイルすると、このエラーが出ました。
この原因は、Classの宣言で記述したメンバ関数(のプロトタイプ)と、実際にメンバ関数を記述
した際に、
引数の数や型などが不一致しているために発生します。

下記の例では、クラスの宣言内では、メンバ関数(1)と一致する宣言(プロトタイプ)ですが、
メンバ関数(2)と一致する宣言(プロトタイプ)がクラスの宣言ないにありません。
メンバ関数(1)とメンバ関数(2)は同じ関数名であるため、
コンパイラはメンバ関数(2)はメンバ関数(1)がオーバーロードされた関数と認識します
が、
宣言(プロトタイプ)が見つからないため、エラーを発生しているのです。


出来れば、エラーメッセージの前の“C2511”なども、記述していただけると、
その番号を元に、MSDN等でメッセージの内容を調べることもできますので、
記述していただければありがたいと思います。
#エラーメッセージを写し間違えても、この番号で正しいエラー内容を確認できますし。

#include <iostream>

class Ctest{ // クラスの宣言
public:
    int funcA( int a );
};

// メンバ関数(1)
int Ctest::funcA( int a )
{
    return a;
}

// メンバ関数(2)
int Ctest::funcA( int a, int b)
{
    return a+b;
}

int main( void )
{
    return 0;
}

古いスレッドには追加発言できません。