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. 如果您想在不使用的情况下保持代码原样,请stringstream考虑将while条件更改为while(i < MAX && getline(infile, names[i], ' '))(和 ofc,摆脱后续getline调用。请注意,i < MAX检查之前很重要,getline否则可能会出现分段错误,names[i]getline)
  4. 如果您正在使用C++11,请考虑使用stof而不是strtof直接操作,string并且无需为它获取 C-str

希望这可以帮助!

于 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

如果您能够使用getline两次,请getline(infile, names[cc], ' ');执行getline(infile, score[cc], ' ');

或者像这样格式化文本文件:

Mike 
1200

John 
350

Jen 
1500

等等

在这种情况下,每三行包含分数,以 2 开头,名称相同,但以 1 开头。数 1、4、7、10 等和 2、5、8、11 等,你知道,哪些是名字,哪些是分数。

编辑:这不是主要问题的答案,但可能是一个很好的实现。

于 2013-05-27T17:19:06.260 回答
1

如果您具有该文件格式,则可以执行以下操作:

  1. 阅读该行
  2. 获取您找到的第一个空格字符的位置(因为那是您的分隔符)
  3. 从该位置拆分字符串。
  4. 将前半部分存储到您的字符串数组中,然后将使用后半部分作为参数调用的函数 atoi(secondHalf.c_str()) 的输出存储到您的分数数组中。

如果您不使用实数,我还将分数数组更改为 int 而不是 float。

更新:这是我试图告诉你的示例代码。我在这里使用向量作为名称和分数:

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 回答