大程序结构
它的意思可以说是这样
main()里边的代码长了,适合分成几个函数
一个源代码文件长了,适合分成几个文件
项目
这个需要新建一个项目,然后把相关的文件添加进来
有的IDE有分开的编译和构建按钮,前者是对单个源文件编译,后者是对整个项目做链接
头文件
把函数原型放到一个头文件中,在需要是在相应的.c文件(源文件)中用include包含,这样可以让编译器在编译时知道函数的原型
在使用和定义这个函数的地方都应该#include这个头文件(后缀为.h)
一般的做法就是任何.c(main.c除外)都有对应的同名.h把所有对外公开的函数的原型和全局变量的声明都放进去
只有声明可以放到头文件中,这是规则不是法律,否则会造成一个项目中多个编译单元有重名的实体
某些编译器允许几个编译单元中存在同名的函数或者用week修饰符来强调这种存在
下面举个例子
新建一个C项目,选择控制台应用程序,并给项目起个名字,这时会有一个main.c文件,下面添加一个头文件
例1:
main.c文件:
# include <stdio.h>
# include "max.h"
//这里用双引号(半角)代替<>,当然stdio.h也可以用双引号,不过一般自定义的头文件都用双引号包括
int main(int argc, char *argv[]) {
int a, b;
printf("请输入两个整数,中间用空格分开:");
scanf("%d %d", &a, &b);
printf("%d\n", max(a, b));
return 0;
}
max.h
int max(int a, int b);
//这是max函数的原型(声明),自定义函数原型定义在头文件中
max.c
//这里放的是函数体,即函数的定义
int max(int a, int b) {
return a>b ? a : b; //使用三目运算符返回两个数中的大数
}
示例输出结果为:
这仅仅是一个简单的程序,平时直接新建一个文件就行了,只有在写较大的程序时才会将程序分成源文件和头文件,这里仅仅是举例
如果此时关闭项目,只打开一个main.c文件,编译时会报错,因为
两个独立的源码文件不能编译形成可执行程序
编译单元
一个.c文件是一个编译单元
编译器每次编译只处理一个编译单元
在编写一些较大的程序时,如果所有文件都已经编译过,而在需要修改哪个源文件时,再进行编译可以只编译被修改文件,而可以不用对其它文件再次编译
“”还是< >
“”要求编译器首先在当前目录(.c文件所在目录)寻找这个文件,如果没有,到编译器指定的目录去找
< >让编译器只在指定的目录去找
编译器自己知道自己的标准库的头文件在哪里
环境变量和编译器命令行参数也可以指定寻找头文件的目录
#include的误区
它不是用来引入库的
stdio.h里只有printf等的原型,其代码在另外的地方
某个.lib(windows)或.a(unix)中
现在的C语言编译器默认会引入所有的标准库
#include<stdio.h>只是为了让编译器知道printf等函数的原型
不对外公开的函数
在函数前面加上static就使得它成为只能在所在的编译单元中被使用的函数,
在全局变量前面加上static就使得它成为只能在所在编译单元中被使用的全局变量
声明和定义
声明是不产生代码的东西
函数原型
变量声明
结构声明
宏声明
枚举声明
类型声明
inline声明
定义是产生代码的东西
int i;是变量的定义
extern int i;是变量的声明
extern用来告知编译器变量在当前范围之外声明过了.被extern语句描述过的变量将分派不到任何空间,因为他们在别的地方被定义过了.extern语句频繁的用于在多个文件之间的跨范围数据传递.
inline这个关键字请求编译器扩张一个给定的函数。它向这个函数发出一条插入代码的call。函数里面有静态变量,嵌套的,switches,或者是递归的时候不给予内联。当一个函数声明包含在一个类声明里面时,编译器会尝试的自动把函数内联。
关键字inline请求编译器给一个函数扩展空间,它向这个函数发出一条插入代码的call.函数里面有 static 数据, 循环,static 或者是递归的时候不给予内联.当一个函数声明包含在一个类声明里面时,编译器会尝试的自动把函数内联.
下面举个较大的程序的例子——学生成绩管理系统(有一些简单的操作)
例2:
main.c文件:
# include <stdio.h>
# include <stdlib.h>
int main(void) {
system("color 2f");
int flag = 0;
menu();
do {
flag = 1;
switch(getch()) {
case '1' :
inputscore();
break;
case '2' :
lookscore();
break;
case '3' :
searchscore();
break;
case '4' :
statistic();
break;
case '5' :
modify();
break;
case '6' :
add();
break;
case '7' :
delscore();
break;
case '8' :
savescore();
break;
case '9' :
exit(0);
default :
printf("输入有误\n");
}
printf("按任意键继续\n");
getch();
menu();
}while (flag == 1);
return 0;
}
studentscore.h文件:
# include <stdio.h>
# include <string.h>
# include <stdlib.h>
# define N 30
# define M 3
typedef struct student {
char number[10];
char name[20];
float score[M];
float aver;
}STU, * PSTU;
STU stu[N];
int n, x = 0;
void menu(void); //菜单
void inputscore(void); //输入学生信息及成绩
void avergescore(void); //求平均
void lookscore(void); //查看成绩
void searchscore(void); //查找成绩
void statistic(void); //成绩统计
void modify(void); //修改成绩
void add(void); //添加成绩
void delscore(void); //删除成绩
void savescore(void); //保存成绩
studentscore.c文件:
# include "studentscore.h"
/*****************************菜单************************************/
void menu(void) {
system("cls");
printf("\n");
printf("\t\t※※★★★★★欢迎进入学生成绩管理系统★★★★★※※\n");
printf("\t\t|**************************************************|\n");
printf("\t\t| 菜单 |\n");
printf("\t\t|**************************************************|\n");
printf("\t\t|录入成绩----------------------------------------1 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|查看成绩及成绩排序------------------------------2 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|查询学生成绩------------------------------------3 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|成绩统计----------------------------------------4 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|修改成绩----------------------------------------5 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|添加成绩----------------------------------------6 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|删除成绩----------------------------------------7 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|保存成绩----------------------------------------8 |\n\t\t|\t\t\t\t\t\t |\n");
printf("\t\t|退出系统----------------------------------------9 |\n");
printf("\t\t※★★★★★★★★★★★★★★★★★★★★★★★★※\n");
printf("\t\t请输入您的选择\n");
}
/***************输入各个同学的学生信息******************************/
void inputscore(void) {
int i, j;
system("cls");
printf("请输入学生总数: ");
scanf("%d", &n);
for(i=0; i<n; i++) {
printf("请输入学生 %d 的学号 姓名(中间用空格分隔):\n", i+1);
scanf("%s %s", stu[i].number, stu[i].name);
printf("请输入学生成绩(中间用空格分隔):\n");
printf("数据结构\tjava程序设计\t汇编\n");
for(j=0; j<M; j++)
scanf("%f", &stu[i].score[j]);
printf("\n");
}
printf("成功输入\n");
}
/*****************计算各个同学的平均分*****************************/
void avergescore(void) {
int i, j;
for(i=0; i<n; i++) {
stu[i].aver = 0;
for(j=0; j<M; j++) {
stu[i].aver += stu[i].score[j];
}
stu[i].aver = stu[i].aver / M;
}
}
/************查看学生成绩及根据平均分对学生进行排序*********************/
void lookscore(void) {
int i, j, k;
STU t;
avergescore();
system("cls");
for(i=0; i<n-1; i++) {
for(k=i,j=i+1; j<n; j++)
if(stu[j].aver > stu[k].aver)
k = j;
if(k != j) {
t = stu[k];
stu[k] = stu[i];
stu[i] = t;
}
}
printf("名次\t学号\t姓名\t数据结构 java程序设计 汇编 平均分\n");
for(i=0; i<n; i++) {
printf("%d\t%s\t%s\t",i+1, stu[i].number, stu[i].name);
for(j=0; j<M; j++)
printf("%4.2f\t\t", stu[i].score[j]);
printf("%4.2f", stu[i].aver);
printf("\n");
}
}
/*****************通过输入学号查找学生成绩***************************/
void searchscore(void) {
char a[10];
int i, j;
system("cls");
avergescore();
printf("请输入需查询的学生学号\n");
scanf("%s", a);
for(i=0; i<=n; i++) {
if(strcmp(a, stu[i].number) == 0) {
printf("名次\t学号\t姓名\t数据结构 java程序设计 汇编 平均分\n");
printf("%d\t%s\t%s\t",i+1, stu[i].number, stu[i].name);
for(j=0; j<M; j++)
printf("%4.2f\t\t", stu[i].score[j]);
printf("%4.2f", stu[i].aver);
printf("\n");
break;
}
if(n == i)
printf("未找到该学生信息\n");
}
}
/*******统计学生成绩信息,平均分及格率,优秀率,成绩方差****************/
void statistic(void) {
PSTU p = stu;
int i, j;
float count = 0.0, sum = 0.0;
system("cls");
avergescore();
for(i=0; i<n; i++) /*平均分计算*/ {
sum += (p+i)->aver;
}
printf("该班级平均分为%4.2f\n\n", sum/n);
for(i=0; i<n; i++) /*及格率计算*/ {
if((p+i)->aver >= 60)
count++;
}
printf("该班级及格率为%4.2f%%\n\n", count/n*100);
count = 0.0;
for(i=0; i<n; i++) /*优秀率计算*/ {
if((p+i)->aver >= 90)
count++;
}
printf("该班级优秀率为%4.2f%%\n\n", count/n*100);
for(i=0; i<n; i++) /*方差计算*/ {
for(j=0; j<M; j++) {
sum = ((p+i)->score[j] - (p+i)->aver) * ((p+i)->score[j] - (p+i)->aver);
}
sum = sum/n;
printf("学生%s的成绩方差为%4.2f\n\n", (p+i)->name, sum);
}
printf("平均分低于60的学生名单:\n");
for(i=0; i<n; i++) {
if(stu[i].aver < 60) {
x++;
printf("%3s\n\n", stu[i].name);
}
}
if(0 == x) {
printf("所有同学都及格了!!!\n\n");
}
}
/***************修改学生成绩*********************************************/
void modify(void) {
char a[10];
int i, j;
system("cls");
avergescore();
printf("请输入需要修改成绩的学生学号\n");
scanf("%s", a);
for(i=0; i<=n; i++) {
if(strcmp(a, stu[i].number) == 0) {
printf("名次\t学号\t姓名\t数据结构 java程序设计 汇编 平均分\n");
printf("%d\t%s\t%s\t",i+1, stu[i].number, stu[i].name);
for(j=0; j<M; j++)
printf("%4.2f\t\t", stu[i].score[j]);
printf("%4.2f", stu[i].aver);
printf("\n");
printf("请重新输入学生成绩:\n");
printf("数据结构\tjava程序设计\t汇编\n");
for(j=0; j<M; j++)
scanf("%f", &stu[i].score[j]);
printf("修改成功\n");
break;
}
if(n == i)
printf("未找到该学生信息\n");
}
}
/*****************添加学生成绩********************/
void add(void) {
int a, i, j;
system("cls");
avergescore();
printf("请输入新增加的学生人数:\n");
scanf("%d", &a);
n +=a;
for(i=n-a; i<n; i++) {
printf("请输入学生%d的学号 姓名:\n", i+1);
scanf("%s %s", stu[i].number, stu[i].name);
printf("请输入学生成绩:\n");
printf("数据结构\tjava程序设计\t汇编\n");
for(j=0; j<M; j++)
scanf("%f", &stu[i].score[j]);
printf("添加成功\n");
}
}
/*******************删除学生成绩*****************************************/
void delscore(void) {
int i, j, c;
char m, a[10];
system("cls");
printf("请输入学生学号\n");
scanf("%s", a);
for(i=0; i<=n; i++) {
if(strcmp(a, stu[i].number) == 0) {
printf("名次\t学号\t姓名\t数据结构 java程序设计 汇编 平均分\n");
printf("%d\t%s\t%s\t",i+1, stu[i].number, stu[i].name);
for(j=0; j<M; j++)
printf("%4.2f\t\t", stu[i].score[j]);
printf("%4.2f", stu[i].aver);
printf("\n");
c = i;
break;
}
if(n == i) {
printf("未找到该学生信息\n");
return;
}
}
printf("是否删除该学生成绩(y/n)\n");
scanf("%s", &m);
if(m == 'y') {
for(i=c; i<=n-1; i++)
stu[i] = stu[i+1];
n += 1;
printf("删除成功\n");
}
else
printf("删除失败\n");
}
/******************保存学生成绩************************/
void savescore(void) {
FILE * fp;
int i, flag = 1;
char m;
system("cls");
avergescore();
puts("是否保存学生成绩(y/n)");
scanf("%s", &m);
if(m == 'y') {
if((fp = fopen("score.dat","wb")) == NULL) {
printf("文件打开失败\n");
return;
}
for(i=0; i<n; i++)
if(fwrite(&stu[i], sizeof(struct student), 1, fp) != 1) {
printf("保存失败\n");
flag = 0;
}
if(flag == 1)
printf("保存成功!\n");
fclose(fp);
}
else
return;
}
部分输出操作结果:
【所有代码均在windows系统下dev c++下运行通过】
(如有错误,敬请指正)