while循环和从文件读取的问题

Issues with while loop and reading from files

本文关键字:读取 问题 文件 循环 while      更新时间:2023-10-16

我正在做这个项目,我对c++相当陌生。很难解释我在做什么,但我会试着解释。所以我正在处理一个名为flix.txt的文件,它看起来像这样:

1 A 5
1 B 4
1 D 3
1 F 5
2 A 1
3 E 3
3 F 1
4 A 2

第一列是人(我的对象),第二列是电影,第三列是对象给出的评分。

我试图首先从每行提取第一个int,并使用'operator new'创建一个对象。然后我将电影转换为int,这样我就可以将评级插入数组中。抱歉,如果这听起来令人困惑。下面是我现在的代码:

//flix program
#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#define NUMBER_OF_MOVIES 6
using namespace std;
int tokenize(string line);
int getMovieNum(char movie);
void resetPos(istream& flix);
class Matrix{
    public:
        int movieRate[NUMBER_OF_MOVIES];
};
int main(){
    int distinctCount = 0;
    int checker = -1;
    int check = 0;
    string line;
    int personNum;
    char movie;
    int rating;
    int movieNum;
    ifstream flix("flix.txt"); 
    ofstream flick("flix1.txt");
    //identify distinct account numbers in file    
    while(getline(flix, line)){
        check = tokenize(line);
        if(check != checker)
            distinctCount++;
        checker = check;
        check = 0;
    }
    //reset position in file
    resetPos(flix);
    //create objects in accordance with distinct numbers
    Matrix* person = new Matrix[distinctCount];
    for(int i = 0; i < distinctCount; i++){
        for(int j = 0; j < NUMBER_OF_MOVIES; j++){
            person[i].movieRate[j] = 0;
            cout << i + 1 << ' ' << person[i].movieRate[j] << endl;
        }
        cout << "n";
    }
    //reset position in file
    resetPos(flix);
    //get data from file and put into respective variables
    while(getline(flix, line)){
        flix >> personNum >> movie >> rating;
        cout << personNum << ' ' << movie << ' ' << rating << endl;
        //changes the char into an int
        movieNum = getMovieNum(movie);
        person[personNum].movieRate[movieNum] = rating;
    }
    //reset position in file
    resetPos(flix);
    //input ratings into movie array
    for(int i = 0; i < distinctCount; i++){
        for(int j = 0; j < NUMBER_OF_MOVIES; j++){
            cout << i + 1 << ' ' << person[i].movieRate[j] << endl;
            flick << i + 1 << ' ' << person[i].movieRate[j] << endl;
        }
    }

    //write data to text file
    //??
    flick.close();
    //free memory
    delete[] person;
    system("pause");
    return 0;
}
int tokenize(string line){
    string myText(line);
    istringstream iss(myText);
    string token;
    getline(iss, token, ' ');
    int strInt = atoi(token.c_str());
    return strInt;
}
int getMovieNum(char movie){
    int movieNum = 0;
    switch(movie){
        case 'A':
            movieNum = 1;
            break;
        case 'B':
            movieNum = 2;
            break;
        case 'C':
            movieNum = 3;
            break;
        case 'D':
            movieNum = 4;
            break;
        case 'E':
            movieNum = 5;
            break;
        case 'F':
            movieNum = 6;
            break;
        default:
            movieNum = 0;
            break;
    }
    return movieNum;    
}
void resetPos(istream& flix){
        flix.clear();
        flix.seekg(0);
}

如果这里有什么错误,我也提前道歉。

我认为问题是在while循环的某个地方,那就是它一直锁定的地方。我花了几个小时在这上面,但我不明白为什么它不起作用。在while循环中,我试图访问文件的每一行,从该行获取数据,将movie char转换为int,然后将数据插入对象内的数组中。当我让它工作时,所有的数据也都错了。任何输入都是高度赞赏的。

您需要对程序进行一些更改,我将只粘贴更改的部分。在你重置人之后的某个地方[]。movieRate[]为0,你写的是while loop

resetPos(flix);
int k = NUMBER_OF_MOVIES + 2;  //this is the variable that i have declared
//get data from file and put into respective variables
while(k){      //do you see that instead of getline() i have used the variable k. i'l tell you why later
    flix >> personNum >> movie >> rating;
    //personNum = tokenize(line,1);
    cout << personNum << ' ' << movie << ' ' << rating << endl;
    //changes the char into an int
    movieNum = getMovieNum(movie);
    person[personNum - 1].movieRate[movieNum] = rating;  //this is personNum-1 and NOT personNum the most common mistake while indexing array.
    k--;
}

这段代码似乎可以作为您的标准。我删除getline()的原因是,如果你调用getline,那么get指针的位置将增加。所以在这之后你调用flix>>什么的…,从第二行读取数据。您的第一个线路5a丢失了。这就是麻烦的原因。

好,让我试着给出一个简单的起点:

#include <iostream>
#include <iterator>
#include <vector>
#include <fstream>
struct rater {
    std::vector<int> ratings;
    rater() : ratings(6) {}
    friend std::istream &operator>>(std::istream &is, rater &r) {
        char movie;
        is >> movie;
        return is >> r.ratings[movie-'A'];
    }
    friend std::ostream &operator<<(std::ostream &os, rater const &r) {
        for (int i=0; i<r.ratings.size(); i++) {
            os << char(i + 'A') << ":" << r.ratings[i] << "t";
        }
        return os;
    }
};
int main() { 
    std::ifstream in("flix.txt");
    std::vector<rater> ratings(5);
    int i;
    while (in >> i) 
        in >> ratings[i-1];
    i=1;
    for (auto r : ratings) 
        std::cout << i++ << "-> " << r << "n";    
}

这里有一点清理。它使用std::map来跟踪Person和Movie键,这更灵活,因为可以使用任何类型的文本字符串(无空格)。您已经添加了一条评论,说您特别想列出人们在其输出中没有评分的电影-这可以通过使用std::set并确保插入遇到的每个电影名称来完成,然后使用对集合的迭代来指导查找每个人的评分:作为练习。

#include <iostream>
#include <string>
#include <fstream>
#include <sstream>
#include <map>
using namespace std;
typedef std::map<std::string, int> Movie_Ratings;
typedef std::map<std::string, Movie_Ratings> Persons_Movie_ratings;
int main()
{
    if (!ifstream flix("flix.txt"))
    {
        std::cerr << "error opening inputn";
        exit(1);
    }
    if (!ofstream flick("flix1.txt"))
    {
        std::cerr << "error opening outputn";
        exit(1);
    }
    Persons_Movie_Ratings ratings;
    std::string line;
    while (getline(flix, line))
    {
        istringstream iss(line);
        string person, movie;
        int rating;
        if (line >> person >> movie >> rating)
            ratings[person][movie] = rating;                
    }
    // input ratings into movie array
    for (Persons_Movie_Ratings::const_iterator i = ratings.begin();
         i != ratings.end(); ++i)
    {
        for (Movie_Ratings::const_iterator j = i->second.begin();
             j != i->second.end(); ++j)
        {
            cout << i->first << ' ' << j->second << endl;
            flick << i->first << ' ' << j->second << endl;
        }
    }
    system("pause");
}