C ++在同一行上读取多种类型的文件

时间:2013-05-27 17:07:07

标签: c++ file

我有一个看起来像这样的文件:

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;
}

大多数名称都存储正确但没有得分。为什么?我做错了什么?

这是我想要实现的最佳方式吗?

5 个答案:

答案 0 :(得分:3)

您的代码中存在拼写错误。 scores[cc] = strtof(tempscore.c_str(), NULL);循环中的scores[i] = strtof(tempscore.c_str(), NULL);应为while

一些附注:

  1. 无需单独处理索引0
  2. 您应该检查while循环中的数组边界。如果可能,请考虑使用vector
  3. 正如stefaanvthe comment中指出的那样,您没有检查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 < / LI>

    希望这有帮助!

答案 1 :(得分: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;
}

答案 2 :(得分: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等。你知道,哪些是名字,哪些是分数。

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

答案 3 :(得分:1)

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

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

如果您不使用实数,我也会将得分数组更改为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)))); 

答案 4 :(得分: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>