0

タイトルで示唆されているように、文字列をchar配列に変換するのに問題があります。

まず、私がこれを行う必要がある理由を明らかにしましょう。私のアプローチが間違っている場合は、喜んで別のコースを受講するからです。(答えが目前の問題に直接焦点を当てることができればいいのですが)

数行のファイルがあります。各行の形式は

b 12 3 4

d 4 1 5.71

..。

私がやろうとしているのは、各行を(getLineを使用して文字列変数に保存して)読み取り、各文字/数字を区切るために空のスペースで分割することです。

これを達成するために、引数としてchar*をとるstrtokメソッドを使用しました。

この変換は、物事がうまくいかなかった場所です。

私はいくつかのアプローチを取りましたが、常に同じように終わります:

試行#1-.data()

const char *converted = new char[(line.size()+1)];
//The sentence is complete in this cout!
cout << line << " -printed string\n";
converted = line.data();
converted[line.size()] = '\0';
//sentence no longer complete!
cout << converted << " -printed char array\n";

試行#2 .c_str()

char *converted;
//The sentence is complete in this cout!
cout << line << " -printed string\n";
converted = (char*)line.c_str();
//sentence no longer complete!
cout << converted << " -printed char array\n";

#3 copy()を試みます

char *converted = new char[(line.size()+1)];
//The sentence is complete in this cout!
cout << line << " -printed string\n";
copy(line.begin(), line.end(), converted);
//sentence no longer complete!
cout << converted << " -printed char array\n";

前のコードで構文エラーが発生している可能性があります。さまざまな方法を試したときにコードを消去したので、これをメモリから実行しています。重要なのは、.data()、copy()、および.c_str()を使用して、それらがすべてコンパイルされ、すべて同じ出力が得られたことです。

b 1234-印刷された文字列

b-印刷されたchar配列

今、私は宿題をしました、そして明らかにこれは完全な最初ではありません。おそらく何が起こっているのかをどこかで読んだと思いますが、これらのメソッドはすべて空のスペース「」を「\ 0」として解釈しているため、「b」を読んだだけで停止します。これを修正する方法の1つは、Boostライブラリを使用することです。

残念ながら、これは私にとって選択肢ではありません。私は外部ライブラリに頼ることができない成果物に取り組んでいます。いくつかの助けをいただければ幸いです。

前もって感謝します。

編集

コード:

(...)
if (fh.is_open()){
    while (fh.good()){
        getline(fh,line);
        char *converted = new char[(line.size()+1)];
        cout << line << " -printed string\n";
        strcpy(converted, line.c_str());
        
        cout << converted << " -printed char array\n";
(...)
4

3 に答える 3

2

#1と#2の同じ間違い、あなたは文字をコピーしなければなりません、あなたがしているのはポインタをコピーすることだけです。

交換

converted = line.data();
converted[line.size()] = '\0';

strcpy(converted, line.c_str());

試行#3の方が優れていますが、ヌルターミネータを追加するのを忘れています。

おそらく、std :: stringで機能するトークン化の方法を調べる必要があります。そうすれば、これらすべてを混乱させることはありません。

于 2013-03-24T11:37:14.510 に答える
1

これで、コードの問題が指摘されました

文字列(行)を空のスペースで分割する場合は、トークン化する代わりに、フォーマットされた入力を使用することをお勧めします。のようなもの(これはテストされていません)

#include <sstream>
#include <string>
while (std::getline(infile, line))
{
    std::istringstream iss(line);
    string token;
    while(iss >> token) { 

       // Do your thing on token

    }
}

必要に応じて変更してください。

于 2013-03-24T12:36:29.987 に答える
0

たとえば、試行#1の問題:

  • メモリリーク:最初に、ポインタを新しく割り当てられたメモリチャンクに設定してから、ポインタをにリセットします。line.data()

  • std::string::data()未定義の動作:ポインタが返す、または指すコンテンツを変更することは許可されていませんstd::string::c_str()。これは、文字列オブジェクトによって保持されている実際のバッファの内部コピーである可能性があります。

文字列を空白で区切られた部分に分割するには、次の方法を試すことができます。

split(const std::string &line, char &letter, std::vector<double> &numbers) {
    typedef std::string::size_t size_t;
    size_t n = line.find(' ');
    if (n == std::string::npos || n > 1) {
        // there aren't any spaces or the first part contains
        // more than one letter!
        // bad case? throw something or return an error code
    }
    letter = line[0];
    size_t n2 = line.find(' ', n);
    while (n2 != std::string::npos) {
        numbers.push_back(str2double(line.substr(n, n2 - n)));
        n = n2;
        n2 = line.find(' ', n);
    }
}

私はコードをテストしませんでした。の呼び出しなどn + 1に書き込む必要がある可能性があります。findそして、あなたはstr2double自分で関数を書かなければなりません。

于 2013-03-24T12:36:39.670 に答える