主要代码如下,其余的小工具无关重要:

程序代码:
/*
http://bbs.bccn.net/thread-439538-1-1.html
题目:学生成绩统计 (一维数组) 从键盘输入一个班(全班最多不超过 30人)学生某门课的成绩, 当输入成绩为负值时, 输入结束, 分别
实现下列功能:(1)统计不及格人数并打印不及格学生名单;(2)统计成绩在全班平均分及平均分之上的学生人数, 并打印这些学生的名单;
(3)以直方图方式统计各分数段的学生人数及所占的百分比。
形式如下:分段 人数 图形
<60 3(10%)***
60‐69 8(…) ********
70‐79 7(…) *******
80‐89 8(…) ********
>=90 4(…) ***
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "common.h"
// 学生信息结构
struct Student_Info
{
    int    ID;                  // 学号
    char   Name[20];            // 姓名(最多19个字符)
    double Score;               // 成绩
    int    Grade;               // 等级
};
// 统计项结构
struct Statistics_Item
{
    double low;                 // 统计段下限
    double high;                // 统计段上限
    size_t count;               // 人数
    double percentage;          // 百分比
};
// 全局数据
Student_Info Students[30];                      // 学生数组(最多不超过30人)
const double Qualify_Value = 60.0;              // 成绩合格线
Statistics_Item Statistics_Data[] =             // 统计结果数组
{
    {  0.0,  59.0, 0, 0.0 },
    { 60.0,  69.0, 0, 0.0 },
    { 70.0,  79.0, 0, 0.0 },
    { 80.0,  89.0, 0, 0.0 },
    { 90.0, 100.0, 0, 0.0 }
};
// 函数原型
void Show_StudentInfo(Student_Info student);    // 输出单个学生的明细信息
void List_Students(void);                       // 输出所有学生的明细资料
void Input_Data(const char* fileName);          // 输入学生数据
double Get_Average(void);                       // 求取平均成绩
size_t Statistics_Unqualified(void);            // 统计不合格学生人数并输出相关学生信息
void Statistics_GoodStudents(double average);   // 统计在平均成绩以上的学生
void Statistics(void);                          // 统计
// 程序主入口
int main(int argc, char* argv[])
{
    // 输入学生数据,如果有命令行参数,则从文本文件读入数据,否则从键盘输入
    Input_Data((argc > 1) ? argv[1] : NULL);
    List_Students();
    putchar('\n');
    Statistics_Unqualified();
    putchar('\n');
    Statistics_GoodStudents(Get_Average());
    putchar('\n');
    Statistics();
    Pause("\n按任意键继续...");
    return EXIT_SUCCESS;
}
void Show_StudentInfo(Student_Info student)
{
    printf_s("%4u   %-20s   %6.2f   %-4d\n", student.ID, student.Name, student.Score, student.Grade);
}
void List_Students(void)
{
    printf_s("%4s   %-20s   %6s   %4s\n", "学号", "姓名", "成绩", "等级");
    // 注:_countof()是宏,计算静态分配的数组的元素个数,在stdlib.h头中定义
    for (size_t index = 0; (index < _countof(Students)) && (Students[index].Score >= 0); ++index)
    {
        Show_StudentInfo(Students[index]);
    }
}
void Input_Data(const char* fileName)
{
    FILE* file = stdin;
    if (fileName != NULL)
    {
        errno_t errorCode = fopen_s(&file, fileName, "rt");
        if (errorCode != 0)
        {
            file = stdin;
        }
    }
    for (size_t index = 0; index < _countof(Students); ++index)
    {
        if (file == stdin)
        {
            // 从键盘输入数据
            printf_s("请输入第%2u个学生的数据(成绩为负数结束):\n", index + 1);
            do
            {
                printf_s("学号: ");
                fflush(stdin);
            } while(scanf_s("%d", &Students[index].ID) == 0);
            do
            {
                printf_s("姓名: ");
                fflush(stdin);
            } while(gets_s(Students[index].Name, _countof(Students[index].Name) - 1) == NULL);
            do
            {
                printf_s("成绩: ");
                fflush(stdin);
            } while(scanf_s("%lf", &Students[index].Score) == 0);
            if (Students[index].Score < 0)
            {
                // 当输入的成绩为负数时结束输入
                Students[index].ID = 0;
                Students[index].Name[0] = '\0';
                break;
            }
            putchar('\n');
        }
        else
        {
            // 从文本文件读入数据
            if ((fscanf_s(file, "%d %20s %lf", &Students[index].ID, Students[index].Name, 20, &Students[index].Score) != 3) || (Students[index].Score < 0))
            {
                Students[index].ID = 0;
                Students[index].Name[0] = '\0';
                break;
            }
        }
    }
    if (file != stdin)
    {
        fclose(file);
    }
}
size_t Statistics_Unqualified(void)
{
    size_t count = 0;
    printf_s("不合格学生:\n");
    for (size_t index = 0; (index < _countof(Students)) && (Students[index].Score >= 0); ++index)
    {
        if (Students[index].Score < Qualify_Value)
        {
            if (count == 0)
            {
                printf_s("%4s   %-20s   %6s   %4s\n", "学号", "姓名", "成绩", "等级");
            }
            ++count;
            Show_StudentInfo(Students[index]);
        }
    }
    printf_s("人数 = %u\n", count);
    return count;
}
double Get_Average(void)
{
    double sum = 0.0;
    size_t number = 0;
    for (size_t index = 0; (index < _countof(Students)) && (Students[index].Score >= 0); ++index)
    {
        sum += Students[index].Score;
        ++number;
    }
    return sum / number;
}
void Statistics_GoodStudents(double average)
{
    size_t count = 0;
    printf_s("成绩在平均分(%6.2f)以上的学生:\n", average);
    for (size_t index = 0; (index < _countof(Students)) && (Students[index].Score >= 0); ++index)
    {
        if (Students[index].Score >= average)
        {
            if (count == 0)
            {
                printf_s("%4s   %-20s   %6s   %4s\n", "学号", "姓名", "成绩", "等级");
            }
            ++count;
            Show_StudentInfo(Students[index]);
        }
    }
    printf_s("人数 = %u\n", count);
}
void Statistics(void)
{
    size_t total = 0;
    for (size_t i = 0; (i < _countof(Students)) && (Students[i].Score >= 0); ++i)
    {
        ++total;
        for (size_t j = 0; j < _countof(Statistics_Data); ++j)
        {
            if ((Students[i].Score >= Statistics_Data[j].low) && (Students[i].Score <= Statistics_Data[j].high))
            {
                ++Statistics_Data[j].count;
            }
        }
    }
    printf_s("%15s   %4s   图形\n", "分数", "人数");
    for (size_t i = 0; i < _countof(Statistics_Data); ++i)
    {
        printf_s("%6.2f - %6.2f  %4u   ", Statistics_Data[i].low, Statistics_Data[i].high, Statistics_Data[i].count);
        for (size_t j = 0; j < Statistics_Data[i].count; ++j)
        {
            putchar('*');
        }
        putchar('\n');
    }
}