【问题标题】:Defining +/- letter grades as constants. C将 +/- 字母等级定义为常数。 C
【发布时间】:2012-09-30 23:58:13
【问题描述】:

我正在尝试完成一个实验,在该实验中,我必须根据结构链接列表中给出的课程信息计算总平均绩点 (GPA)。我正在尝试用适当的成绩点定义每个字母等级('A' = 4.0,“A-” = 3.7 ...)。课程成绩存储在字符数组中。我可以使用#define 导数来定义字母等级 A、B、C、D、E,但我在定义 +/- 等级时遇到了麻烦。使用#define 派生是完成此任务的正确方法吗?如果是这样,有人能告诉我正确的语法吗?

/* Definition of a data node holding course information */
  struct course {
    int term;
    char name[15];
    char abbrev[20];
    float hours;
    char grade [4];
    char type[12];
    struct course *next;
  };



float gpa ( struct course *ptr )
{
  float totalhours;
  float gpa;
  float gradepoints;

  while (ptr != NULL )
    {
      totalhours += (ptr->hours);
      gradepoints = (ptr->hours * ptr->grade);
    }
  gpa = (gradepoints / totalhours);
}

【问题讨论】:

  • gpa = (学分/总学时);
  • 我将立即建议您将该 ptr 推进到列表中的下一个,否则在 while 循环退出之前将是一个寒冷的日子。
  • 为什么不称它们为 A_PLUS 和 A_MINUS?如果这样不行,原因在于您没有提供事实或代码。
  • 啊,是的,谢谢! -WhozCraig 我收到了字母等级作为输入。可能的输入值为 {A = 4.0, A- = 3.7, B+ = 3.3, B = 3.0, B- = 2.7, C+ = 2.3, C = 2.0, C- = 1.7, D+ = 1.3, D = 1.0, E = 0.0} 忽略其他等级,UEN、EN、R、I 等。
  • '在 while 循环退出之前' ...但是当它退出时,ptr 将为 NULL,从而导致 UB。大概最后一行应该是 `gpa = (gradepoints / totalhours);` ...如果没有课程,它仍然会产生 UB。给有志成为程序员的人的一个提示:学会关注细节,写完代码再读。

标签: c arrays constants c-preprocessor


【解决方案1】:

您要查找的是地图或字典,C 本身不支持它。您可以为您的用例实现一个简单的地图作为structs 的数组,如下所示:

struct GradeInfo {
  char *grade;
  float value;
};
struct GradeInfo GRADES[] = { {"A", 4.0}, {"A-", 3.7}, ..., {NULL, 0.0}};

然后在你的 for 循环中循环这个数组(修复一些错误):

float gpa ( struct course *ptr )
{
  float totalhours = 0.0;
  float gradepoints = 0.0;

  for (; ptr; ptr = ptr->next)
    {
      float grade = -1.0;
      struct GradeInfo *info;
      for (info = GRADES; info->grade; ++info) {
        if (!strcmp(ptr->grade, info->grade)) {
          grade = info->value;
          break;
        }
      }
      if (grade < 0) {
        continue;
      }
      totalhours += (ptr->hours);
      gradepoints = (ptr->hours * ptr->grade);
    }
  if (!totalhours) {
    return 0.0;
  }
  return (gradepoints / totalhours);
}

【讨论】:

  • 你的数组一张地图。地图可以实现为线性数组、二叉树或哈希表(以及其他数据结构的变体)。
  • 这段代码仍然有一个错误......一个狡猾的学生可以通过不参加任何课程来调用UB。
  • 我知道这是一张地图。我是说 C 没有原生映射类型,例如 python 或 perl 甚至 C++ STL。也就是说,你不会得到使用 [] 或类似的语法糖。
  • 我无法知道你知道什么,只是你写了什么。你的回答中没有说你“在说什么”。而且您将语法与“本机”混为一谈……许多系统在库中提供了这些数据结构,而没有将它们构建到语法中(C++ 肯定是这样)。
  • 我重申:当您写“您要查找的是地图”时,您会误导读者,因为该数组 地图。当您谈论“原生地图类型”时......原生地图类型可以实现为线性数组。一些复杂的系统(例如 Scala)实际上是为小地图这样做的。
【解决方案2】:

您想要的是字符串文字,而不是具有这些名称的变量...您可以定义宏,但由于映射是固定的,它只是增加了一个毫无意义的额外级别。例如,

// grade_string is a string read from the input
float grade_value;

if (strcmp(grade_string, "A") == 0)
    grade_value = 4.0;
else if (strcmp(grade_string, "A-") == 0)
    grade_value = 3.7;
etc.

有几种更紧凑的方法可以做到这一点。

1) 创建一个映射数组,例如,

struct {
    char*  string;
    double value; 
} grades = { {"A", 4.0}, {"A-", 3.7}, etc. };

并循环遍历这个数组,将字符串与grade_string 进行比较并提取值。例如,

int ngrades = sizeof grades / sizeof *grades;
int i;
for(i = 0; i < ngrades; i++)
    if (strcmp(grades[i].string, grade_string) == 0)
    {
        grade_value = grade[i].value;
        break;
    }

if (i == ngrades)
    /* invalid grade */

2) 使用哈希表。如果您有大量映射,这将是可取的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-11
    • 2017-07-18
    • 2019-11-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多