1

次のコードがあります。

#include <stdio.h>
#include <stdlib.h>
#include <string>
#include <vector>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <fstream>
#include <streambuf>

bool cmp(const std::string& lhs, const std::string& rhs) {
    return lhs < rhs;
}

int main(int argc, char **argv){
    /* USAGE: PROGRAM FILENAME DELIMITER */
    if (argc != 3){
        fprintf(stderr, "./program filename delimiter \n");
        exit(EXIT_FAILURE);
    }

    char *filename = argv[1];
    char *delimiter = argv[2];

    std::vector<std::string> vWords;
    std::vector<std::string> vWords_TMP;
    std::ifstream t(filename);
    std::string str((std::istreambuf_iterator<char>(t)),
                    std::istreambuf_iterator<char>());
    boost::char_separator<char> sep(delimiter);
    boost::tokenizer< boost::char_separator<char> > tokens(str, sep);
    BOOST_FOREACH (const std::string& t, tokens) {
        vWords.push_back(t);
    }
    vWords_TMP = vWords;
    for( std::vector<std::string>::const_iterator i = vWords.begin(); i != vWords.end(); ++i) std::cout << *i << '\n';
    std::sort(vWords_TMP.begin(), vWords_TMP.end());
    for( std::vector<std::string>::const_iterator i = vWords_TMP.begin(); i != vWords_TMP.end(); ++i) std::cout << *i << '\n';
}

ただし、実行すると、std::sort はベクトルのソートに失敗します。次のファイルを入力します。

> FILE
UUUUUUUUUUUUUUUUUUUUU
AAAAAAAAAAAAAAAAAAAAA
KKKKKKKKKKKKKKKKKKKKK
BBBBBBBBBBBBBBBBBBBBB
YYYYYYYYYYYYYYYYYYYYY

次のようになります。

AAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBB
KKKKKKKKKKKKKKKKKKKKK
UUUUUUUUUUUUUUUUUUUUU
YYYYYYYYYYYYYYYYYYYYY

残念ながら、ソート後の出力は同じです。何か案は?

4

3 に答える 3

1

vWordsprint ステートメントを使用して構造を変更します。

BOOST_FOREACH (const std::string& t, tokens) {
    vWords.push_back(t);
    std::cout << "pushing token: \"" << t << "\"" << std::endl;
}

そして、ファイルの内容全体が単一の文字列としてベクターにプッシュされることに気付くでしょう。明らかに、単一の要素を並べ替えても何も変わりません。

代わりに何が起こるべきかを決めるのはあなた次第です。

delimiter改行になりたいという意味だと思います。コマンドラインで改行をプログラムに渡す唯一の方法は、次のとおりです。

$ ./a.out file  "
> "
pushing token: "UUUUUUUUUUUUUUUUUUUUU"
pushing token: "AAAAAAAAAAAAAAAAAAAAA"
pushing token: "KKKKKKKKKKKKKKKKKKKKK"
pushing token: "BBBBBBBBBBBBBBBBBBBBB"
pushing token: "YYYYYYYYYYYYYYYYYYYYY"
UUUUUUUUUUUUUUUUUUUUU
AAAAAAAAAAAAAAAAAAAAA
KKKKKKKKKKKKKKKKKKKKK
BBBBBBBBBBBBBBBBBBBBB
YYYYYYYYYYYYYYYYYYYYY
AAAAAAAAAAAAAAAAAAAAA
BBBBBBBBBBBBBBBBBBBBB
KKKKKKKKKKKKKKKKKKKKK
UUUUUUUUUUUUUUUUUUUUU
YYYYYYYYYYYYYYYYYYYYY

(そして、あなたのプログラムはあなたが望むように動作することに注意してください)

コマンドライン引数として改行を渡す方法は、開い"てからEnterキーを押し、閉じ"てもう一度入力してコマンドを実行することです。

于 2013-11-10T08:16:32.667 に答える
0

改行を区切り文字としてプログラムに渡す方法がわからないので、何か他のものを渡します。そして、キャリッジ リターンを 1 つの文字列としてファイルからすべての行を取得します。1 つの文字列を並べ替えても何も変わらないため、同じ出力が表示されます。その場合に出力ループを次のように変更するかどうかを確認するには、次のようにします。

for( std::vector<std::string>::const_iterator i = vWords_TMP.begin(); i != vWords_TMP.end(); ++i) 
    std::cout << "\"" << *i << "\"\n";

そして、出力に表示される二重引用符の数を確認してください。

于 2013-11-10T08:13:39.453 に答える
0

問題は、ファイルのすべての行を 1 つの文字列に読み取っていることにあるようです。ここに示されているように、実際のソートアルゴリズム自体は機能します

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;

int main() {
    typedef std::vector<std::string> Strings;
    Strings strings = { "world", "good bye", "hello", "aloha" };
    sort(strings.begin(), strings.end());
    for (Strings::iterator it = strings.begin(); it != strings.end(); ++it) cout << *it << "\n";
    return 0;
}
于 2013-11-10T08:16:26.660 に答える