1

次のようなファイルがあります。

Mike 1200
John 350
Jen 1500
Tara 700
Michelle 2000
Kevin 500
Matt 450
Kim 200     

コンテンツを保存するための私のコード:

#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
using namespace std;

const int MAX = 15;

int main() {

// declare variables
string names[MAX];
string tempscore;
float scores[MAX];
fstream infile;

infile.open("winners.txt", ios::in);

int cc = 0;

getline(infile, names[cc], ' ');

infile.ignore( 0, ' ');

infile >> tempscore;
infile.ignore( 1, '\n');

scores[cc] = strtof(tempscore.c_str(), NULL);

    cout << "'" << names[cc] << "'" << endl;
    cout << "'" << scores[cc] << "'" << endl;

int i = 1;

while (infile) {

    getline(infile, names[i], ' ');

    infile.ignore( 0, ' ');

    infile >> tempscore;
    infile.ignore( 1, '\n');

    scores[cc] = strtof(tempscore.c_str(), NULL);


    cout << "'" << names[i] << "'" << endl;
    cout << "'" << scores[i] << "'" << endl;
    i++;
}
infile.close();

return 0;
}

ほとんどの名前は正しく保存されていますが、スコアはまったく保存されていません。なんで?私は何を間違っていますか?

これは私が達成しようとしていることを行うための最良の方法ですか?

4

5 に答える 5

3

コードにタイプミスがあります。ループ に入るscores[cc] = strtof(tempscore.c_str(), NULL);必要がscores[i] = strtof(tempscore.c_str(), NULL);あります。while

いくつかの補足事項:

  1. 0個別にインデックスを処理する必要はありません
  2. whileループ内で配列の境界を確認する必要があります。vector可能であれば使用を検討してください
  3. 以下のコメントでstefaanvが指摘しているように、 の戻り値をチェックしていませんgetline。利用せずにコードをそのまま残したい場合は、条件を(および ofc にstringstream変更して、後続の呼び出しを取り除くことを検討してください。チェックが前に行われることが重要であることに注意してください。)whilewhile(i < MAX && getline(infile, names[i], ' '))getlinei < MAXgetlinenames[i]getline
  4. を使用している場合は、直接操作する代わりにC++11使用することを検討してください。C-str を取得する必要はありません。stofstrtofstring

お役に立てれば!

于 2013-05-27T17:32:36.137 に答える
2

行ベースのファイル解析では、最初に行を読み取って文字列ストリームに入れ、次に各フィールドを文字列に格納して変換することなく、その文字列ストリームから直接読み取ります。

int main() {
const int MAX = 15;

// declare variables
std::string names[MAX];
float scores[MAX];
std::fstream infile;

infile.open("winners.txt", std::ios::in);

int i = 0;
std::string line;

while (getline(infile, line)) {
    std::stringstream input(line);

    input >> names[i] >> scores[i];
    if (input) {
        std::cout << "'" << names[i] << "'" << std::endl;
        std::cout << "'" << scores[i] << "'" << std::endl;
        i++;
        if (i >= MAX) break;  // protect your array or use a vector or deque
    }
}
infile.close();

return 0;
}
于 2013-05-27T17:18:35.977 に答える
1

そのファイル形式がある場合は、次のことができます。

  1. 行を読む
  2. 見つけた最初の空白文字の位置を取得します (それがセパレータであるため)
  3. その位置から文字列を分割します。
  4. 前半を文字列配列に保存し、後半をパラメーターとして呼び出した関数 atoi(secondHalf.c_str()) の出力をスコア配列に保存します。

また、実数を使用していない場合は、score 配列を float ではなく int に変更します。

更新: これは、私が伝えようとしているコードの例です。ここでは、名前とスコアにベクトルを使用しています。

int i = 0;
for(i=0; i<line.size(); i++)
{
    if(line[i] == ' ') break; //Then we have the position of the space char
}
names.push_back(line.substr(0,i));
scores.push_back(std::string(atoi(line.substr(i)))); 
于 2013-05-27T17:26:34.777 に答える
1

C 関数を使用して、フォーマットされた行をファイルから読み取ることができます。

FILE *fp = NULL;
int score = 0;
char name[20];
fp = fopen("winners.txt", "r");
if(!fp)
 return -1;

while(tell(fp) != EOF) {
 fscanf(fp, "%s %d", name, &score);
 printf("Name : %s, Score : %d", name, score);
}

するのを忘れないで#include <cstdio>

于 2013-05-27T18:02:39.423 に答える
1

getline2回使用できる場合は、実行しgetline(infile, names[cc], ' ');てくださいgetline(infile, score[cc], ' ');

または、テキスト ファイルを次のようにフォーマットします。

Mike 
1200

John 
350

Jen 
1500

この場合、3 行ごとにスコアが含まれており、2 から始まり、名前は同じですが 1 から始まります。1、4、7、10 などと 2、5、8、11 などを数えます。どちらが名前で、どちらがスコアです。

編集:これは主な質問に対する回答ではありませんが、適切な実装になる可能性があります。

于 2013-05-27T17:19:06.260 に答える