键值对实现C.

时间:2014-12-04 20:06:17

标签: c++ char double key-value keyvaluepair

我有一个.txt文件,用于存储学生姓名及其两个最佳分数。如果学生因某种原因(即退学)未能通过课程,则不会记录任何分数。

我的文件看起来像这样

Samuel= 90.5, 95.9
Bill= 25.2, 45.3
Tim
Anthony= 99.9, 12.5
Mark
Rob

基本上,TimMarkRob在课程中失败,因此不会存储他们的分数。另外,为了区分失败的标记和通过标记,我使用了=符号。基本上,我想将所有名称与其相关值一起存储在内存中。

这是我的实现,但是在我已经声明一个double *marks[2]数组来存储所有六个标记的意义​​上它是有缺陷的,显然它只会存储3.我无法将值存储到{ {1}}数组。

这是我的代码......

double

如何使用有效标记存储学生的价值观?请不要使用istream& operator>> (istream& is, Students& student) { student.names = new char*[6]; for (int i=0; i<10; i++) { student.names[i] = new char[256]; student.marks[i] = new double[2]; is.getline(student.names[i], sizeof(student.names)); for (int j=0; j < 256; j++) { if((student.names[i][j] == '=')) { int newPos = j + 1; for (int k = newPos; k < 256; k++) { student.names[i][k - newPos] = student.names[k]; } } } } } vectors,只使用纯C / C ++ stringstreams

2 个答案:

答案 0 :(得分:0)

您有几个选项,可以使用struct之类的

struct Record {
    std::string name;
    double marks[2];
};

然后将其粘贴到类似std::vector<Record>或类似

的数组中
Records *r = new Records[1000];

您还可以保留三个不同的阵列(自动分配或动态分配,甚至std::vector),一个用于保存名称,两个用于保存标记。

在每种情况下,您只需通过标记为零之类的东西来指示失败。

此外,您可以使用

std::string name;
double first, second;
std::cin >> name;
if (name[name.size() - 1] == '=')
    std::cin >> first >> second;

这将解析你想要的输入到一行。一旦你完成了这一切,你就可以将整个事物包含在一个循环中,同时将你所获得的值粘贴到我已经描述过的某种数据结构中。

希望能为您提供一些关于去哪里的建议!

答案 1 :(得分:0)

这是一个策略:

首先,你需要实现一个struct来保存键值对,我建议如下:

struct Student {
    char name[30];
    double marks[2];
};

请注意,如果知道长度永远不会更高,则可以在struct内给出char数组的维度。 (这里给出)

现在您需要知道ifstream中有多少行,您可以通过is.getline()次调用来实现此目的。 (完成时不要忘记调用is.clear()is.seekg(0),以便在实际循环开始时进行调用)

当您知道ifstream中有多少行时,您可以使用动态投射struct的数组与文件的实际长度:

Student * students = new Student[lineCount]; // line count of is

正如您所看到的,没有必要使用std::vector来保存值。考虑到getline()循环可能只是为了得到行数而过度杀戮,或者你可以通过创建一个永远不会被超越的长度的数组在编译时给学生一个长度。 (例如Student students[128];

现在你需要解析这些行,我建议你像下面一样循环(逐行):

// int parseLine ( char* line, char* name, double* marks ) { ...   
bool hasMarks=false;
int iLine=0; // Line pos iterator
int iName=0; // Name pos iterator
char mk1Str[4]; // String buffer, Mark 1
char mk2Str[4]; // String buffer, Mark 2

while(line[iLine]!='\0')
{
    if(line[iLine]=='=')
    {
        hasMarks=true;
        name[iLine]='\0';

        for(int iMark=0;iMark<4;iMark++)
        {
            mk1Str[iMark]=line[iLine+iMark+2];
            mk2Str[iMark]=line[iLine+iMark+8];
            // ^^ You can harcode the offsets (2,8) since they don't change 
        }
        break;
    }
    name[iName++]=line[iLine]; 
    iLine++;
}

现在您需要将标记解析为double值,为此您可以使用与atof()一起使用的char*函数。 bool hasMarks可以帮助您了解学生是否定义了标记,如果没有,您可以为struct的标记字段定义虚拟值,如-1。

我认为这适用于您的情况......