将信息读入C++结构体数组

3
我正在为我的C++课程编写一个程序。最终,我希望我的程序可以对以下格式的联系人文本文件执行快速排序:
名字 姓氏 号码
每个联系人由一个新行分隔。我已经开始计算行数并使用动态内存分配创建了一个结构体数组,其大小与行数相同。
然而,当我尝试从文本文件中读取信息并将其输出到屏幕时,我只得到了一些乱码。我在互联网上查找解决方案,但是我发现所有的例子都使用不同于我的语法。
以下是我目前的代码:
#include <iostream>
#include <fstream>
#include <istream>

char in[20];
char out[20];

using namespace std;

struct contact
{
    char firstName[14];
    char surName[14];
    char number[9];
};
//structure definition

int main(void){

    cout << "Please enter the input filename: " << endl;
    cin >> in;
    ifstream input(in);

    if(!input){
        cerr << "failed to open input file " << in << endl;
        exit(1);
    }

    cout << "Please enter tne output filename: " << endl;
    cin >> out;

    // read in the input and output filenames

    char a;
    int b=0;
    while (input.good ())
    {
        a=input.get ();
        if (a=='\n')
        {
            b++;
        }
    }
    // count the number of lines in the input file

    input.seekg (0, ios::beg);

    //rewind to beginning of file

    contact* list = new contact[b];

    //dynamically create memory space for array of contacts

    int i = 0.;
      while(input){
            if(i >= b) break;
            if(input >> *list[i].firstName >> *list[i].surName >> *list[i].number) i++;  
            else break;
      }
    input.close();

    //read information from input file into array of contacts

    for(int N = 0; N < b; N++){
        cout << list[N].firstName << list[N].surName << list[N].number << endl;
    }

    ofstream output(out);
    int k = 0;
    for(int k = 0; k<b; k++){
        output << list[k].firstName << "        " << list[k].surName << "       " << list[k].number << endl;
    }

    //print out the unsorted list to screen and write to output file
    //i've done both here just to check, won't print to screen in final version

    output.close();
    delete []list;

}       // end of main()

我非常确定您需要刷新输入流,因为它已经到达文件末尾,并将对象的值设置为false。您还使用了一些低效的方法,当您可以一次抓取一行直到文件结束时,就不需要使用input.get。 - Syntactic Fructose
什么是清空输入流?我以为 seekg 会将编译器带回文件的开头? - GGled
是的,但是在你计算行数的时候,文件已经到达了eof。文件标志被设置为FALSE以显示它已经到达了eof,但将读取器设置回零不会刷新此标志。 - Syntactic Fructose
你不能使用std::string和std::vector吗? - walrii
当使用std::string变量打开文件时,请使用std::string::c_str()方法。I/O流文件具有需要C风格字符串的构造函数。这在最近的C++版本中已经得到修复。 - Thomas Matthews
显示剩余3条评论
2个回答

0
你将文件位置重置到开头,但是文件的eofbit仍然被标记为true,这是因为你第一次读取行数时已经标记了。一个快速的解决方法是在读取完行数后重新打开文件,可能会使行数计数成为清理代码的函数。
int lines(const string path)
{
    ifstream tmp(path.c_str());
    string temp;
    int count = 0;
    getline(inFile,temp);
    while(inFile)
    {
       count++;
       getline(inFile,temp);
    }
    tmp.close();
    return count;
}

我尝试按照上述方法计算完行数后关闭并重新打开文件,但输出仍然是相同的乱码。我已经尝试使用你的函数,但Intellisense告诉我它在第一行函数之后需要一个声明。 - GGled
关于您的输入,再注意一下:在输入中删除所有列表对象前面的*,然后告诉我它的作用。 - Syntactic Fructose

0

好的,我使用较新的C++构造方法快速地编写了一个简单的方法,让你完成大部分工作。你需要自己编写文件写入(很简单)和快速排序,但是我已经将结构体放入了向量中,所以对向量进行排序就像编写一个自定义函数来比较一个结构体与另一个结构体一样容易。如果代码不够规范,请提前谅解。我已经超过了我的睡觉时间,而且非常疲倦,但这个问题足够有趣,我想尝试一下。祝你编程愉快!

#include <iostream>
#include <fstream>
#include <istream>
#include <string>
#include <vector>
#include <algorithm>
#include <cctype>
#include <sstream>

using namespace std;

std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
    std::stringstream ss(s);
    std::string item;
    while(std::getline(ss, item, delim)) {
        elems.push_back(item);
    }
    return elems;
}


std::vector<std::string> split(const std::string &s, char delim) {
    std::vector<std::string> elems;
    return split(s, delim, elems);
}

struct contact
{
    std::string firstName;
    std::string surName;
    std::string number;

    contact(std::string& fName, std::string& lName, std::string& num) : firstName(fName), surName(lName), number(num) {}
};
//structure definition

char in[20];
char out[20];

int main()
{
    std::vector<contact> contacts;

    cout << "Please enter the input filename: " << endl;
    cin >> in;
    ifstream input(in);

    if(!input){
        cerr << "failed to open input file " << in << endl;
        exit(1);
    }

    cout << "Please enter tne output filename: " << endl;
    cin >> out;

    std::string sinput;

    // read in the input and output filenames
    while (input.good ())
    {
        getline(input, sinput);

        vector<string> tokens = split(sinput, ' ');
        if (tokens.size() == 3)
        {
            contact c(tokens[0], tokens[1], tokens[2]);
            contacts.push_back(c);
        }
    }

    input.close();

    //read information from input file into array of contacts

    std::cout << "Outputting from vector..." << std::endl;
    for_each(contacts.begin(), contacts.end(), [](contact& c) {
        cout << c.firstName << " " << c.surName << " " << c.number << endl;
    });

    return 0;
}

另外,我想要感谢这篇回答在这个网站上提供的分割方法。谢谢!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接