比较同一文件中的数据行

时间:2016-02-26 14:08:28

标签: c++ file

我正在为我的intro CS课程开发一个项目。我们仍然是C ++的新手,并使用基本概念,如while和for循环以及文件流。应该解决以下问题,而无需借助数组,向量或函数等高级功能。

基本上,我拿一个包含学生和课程数据的文本文件(FILE ONE)并创建一个新文件。文件一(我从中输入数据)有6k行。以下是一个例子:

20424297    1139    CSCI       16000    W   -1  3.00    RNL 
20424297    1142    PSYCH      18000    W   -1  3.00    RLA 
20424297    1142    PSYCH      22000    W    -1 3.00    RLA 
20608974    1082    ENGL       12000    A-  3.7 3.00    RECR    
20608974    1082    HIST       15200    B+  3.3 3.00    FUSR    
20608974    1082    PHILO      10100    A+  4   3.00    FISR    

看到第一列?每组唯一的数字代表一个学生(也称为eiD)。文件一是学生所上课的巨大列表,包括他们获得的科目,课程和成绩。

这个项目的目的是创建一个新的文本文件,总结每个学生的GPA。那部分我相当自信我能搞清楚(获取累积的GPA数据)。令我困惑的是我应该如何将文件中的行相互比较。

我的教授通过让学生将所有数据组合在一起,确实让事情变得简单。这稍微减轻了我的负担。我基本上必须逐行浏览此文件,并将其与下一行进行比较,以查看它是否具有相同的学生ID号。

我的第一个倾向是创建一系列嵌套的while循环。只要读取数据,第一个循环就会处于活动状态。我的下一个倾向是在另一个循环中重复这个。然后我会创建变量来保存上一行的学生ID号和当前行的学生ID号,创建条件,这些条件将根据它们是否相同而有效:

   while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) // This loop will keep running until there's no data left
   {
      string eiD_base = eiD_2; // eiD_base was the variable I made to hold the "previous" student's ID, for comparison to the next line
      while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) // This loop unfortunately reads the entire file, defeating its intent
      {
         string eiD_temp = eiD_2; // eiD_temp was the variable I made to hold the current student ID, for comparison
         if (eiD_base == eiD_temp)
         {

            outputStream2 << "Same line :( " << endl; 
         }
         else
         {
            outputStream2 << eiD_2 << endl; // this is where you post the student data from the previous line!
         }   
      }
   }

在编译并运行上述内容之后,我意识到这种方法不起作用,因为第二个嵌套循环将遍历FILE ONE中的每一行而不触及第一个循环。我最终想出了另一种使用计数器的方法:

  // NOTE: The logic of the below code is as follows:
  // Create a counter to note what the first student ID is.
  // Store that value in eiD_Base when counter = 0. Increment counter.
  // Now change eiD_Base everytime you find a line where eiD_temp
  // differs from eiD_base. 

  string eiD_base;
  string eiD_temp;
  int counter = 0; // counter to help figure out what the first student ID was
   while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2)
   {
      eiD_temp = eiD_2;
      if (counter == 0)
      {
        eiD_base = eiD_2; // basically, set the first student ID to eiD_base when counter is 0. This counter is incremented only once. 
        counter++;
      }

      if (eiD_base == eiD_temp)
      {
        outputStream2 << "Same ID:  " << eiD_2 << endl; 

    // NOTE: This is my first instinct as to where the code for calculating GPAs should go. 
    // The problem is that if that if the code is here, how do I factor in GPA data 
    // from a line that doesn't meet (eiD_base == eiD_temp)? I feel like that data would
    // be jettisoned from calculations.

      }
      else
      {
        outputStream2 << "Previous ID: " << eiD_base << " and this is what eiD is now is now: " << eiD_temp <<  endl; // This is my first instict for 
        eiD_base = eiD_2; // if eiD_base !== eiD_temp, have eiD_base reset here. 
      }   

   }

这似乎更接近我的需要。但是,我注意到了另一个问题。使用这种方法,当我创建的用于记录学生ID(eiD_base&amp; eiD_temp)中的变化的变量在一行数据上不相等时,似乎该行被抛弃。鉴于我需要为每个学生计算一些像GPA数据这样的东西,有一种不允许为不同学生的第一行累积数据的方法不是一个好的解决方案。

我不知道我是否应该完全免除计数器方法(在这种情况下我会欢迎有关如何最好地替换它的建议)或者如果我的计数器方法可以通过放置更具策略性地计算GPA的代码来实现。任何见解或帮助都是最受欢迎的!

1 个答案:

答案 0 :(得分:1)

我的回答风格是我尝试追随:https://meta.stackexchange.com/questions/10811/how-do-i-ask-and-answer-homework-questions

您遇到的一个问题是,您不知道是否应该完全免除计数器方法(在这种情况下,您会欢迎有关如何更换它的建议)或者如果您的计数器方法可以通过放置计算代码来实现GPA更具战略性。

对于前者,LiMuBei已经提到了这个方法。当您计算多个GPA(主要gpa,gpa仅适用于comp sci类)时,您总结了多个GPA的多个变量。

对于后者,您希望考虑改变每个if / while语句中的场景的未知元素。 (counter == 0)是第一行的场景。 (eiD_base == eiD_temp)是第一行的场景,当场景至少有2行时,当前行与前一行具有相同的ID。 (eiD_base!= eiD_temp)是存在至少2行的情况,当前行具有与前一行不同的ID。这里是未知元素:{1行,至少2行},{sameID,differentID}。当未知元素为{1行}时,您必须修改(counter == 0)和(eiD_base == eiD_temp)。在(计数器== 0)中,您修改适用于第一行和唯一一行的代码。在(eiD_base == eiD_temp)中,适用于{1 line}和{至少2行},{sameID},代码必须适用于2个场景。

对于完整的解决方案,您将在while循环之前声明变量,在(eiD_base == eiD_temp)中聚合变量,打印先前ID&amp;的GPA值。在(eiD_base!= eiD_temp)中设置新学生第一行的变量,并在while循环后打印最后一个ID的GPA值。

double csci_Grape_Point;
// more variables for doing the calculation

while (sdStream2 >> eiD_2 >> semester_2 >> subject_2 >> coursenumSD_2 >> grade_2 >> gpa_2 >> courseHours2 >> code_2) {
  eiD_temp = eiD_2;
  if (counter == 0)
  {
    eiD_base = eiD_2; 
    counter++;
    csci_Grape_Point = 0.0;
    // more initialization of variables for doing the calculation
  }
  if (eiD_base == eiD_temp)
  {
    csci_Grape_Point = csci_Grape_Point + (gpa_2 * courseHours2);
    // more sum calculation, such as total csci credit hours 
  }
  else
  {
    outputStream2 << "Previous ID: " << eiD_base << " and this is what eiD is now is now: " << eiD_temp <<  endl;
    eiD_base = eiD_2;

    // for the previous ID, calculate gpa for just comp sci classes
    // for the previous ID, calculate more gpa's

    // set the variable to include the first line of data of a new student
    csci_Grape_Point = (gpa_2 * courseHours2);
    // set more variables for doing the calculation
  }
}
// for the last ID, calculate gpa for just comp sci classes
// for the last ID, calculate more gpa's

您的另一个问题是(eiD_base == eiD_temp)中的数据计算。 当一条线不满足时(eiD_base == eiD_temp),当前线与前一条线不同。您可以根据汇总的数据(eiD_base == eiD_temp)计算GPA数据,并为(eiD_base!= eiD_temp)中新学生的第一行设置数据。

你可能想先解决一个更简单的问题,如果问题不容易为你解决,你想尝试在编程方面做得好。

你可以使用1行和2行的文件。