没写过C语言,学了一晚上C的结果,为交作业新鲜出炉的

环境是 Ubuntu. 编译器 gcc

#include<stdio.h>
#include<stdlib.h>
#include<memory.h>
#include<termio.h>

#define STDIN_FILENO 0
#define MAX_LEN   8
#define BACKSPACE 8
#define ENTER     13
#define ALARM     7
#define DATA_FILE "./data.txt"
#define USERNAME "root"
#define PASSWD "root"

/**
* 学生结构体
**/
typedef struct {
    char no[7];
    char name[9];
    char gender;
    float scores[3];
    float total_score;
    float avg_score;
} Student;

Student *stulist;  //所有学生列表
int stunum; //学生数量
char *stuproperty[7] = {
    "不指定",
    "学号",
    "姓名",
    "性别",
    "课程1",
    "课程2",
    "课程3"
};

/**
* 密码输出星号函数
**/
int getch() {
    struct termios tm, tm_old;
    int fd = STDIN_FILENO, c;
    if (tcgetattr(fd, &tm) < 0) return -1;
    tm_old = tm;
    cfmakeraw(&tm);
    if(tcsetattr(fd, TCSANOW, &tm) < 0) return -1;
    c = fgetc(stdin);
    if(tcsetattr(fd, TCSANOW, &tm_old) < 0) return -1;
    return c;
}

char *getpwd(const char *prompt)
{
    int i=0, ch;
    static char p[MAX_LEN+1]="";
    printf("%s", prompt);
    while((ch = getch())!= -1 && ch != ENTER)
    {
        if(i == MAX_LEN && ch != BACKSPACE)
        {
            putchar(ALARM);
            continue;
        }
        if(ch == BACKSPACE)
        {
            if(i==0)
            {
                putchar(ALARM);
                continue;
            }
            i--;
            putchar(BACKSPACE);
            putchar(' ');
            putchar(BACKSPACE);
        }
        else
        {
            p[i] = ch;
            putchar('*');
            i++;
        }
    }
    if(ch == -1)
    {
        while(i != -1)
        {
            p[i--] = '\0';
        }
        return NULL;
    }
    p[i]='\0';
    printf("\n");
    return p;
}

/**
* 登录验证
**/
void validate() {
    char *username = (char *) malloc(sizeof(char) * 8);
    printf("\n\t请输入用户名: ");
    scanf("%s", username);
    getchar();
    char *passwd = getpwd("\n\t请输入密码: ");
    if (strcmp(username, USERNAME) != 0 || strcmp(passwd, PASSWD) != 0) {
        printf("\n\t用户名或密码错误,程序即将退出\n");
        getchar();
        exit(0);
    }
}

/**
* 交换函数
**/
void swap(Student *stulist, int i, int j) {
    Student stutemp = stulist[i];
    stulist[i] = stulist[j];
    stulist[j] = stutemp;
}

/**
* 字符串重复函数
**/
char *strrep(char c, int n) {
    char *str = (char *) malloc(sizeof(c) * n + 1);
    int i;
    for (i = 0; i < n; i++) {
        *str++ = c;
    }
    *str = '\0';
    str -= n;
    return str;
}

/**
* 结果输出函数
**/
void print_result(Student *stulist, int stunum) {
    int i;
    float sum[3] = {0};
    float avg[3] = {0};
    float max[3] = {0};
    float min[3] = {
        stunum > 0 ? stulist[0].scores[0] : 0,
        stunum > 0 ? stulist[0].scores[1] : 0,
        stunum > 0 ? stulist[0].scores[2] : 0,
    };
    printf("\n\t位置\t学号\t姓名\t性别\t课程1\t课程2\t课程3\t总分\t平均分\n\n");
    for (i = 0; i < stunum; i++) {
        Student *s = &stulist[i];
        printf("\t%d\t%s\t%s\t%s\t%.1f\t%.1f\t%.1f\t%.1f\t%.1f\n", i, s->no, s->name, s->gender == '1' ? "" : "", s->scores[0], s->scores[1], s->scores[2], s->total_score, s->avg_score);
        sum[0] += s->scores[0];
        sum[1] += s->scores[1];
        sum[2] += s->scores[2];
        avg[0] = sum[0] / stunum;
        avg[1] = sum[1] / stunum;
        avg[2] = sum[2] / stunum;
        max[0] = s->scores[0] > max[0] ? s->scores[0] : max[0];
        max[1] = s->scores[1] > max[1] ? s->scores[1] : max[1];
        max[2] = s->scores[2] > max[2] ? s->scores[2] : max[2];
        min[0] = s->scores[0] < min[0] ? s->scores[0] : min[0];
        min[1] = s->scores[1] < min[1] ? s->scores[1] : min[1];
        min[2] = s->scores[2] < min[2] ? s->scores[2] : min[2];
    }

    //输出各科目成绩统计
    printf("\n\t\t最高分\t最低分\t总分\t平均分");
    printf("\n\t课程1\t%.1f\t%.1f\t%.1f\t%.f", max[0], min[0], sum[0], avg[0]);
    printf("\n\t课程2\t%.1f\t%.1f\t%.1f\t%.f", max[1], min[1], sum[1], avg[1]);
    printf("\n\t课程3\t%.1f\t%.1f\t%.1f\t%.f\n", max[2], min[2], sum[2], avg[2]);

}

/**
* 插入学生记录
**/
void add_stu() {
    Student stu;
    int no;
    printf("\n\t请输入插入的位置: ");
    scanf("%d", &no);
    printf("\n\t请输入学号: ");
    scanf("%s", stu.no);
    printf("\n\t请输入姓名: ");
    scanf("%s", stu.name);
    printf("\n\t请输入性别(1男2女): ");
    getchar();
    scanf("%c", &stu.gender);
    printf("\n\t请输入课程1成绩: ");
    scanf("%f", &stu.scores[0]);
    printf("\n\t请输入课程2成绩: ");
    scanf("%f", &stu.scores[1]);
    printf("\n\t请输入课程3成绩: ");
    scanf("%f", &stu.scores[2]);
    Student *s = &stu;
    stu.total_score = stu.scores[0] + stu.scores[1] + stu.scores[2];
    stu.avg_score = stu.total_score / 3;

    if (stulist == NULL) {
        stulist = (Student *) malloc(sizeof(Student));
    } else {
        stulist = (Student *) realloc(stulist, sizeof(Student) * (stunum + 1));
    }

    //插入指定编号位置
    if (no >= 0 && no < stunum) {
        memmove(&stulist[no + 1], &stulist[no], (stunum - no) * sizeof(Student));
    } else {
        //插到末尾
        no = stunum;
    }

    memcpy(&stulist[no], &stu, sizeof(Student));
    stunum++;
}

/**
* 查询学生
**/
void query_stu() {
    //输出查询菜单
    int i;
    for (i = 0; i < 7; i++) {
        printf("\n\t%d.%s", i + 1, stuproperty[i]);
    }
    printf("\n\n\t请输入查询条件编号: ");
    int choice;
    float low;
    float high;
    char *condition = (char *) malloc(sizeof(char) * 8);
    scanf("%d", &choice);
    switch(choice) {
        case 1: break;
        case 5:
        case 6:
        case 7:
            printf("\n\t请输入成绩下限: ");
            scanf("%f", &low);
            printf("\n\t请输入成绩上限: ");
            scanf("%f", &high);
            break;
        default:
            printf("\n\t请输入要查询的值: ");
            scanf("%s", condition);
    }

    //筛选符合条件的学生
    Student *sturesult = (Student *) malloc(sizeof(Student) * stunum);
    int resultnum = 0;
    for (i = 0; i < stunum; i++) {
        switch(choice) {
            case 2:
                if (strcmp(stulist[i].no, condition) == 0) 
                    sturesult[resultnum++] = stulist[i];
                break;
            case 3:
                if (strcmp(stulist[i].name, condition) == 0) 
                    sturesult[resultnum++] = stulist[i];
                break;
            case 4:
                if (stulist[i].gender == *condition) 
                    sturesult[resultnum++] = stulist[i];
                break;
            case 5:
            case 6:
            case 7:
                if (stulist[i].scores[choice - 5] >= low && stulist[i].scores[choice - 5] <= high)
                    sturesult[resultnum++] = stulist[i];
                break;
            default:
                sturesult[resultnum++] = stulist[i];
                break;
        }
    }

    //输出查询结果
    print_result(sturesult, resultnum);
}

/**
* 编辑学生
**/
void edit_stu() {
    int no;
    printf("\n\t请输入要编辑的学生位置: ");
    scanf("%d", &no);

    if (no < 0 || no >= stunum) no = 0;

    //输出编辑菜单
    int i;
    for (i = 1; i < 7; i++) {
        printf("\n\t%d.%s", i, stuproperty[i]);
    }

    int choice;
    char *value = (char *) malloc(sizeof(char) * 8);
    printf("\n\n\t请输入要编辑的属性编号: ");
    scanf("%d", &choice);
    printf("\n\t请输入要新的属性值: ");
    scanf("%s", value);

    //修改属性
    switch(choice) {
        case 1:
            memcpy(stulist[no].no, value, sizeof(char) * 7);
            break;
        case 2:
            memcpy(stulist[no].name, value, sizeof(char) * 9);
            break;
        case 3:
            stulist[no].gender = *value;
            break;
        case 4:
        case 5:
        case 6:
            stulist[no].scores[choice - 4] = atof(value);
            //重新计算平均成绩和总成绩
            stulist[no].total_score = stulist[no].scores[0] + stulist[no].scores[1] + stulist[no].scores[2];
            stulist[no].avg_score = stulist[no].total_score / 3;
            break;
        default:
            break;
    }
}

/**
* 删除学生
**/
void del_stu() {
    int no;
    printf("\n\t请输入要删除的学生的位置: ");
    scanf("%d", &no);
    if (no < 0 || no >= stunum) no = 0;
    memmove(&stulist[no],
            &stulist[no + 1],
            sizeof(Student) * (stunum - no - 1)
           );
    stunum--;
}

/**
* 学生排序
**/
void sort_stu() {
    //输出排序菜单
    int i;
    Student *sturesult = (Student *) malloc(sizeof(Student) * stunum);
    memcpy(sturesult, stulist, stunum * sizeof(Student));
    for (i = 1; i < 7; i++) {
        printf("\n\t%d.%s", i, stuproperty[i]);
    }

    int choice;
    printf("\n\n\t请输入要排序的字段编号: ");
    scanf("%d", &choice);
    
    //使用选择排序
    for (i = 0; i < stunum; i++) {
        int j;
        int min = i;
        for (j = i + 1; j < stunum; j++) {
            switch(choice) {
                case 1:
                    if (strcmp(sturesult[j].no, stulist[min].no) < 0) 
                        min = j;
                    break;
                case 2:
                    if (strcmp(sturesult[j].name, stulist[min].name) < 0) 
                        min = j;
                    break;
                case 3:
                    if (sturesult[j].gender < stulist[min].gender) 
                        min = j;
                    break;
                case 4:
                case 5:
                case 6:
                    if (sturesult[j].scores[choice - 4] < stulist[min].scores[choice - 4]) 
                        min = j;
                        break;
                default:
                    break;
            }
        }
        swap(sturesult, i, min);
    }

    //输出排序结果
    print_result(sturesult, stunum);

    //是否保存
    printf("\n\t请问是否需要保存排序结果(输入1/0): ");
    scanf("%d", &choice);
    if (choice == 1) {
        free(stulist);
        stulist = sturesult;
    } else {
        free(sturesult);
    }
}

/**
* 初始化,将数据文件读取进数组
**/
void init_sys() {
    FILE *fp = fopen(DATA_FILE, "rb");
    if (fp == NULL) {
        stunum = 0;
        stulist = NULL;
    } else {
        fread(&stunum, sizeof(int), 1, fp);
        stulist = (Student *) malloc(sizeof(Student) * stunum);
        fread(stulist, sizeof(Student), stunum, fp);
        fclose(fp);
    }
}

/**
* 程序结束,将数据写入文件
**/
void uinit_sys() {
    FILE *fp = fopen(DATA_FILE, "wb");
    fwrite(&stunum, sizeof(int), 1, fp);
    fwrite(stulist, sizeof(Student), stunum, fp);
    fclose(fp);
}

/**
* 成绩统计
**/
void statistics() {
    //3门课,每门课10个区间
    int courses[3][10] = {0};
    int i, j;
    for (i = 0; i < stunum; i++) {
        for (j = 0; j < 3; j++) {
            int q = (int) (stulist[i].scores[j] / 10);
            if (q > 9) q = 9;
            if (q < 0) q = 0;
            courses[j][q]++;
        }
    }

    for (i = 0; i < 3; i++) {
        printf("\n\n\t课程%d统计图: ", i + 1);
        printf("\n\t区间\t人数\t条形图");
        for (j = 0; j < 10; j++) {
            char *str = strrep('*', courses[i][j]);
            printf("\n\t%d-%d\t%d\t%s", j * 10, (j + 1) * 10 - 1, courses[i][j], str);
            free(str);
        }
    }
    printf("\n");
}

void main() {
    validate();
    init_sys();
    int flag = 1;
    while (flag) {
        char *menu[] = {
            "添加学生记录",
            "查询学生记录",
            "编辑学生记录",
            "删除学生记录",
            "排序学生记录",
            "统计学生记录",
            "退出系统"
        };

        //输出主菜单
        char *title = strrep('*', 33);
        printf("\n\t%s\t", title);
        int i;
        for (i = 0; i < 7; i++) {
            printf("\n\t*\t%d.%s\t\t*", i + 1, *(menu + i));
        }
        printf("\n\t%s\t\n\n", title);
        printf("\n\t请输入要执行的操作编号: ");
        
        //等待选择功能
        int choice;
        scanf("%d", &choice);
        switch (choice) {
            case 1: 
                add_stu();
                break;
            case 2: 
                query_stu();
                break;
            case 3: 
                edit_stu();
                break;
            case 4:
                del_stu();
                break;
            case 5:
                sort_stu();
                break;
            case 6: 
                statistics();
                break;
            default:
                flag = 0;
                printf("\n\tBye\n");
        }
    }
    uinit_sys();
}
posted on 2012-10-22 19:12  ZimZz  阅读(633)  评论(0编辑  收藏  举报