-2

コンストラクタとデストラクタで構成される StringList というクラスがあります。私が目指しているのは、プログラムが実行されていない後でも配列内の文字列を保持できるようにすることです。これを行う方法は、コンストラクター関数にファイルから文字列を読み取らせ、それらを文字列配列 (str[]) に格納させることです。デストラクタは、現在の文字列をファイルに保存します。メモリの作成時にファイルからの読み取りと保存に問題があります。各単語を配列内の 1 つの要素にしたい。たとえば、読み取り元のファイルでは、文字列は次のように格納されます。

HELLO
MOM
DAD
FOUR
YELLOW

各単語をスロットにしたい。言い換えると。str[0] = HELLO、str[1] = MOM、str[2] = DAD など。

ここに私のコンストラクタ関数があります:

StringList::StringList()
{
    numberOfStrings=0;
    str = new string[1000000];

ifstream myfile ("Read.txt");
 if (myfile.is_open())
    {
        for (int i = 0; i < 1000000; i++)
        {
            getline(myfile,str[i]);
            numberOfString++;


        }

        myfile.close();
    }


}

ここでの問題は、 for (int i=0; i<100000;i++) の行です。これが行ったことは、要素が 100000 に達するまで各空白スペースを埋め続けることです。空白を追加して 20 まで埋めます。txt 内の実際の文字列の量まで埋める方法はありますか。ファイル?

4

3 に答える 3

4

NumberOfStrings++読み取り時に for ループの外側にある (つまり、1 回だけインクリメントされる)。std::vector<std::string>また、動的配列の代わりに使用することを検討してください。

配列の代わりに std::vector を使用したコードのバージョンを次に示します。

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

class StringList
{
public:
    StringList(): str(1000000), numberOfStrings(0)
    {
        std::ifstream myfile ("Read.txt");
        if (myfile.is_open())
        {
            for (int i = 0; i < str.size(); i++)
            {
                getline(myfile, str[i]);
                numberOfStrings++;
            }

            myfile.close();
        }
    }

    StringList::~StringList()
    {
        std::ofstream os("Read.txt");
        for (int i = 0; i <numberOfStrings; i++) 
        {
            os << str[i] << std::endl;
        }
    }

private:
    std::vector<std::string> str;
    int numberOfStrings;
};

ご覧のとおり、変更はかなり最小限です。

于 2013-07-04T01:49:52.077 に答える
1

ループが終了した後、numberOfStrings変数は一度だけ更新されます。for失敗の戻り値をチェックすることにより、読み取る行数を大量に指定する必要なく、これを単純化することもできますgetline。ファイルの終わりを超えて読み取ろうとすると、getlinefalse が返されます。

numberOfStrings = 0;
str = new std::string[1000000];
std::ifstream myfile("Read.txt");
if (myfile.is_open())
{
    std::string line;
    while(getline(myfile, str[numberOfStrings]))
        numberOfStrings++;
    myfile.close();
}

を使用すると、これをさらに単純化できますstd::vector。回答で提供されている例を拡張すると、StringList以下のようになります。

StringList.h

#include <vector>
#include <string>

class StringList
{
public:
    StringList();
    void PrintWords();
private:
    size_t numberOfLines;
    std::vector<std::string> str;
};

各文字列に 1 行で読み込む StringList.cpp

#include "StringList.h"
#include <fstream>

StringList::StringList()
{
    std::ifstream myfile("Read.txt");
    if (myfile.is_open())
    {
        std::string line;
        while(getline(myfile, line))
        {
            lines_.push_back(line);
        }
        myfile.close();
    }
    numberOfLines = str.size();
}

std::istream_itertorと を使用して各文字列に単一の単語を読み込む StringList.cppstd::copy

#include "StringList.h"
#include <fstream>
#include <istream>
#include <algorithm> // std::copy
#include <iterator>  // istream_iterator

StringList::StringList()
{
    std::ifstream myfile("Read.txt");
    if (myfile.is_open())
    {
        std::copy(
            istream_iterator<string>(myfile),
            istream_iterator<string>(),
            back_inserter(str));
    }
    numberOfLines = str.size();
}

単語を印刷する他の関数

StringList::PrintWords()
{
    for(size_t i = 0; i < numberOfLines; ++i)
    {
        std::cout << str[i] << std::endl;
    }
}

また、コードでの使用を避けることをお勧めusing namespace stdします。からすべてを現在のスコープ (通常はグローバル名前空間) にプルしstd、識別子との競合を引き起こす可能性があります。

于 2013-07-04T01:57:28.093 に答える