C++ 键值对实现

C++ 键值对实现,c++,char,double,key-value,keyvaluepair,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 基本上,Tim、Mark和Rob没有通过课程,因此他们的分数不会被存储。此外,为了区分失败标记和通过标记,我使用了=符号。基本上,我希望将所有名称与其关联值一起存储到内存中 这是我的实现,但是它有缺陷,因为我声

我有一个.txt文件,它存储了学生的名字以及他们的两个最好成绩。如果一名学生因某种原因(如中途退学)未能通过课程,则不记录分数

我的文件看起来像这样

Samuel= 90.5, 95.9
Bill= 25.2, 45.3
Tim
Anthony= 99.9, 12.5
Mark
Rob
基本上,Tim、Mark和Rob没有通过课程,因此他们的分数不会被存储。此外,为了区分失败标记和通过标记,我使用了=符号。基本上,我希望将所有名称与其关联值一起存储到内存中

这是我的实现,但是它有缺陷,因为我声明了一个double*marks[2]数组来存储所有六个标记,而它显然只存储3个。我无法将值存储到双数组中

这是我的密码

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

我如何用有效的分数存储学生的价值观?请不要使用向量或字符串流,只使用纯C/C++字符数组

您有一些选择,您可以使用这样的结构

然后将其粘贴到std::vector或类似的数组中

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;
这将解析输入,就像您希望它解析一行一样。一旦完成了,您就可以将整个过程包装在一个循环中,同时将得到的值粘贴到我已经描述过的某种数据结构中

希望这能给你一些关于去哪里的想法

这里有一个策略:

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

struct Student {
    char name[30];
    double marks[2];
};
请注意,如果知道长度永远不会更高,则可以在结构中给出char数组的维度。这是这里给出的

现在,您需要知道ifstream中有多少行,您可以通过is.getline调用进行循环来达到目的。完成后,不要忘记调用is.clear和is.seekg0,以便在真正循环的开始处

当您知道ifstream中有多少行时,可以使用文件的实际长度动态强制转换结构的数组:

Student * students = new Student[lineCount]; // line count of is
如您所见,不需要使用std::vector来保存这些值。考虑到GETLIN循环可能只是一个过多的错误,只是为了得到行计数,或者,您可以通过编译一个长度永远不会超过的数组来给学生提供一个长度。 e、 g.学生[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++;
}
现在,您需要将标记解析为双值,为此,您可以使用与char*一起工作的atof函数。boolhasmarks可以帮助您知道学生是否定义了标记,如果没有,您可以为结构的标记字段定义伪值,如-1


我认为这对你的案子很有效…

@Silicomancer,不,这不是家庭作业。只是自学,如果是家庭作业,我会向讲师寻求帮助。您可以使用getline读取行,使用stringstream将读取的数据指定为名称和数字。可以使用无序的_映射,将字符串作为键映射到双精度值向量。希望这能有所帮助。@learningToCode,有没有一种不用stringstream和vectors的方法可以做到这一点?-1因为要求代码高尔夫解决方案并不能解决实际问题。+1因为编码就像写作一样,你必须阅读大量的代码才能写出它。谢谢你的回答。我会认为这是一个替代的答案,但是我将非常感激如果你能帮助我解决它使用我的istrAM和没有载体。如果你能帮助我,那将意义重大out@SamThers你根本不需要向量,向量只是用来存储你得到的数据。如果您真的愿意,可以使用数组。我建议使用向量的唯一原因是,您可以不断增加向量,而不必担心空间不足。谢谢更新的答案。只存储有效的数字怎么样。我不想储存任何空白,我也不想把它们留作空白0@SamThers您可以从正在使用的数据结构中完全省略它们,这样就不会有该学生曾经被录取的记录,或者您可以添加一个布尔标志来判断该学生是否失败。
// 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++;
}