转义符:
转义字符 | 含义 |
---|---|
\n | 换行 |
\t | 向后移动 |
\b | 退格 |
\r | 回车 |
\f | 换页 |
\ | 显示\ |
’ | 显示、 |
" | 显示“ |
单引号与双引号的是不一样的
单引号表示字符,双引号表示字符串;
字符型:
数据类型 | 存储单位数 |
---|---|
char | 1 |
数据类型大概:
整数型
有符号整数型 | 存储单位数 |
---|---|
int | 4 |
short | 2 |
long | 4 |
long long | 8 |
有无符号的整型的存储单位数是一致的
无符号整型 | 取值范围 |
---|---|
unsigned int | 0~2^32-1 |
unsigend short | 0~2^16-1 |
unsigend long | 0~2^32-1 |
unsigned long long | 0~2^64-1 |
浮点型
浮点类型 | 存储范围 |
---|---|
float | 4 |
double | 8 |
long double | 10 |
常数:
#用宏定义常量dad为jack
#define dad jack
常量(查询无法更改这个量,增加安全性能,用关键字:const)
#用关键字const定义的p,无法被查询更改;
const float p = 3.1212;
输入输出IO:
printf()函数:
1.可以自定义输出宽度:如果指定宽度小了,输出也不会截取,如果大了,会导致输入向右靠齐;
#include <stdio.h>
int main(){
float a = 12.34,b=5.67568;
printf("%2.4f\n",a);
printf("%1.3f\n",b);
return 0;
}
2.对实时的宽度控制:
//m.n,m是控制整数的宽度,n是控制小数的宽度;
printf("%m.nf",%d);
#include <stdio.h>
int main(){
int a = 1234,b=567568;
printf("%2d\n",a);
printf("%25d\n",b);
return 0;
}
格式符 | 使用说明 |
---|---|
d,i | 输出带符号的十进制数 |
o | 输出无符号的八进制数 |
x | 输出无符号的十六进制数 |
u | 无符号的整数 |
c | 单个字符 |
s | 一连串字符 |
f | 输出实数(6位小数) |
其他输出方式:
putchar();
#include <stdio.h>
int main(){
char ch = 'n';
putchar('C');
putchar('C'+37);
putchar('\151');
putchar(ch);
putchar(ch-13);
return 0;
}
puts();
#include <stdio.h>
int main(int argc,char* argv[]){
char ch[] = "C program language!!";
puts(ch);
return 0;
}
scanf()函数
1.scanf()输入时,字符用空格隔开,代表他们不是一个字符;
2.scanf()还可以指定输入的长度:
3.当用户输入的数据大于输入项的时候,多余的输入数据不会作废,会等待下一次输入操作;
4.在scanf()中不要插入字符串,他是不会显示出来的而且还会造成用户的使用困难:
例如
c scanf("请输入:%d",&a); //输入的必须是一下格式:"请输入:1"
5.scanf()有返回值,返回的是输入项的个数:
格式符 | 使用说明 |
---|---|
d,i | 输入带符号的十进制数 |
o | 输入无符号的八进制数 |
x | 输入无符号的十六进制数 |
u | 输入无符号的整数 |
c | 输入单个字符 |
s | 输入一连串字符 |
f | 输入实数(6位小数) |
#include <stdio.h>
int main(){
int a,b,c;
scanf("%d%d%d",&a,&b,&c);
printf("第一个a:%d\n第二个:%d\n第三个:%d\n",a,b,c);
return 0;
}
其他输入方式:
getchar()获得单个字符;输入的字符不需要间隔,因为间隔也是字符;
#include <stdio.h>
int main(){
int a,b,c,d;
a = getchar();
b = getchar();
printf("%c,%c",a,b);
return 0;
}
gets()获得一个字符串;以回车作为字符串输入结束的标志;
#include <stdio.h>
int main(){
char a[20],b[90];
gets(a);
gets(b);
printf("%s\n",a);
printf("%s\n",b);
return 0;
}
语句:
赋值语句:
空语句;
复合语句;{}后面不要加“;”号;
变量作用域
局部变量:
#include <stdio.h>
int main(){
int i = 1;
{
int i = 2;
{
int i = 3;
printf("%d\n",i);
}
printf("%d\n",i);
}
printf("%d\n",i);
return 0;
}
全局变量:
#include <stdio.h>
int i = 0;
int main(){
{
int i = 2;
{
int i = 3;
printf("%d\n",i);
}
printf("%d\n",i);
}
printf("%d\n",i);
return 0;
}
语句执行顺序:
#include <stdio.h>
int i = 0;
void a(){
char i = 'a';
printf("%c",i);
}
int main(){
{
int i = 2;
{
int i = 3;
printf("%d\n",i);
}
printf("%d\n",i);
}
printf("%d\n",i);
a();
return 0;
}
选择结构:
逻辑运算优先级:“!”>“&&”>“||”;
运算符 | 结合方向 |
---|---|
! | 从右向左 |
&& | 从左向右 |
|| | 从左向右 |
if结构
if(表达式)语句;
判断一个数是不是正偶数(if-else):
#include <stdio.h>
int main(){
int i;
printf("请输入一个数,判断它是否是一个正偶数。\n");
scanf("%d",&i);
if(i>0&&!(i%2))
{
printf("%d这个数是正偶数",i);
}
else
{
printf("%d这个数不是正偶数",i);
}
return 0;
}
if嵌套结构;
判断它是否是一个正偶数且被8整除
#include <stdio.h>
int main(){
int i;
printf("请输入一个数,判断它是否是一个正偶数且被8整除。\n");
scanf("%d",&i);
if(i>0&&!(i%2))
{
printf("%d这个数是正偶数",i);
if(!(i%8))
{
printf("且这个数可以被8整除");
}
else
{
printf("但这个数不可以被8整除");
}
}
else
{
printf("%d这个数不是正偶数",i);
}
return 0;
}
if - else:比上面直接if嵌套代码简单;
#include <stdio.h>
int main(){
int i;
printf("请输入一个数,判断它是否是一个正偶数且被8整除。\n");
scanf("%d",&i);
if(i<=0||i%2)
{
printf("%d这个数不是正偶数",i);
}
else if(!(i%8))
{
printf("%d这个数是正偶数且可以被8整除",i);
}
else
{
printf("%d这个数是正偶数但不可以被8整除",i);
}
return 0;
}
switch路径:
1.switch表达式的值必须是整数,即整型与字符型,表达式两边的括号不能省略;
2.case 和 后面的常量表达式之间有空格,且常量表达式不能有变量,常量表达式必须是整型或字符型,且“:”不能省略。
#include <stdio.h>
int main(){
int i;
printf("请输入1~7之间的数,来显示星期几。\n");
scanf("%d",&i);
switch (i) {
case 1:
printf("星期一\n");
break;
case 2:
printf("星期二\n");
break;
case 3:
printf("星期三\n");
break;
case 4:
printf("星期四\n");
break;
case 5:
printf("星期五\n");
break;
case 6:
printf("星期六\n");
break;
case 7:
printf("星期日\n");
break;
default:
printf("请按照要求输入");
}
return 0;
}
if与switch作比较来说,if可以实现switch的所有功能,但switch不能实现switch的所有功能,switch的可读性比if好;它们可以一起使用,取长补短,各取所需;
循环结构:
for语句
for(表达式1;表达式2;表达式3)
循环体;
表达式1:循环前的初始化
表达式2:中止条件
表达式3:步进条件,循环体执行完之后才运行;
计算1-200之间可以被3整除的数量的数:
#include <stdio.h>
int main(){
int a = 0,b = 0;
for (a = 0; a < 201; ++a) {
if(!(a%3))
{
b++;
}
}
printf("%d",b);
return 0;
}
while()循环
while(表达式)
循环体;
do-while()循环
do
循环体
while(表达式)
循环大同小异:三点标配:
1.起点
2.终点
3.有重复执行的语句
跳出循环的语句:
continue语句
只是让当前执行的循环结束,接着循环下一次循环:
#include <stdio.h>
int main(){
for (int i = 0; i < 10; ++i) {
if(i == 5||i==8){
continue;
}
printf("%d\n",i);
}
return 0;
}
break语句
则是直接跳出当前的循环,不会再接着循环了
#include <stdio.h>
int main(){
for (int i = 0; i < 10; ++i) {
if(i == 5||i==8){
break;
}
printf("%d\n",i);
}
return 0;
}
goto语句()
可以让系统直接调到指定目的,但不推荐用,因为它的可读性差,不利于系统稳定;
循环嵌套:
描绘出九九乘法表:
#include <stdio.h>
int main(){
int a = 0;
for (int i = 0; i < 10; ++i) {
++a;
for (int j = 1; j < a; ++j) {
printf("%d*%d=%d\t",i,j,(i*j));
}
printf("\n");
}
return 0;
}
金字塔
#include <stdio.h>
int main(){
int a = 0;
for (int i = 0; i < 8; ++i) {
for (int j = 0; j < 15; ++j) {
if(j >= (7-i) && j <= (7+i))
{
printf("*");
}
printf("\t");
}
}
return 0;
}
函数
无参函数
函数返回值的类型 函数名()
{
函数体
}
不能再函数内部定义函数,但可以在函数内部引用函数;
#include <stdio.h>
int a(){
int a = 100;
return a;
}
int main(){
int b;
b = a();
printf("%d",b);
return 0;
}
返回值的类型转换;始终将表达式的类型转换成“函数返回值的类型”;
例如:下面的假若定义为
#include <stdio.h>
int a(){
//a类型为字符型
char a = 100;
return a;
}
int main(){
int b;
//函数a()的返回值类型是int型
b = a();
printf("%d",b);
return 0;
}
假如函数内有多个return,但函数不会返回多个返回值,因为函数只能返回一个值,所以有时“return”的作用与break的作用相似,只不过一个会导致函数中止,一个是让循环中止;
函数的使用遵循“先定义,后使用”,那如果先“先使用,在定义”可以吗?
答案是:可以的,但需要声名:(不要忘记在声明 的后面加上“;”)
#include <stdio.h>
int a();
int main(){
int b;
b = a();
printf("%d",b);
return 0;
}
int a(){
int a = 100;
return a;
}
定义在函数外的变量,会不断累加,除非函数有初始化,要注意!!
定义在函数内的变脸,会因为函数的消失,消失,但有例外!!!
静态变量(关键字 static)
#include <stdio.h>
int a();
int main(){
int b,c;
b = a();
c = a();
printf("%d",b);
printf("%d",c);
return 0;
}
int a(){
static int a = 100;
a += 100;
return a;
}
有参函数:
函数返回值类型 函数名(类型1 形参1,类型2 形参2,类型3 形参3)
{
函数体
}
#include <stdio.h>
//声明函数的时候,括号内的类型必须有,形参可以没有;
int add(int,int);
int main(){
int b,c;
b = add(2,4);
printf("%d",b);
return 0;
}
int add(int add_1,int add_2){
int add_3;
add_3 = add_1 + add_2;
return add_3;
}
递归函数:(听说蛮好用的,目前没有涉及到)
#include <stdio.h>
int add(int add_1);
int main(){
int b,c;
b = add(100);
printf("%d",b);
return 0;
}
int add(int add_1){
if( add_1 == 1)
return 3;
add(add_1-1);
}
递归分为
- 直接递归
- 间接递归
递归可以解决的问题满足三点:
- 要解决的问题可以转化成新的问题,而且新问题与旧问题没有本质的区别;
- 问题逐渐转化,原来的问题可以解决;
- 函数中有结束递归的条件;
利用求n!:
#include <stdio.h>
int add(int n);
int main(){
int b,c;
b = add(5);
printf("%d",b);
return 0;
}
int add(int n){
if(n == 1)
return 1;
return n* add(n-1);
}
逆序输出:
1使用循环:
#include <stdio.h>
int main(){
int a,b =0;
printf("请输入一串数字。");
scanf("%d",&a);
while(1)
{
if(a>10)
{
printf("%d",a%10);
a = a/10;
}
else
{
printf("%d",a);
break;
}
}
return 0;
}
递归函数的方法:
#include <stdio.h>
int in(int);
int main(){
int a,b =0;
printf("请输入一串数字。");
scanf("%d",&a);
in(a);
return 0;
}
int in(int n){
if(n<10){
printf("%d",n);
}
else{
printf("%d",n%10);
in(n/10);
}
}
练习:
#include <stdio.h>
int in(int);
int main(){
int a,b =0;
printf("请输入一串数字。");
scanf("%d",&a);
b=in(a);
printf("%d",b);
return 0;
}
int in(int n){
if(n == 1)
{
return 1;
}
return (n*n*n + in(n-1));
}
数组
数据类型 数组名[整型常量表达式] = {数据1,数据2,数据3,...}
数组的赋值:
#include <stdio.h>
int main(){
int list[5];
for (int i = 0; i < 5; ++i) {
list[i] = i+1;
}
for (int i = 0; i < 5; ++i) {
printf("%d\n",list[i]);
}
return 0;
}
使用数组与随机生成函数:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int list[20];
int main(){
srand((unsigned int) time(0));
for (int i = 0; i < 20; ++i) {
list[i] = rand()%1001;
}
for (int i = 0; i < 20; ++i) {
printf("%d\n",list[i]);
}
return 0;
}
冒泡排列:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int list_a[20];
int b;
int main(){
srand((unsigned int) time(0));
for (int i = 0; i < 20; ++i) {
list_a[i] = rand()%1001;
}
for (int i = 0; i < 19; ++i) {
for (int i = 0; i < 19; ++i) {
if (list_a[i] > list_a[i + 1]) {
b = list_a[i];
list_a[i] = list_a[i + 1];
list_a[i + 1] = b;
} else { ;
}
}
}
for (int i = 0; i < 20; ++i) {
printf("%d\n", list_a[i]);
}
return 0;
}
选择排序:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int list_a[20];
int temp;
int main(){
srand((unsigned int) time(0));
for (int i = 0; i < 20; ++i) {
list_a[i] = rand()%1001;
}
for (int i = 0; i < 19; ++i) {
int pos = 0;
for (int j = 1; j < 20-i; ++j) {
if(list_a[pos] < list_a[j])
{
pos = j;
}
//检测是否需要更换位置
if(pos != 19-i)
{
temp = list_a[pos];
list_a[pos] = list_a[19-i];
list_a[19-i] = temp;
}
}
}
for (int i = 0; i < 20; ++i) {
printf("%d\n", list_a[i]);
}
return 0;
}
二维数组:
数据类型 数组名[整数常量表达式] [整数常量表达式],...
二维数组赋值
int seat[3][3] = {{1,2,3},{4,5,6},{7,8,9}};
int seat[3][3] = {1,2,3,4,5,6,7,8,9};
二维数组可以省略第一个下标;
此外还有多维数组;
指针
数据类型* 变量名;
数据变量 *变量名;
&变量名 可以获得变量的地址
#include <stdio.h>
int main(){
int a = 21;
int *p = &a;
printf("%d",*p);
return 0;
}
这里说明一下:
int *p = &a;
中的“*”星号仅仅起到标记作用,a的地址还是赋给P的;
类似:
int *p;
p = &a;
//不可以
*p = &a;
而printf(“%d”,*p);中的星号是起作用的,类似箭头指向P中所存地址中的内容;
scanf与指针的作用:因为p是用于存储地址的所以可以直接将scanf的形参可以直接用它;
#include <stdio.h>
int main(){
int a = 21;
int *p = &a;
scanf("%d",p);
printf("%d",*p);
return 0;
}
指针的可以进行四则运算不用小括号括起来,在自增自减的时候要用小括号括起来:
(*P)++;
(*p)--;
熟悉指针的练习-指针与数组的关系;
同一数组中的变量的地址
#include <stdio.h>
int main(){
int list_a[10];
int *p;
for (int i = 0; i < 10; ++i) {
p = &list_a[i];
printf("%d\n",p);
}
return 0;
}
#include <stdio.h>
int main(){
int list_a[10]={1,2,3,4,5,6,7,8,9,0};
int *p;
//下面两种赋值都是可以的;
//p = &list_a[0];
p = list_a;
for (int i = 0; i < 10; ++i) {
printf("%d\n",*(p+i));
}
return 0;
}
用指针实现数组的逆序输出,更简单;
#include <stdio.h>
int main(){
int list_a[10] = {1,2,3,4,5,6,7,8,9,0};
int *p_1;
p_1 = list_a;
for (int i = 0; i < 10; ++i) {
printf("%d",*(p_1+9-i));
}
return 0;
}
指向二维数组的指针:
例如
num[2][2]
int *p = num[][0];
num[2][1]的指针是p+2*1+1;
保存指针的数组;
#include <stdio.h>
int main(){
int list_a[4][4] = {{1,2,3,4},{5,6,7,8},{11,12,13,14},{15,16,17,18}};
int *list_p[4];
for (int i = 0; i < 4; ++i) {
list_p[i] = list_a[i];
}
for (int i = 0; i < 4; ++i) {
for (int j = 0; j < 4; ++j) {
printf("%d\n",*(list_p[i]+j));
}
}
return 0;
}
指针与函数的结合
可以通过让函数传入指针获得更改数据的力量:
#include <stdio.h>
int add(int *p);
int main(){
int a =10;
add(&a);
printf("%d",a);
return 0;
}
int add(int *p)
{
*p = *p + 5;
return 0;
}
指针还可以用来指代函数;
二级指针:
int **p;
结构:
关键词:struct
struct 结构类型名
{
数据类型1 成员变量名1;
数据类型2 成员变量名2;
数据类型3 成员变量名3;
数据类型4 成员变量名4;
数据类型5 成员变量名5;
}变量名;
#include <stdio.h>
int main(){
struct student {
int id_name;
char sex;
short height;
short weight;
short age;
}student1= {110,2,175,70,21};
printf("%d",student1.id_name);
return 0;
}
typedef的作用:赋予特定的符号和类型关键字一样的效果
typedef struct student ST;
typedef int integer;
#include <stdio.h>
int main(){
struct student {
int id_name;
char sex;
short height;
short weight;
short age;
}student1= {110,2,175,70,21};
typedef struct student ST;
ST student2 = {120,3,180,76,24};
printf("%d\n",student1.id_name);
int *p = &student2.id_name;
printf("%d",*p);
return 0;
}
链表:
结构体中有指针,指针指向同类型的结构体;
#include <stdio.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st student1 = {1,2};
st student2 = {3,4};
st student3 = {5,6};
student1.p = &student1;
student2.p = &student3;
student3.p = &student2;
printf("%d\n",student1.id);
printf("%d\n",student1.p -> id);
printf("%d\n",student2.p -> id);
return 0;
}
链表与数组的配合
数组是可以存放大量一样类型的数据;长度固定;
链表可以存储大量任意类型的数据;长度可变;
链表最小单元----结点;
结点可以分为“数据域”,“指针域”;
struct student
{
//数据域
int id;
char sex;
//指针域
struct student *p;
};
链表的构成为:
- 头结点
- 数据结点
- 尾结点
建立动态链表:
malloc()动态申请空间;
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st *next;
next = (st *) malloc(sizeof(st));
if(next!=NULL)
{
next -> id = 10;
next -> sex = 1;
printf("%d %d",next -> id,next -> sex);
}
return 0;
}
建立动态链表的源码:
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st student1 = {1,'a'};
st student2 = {2,'b'};
st student3 = {3,'c'};
student1.p = &student2;
student2.p = &student3;
st *next;
next = (st *) malloc(sizeof(st));
if(next != NULL)
{
next -> id = 4;
next -> sex = 'd';
student3.p = next;
}
st *start;
start = &student1;
for (int i = 0; i < 4; ++i) {
printf("id:%d\tsex:%c\n",start->id,start->sex);
start = start -> p;
}
return 0;
}
对链表的操作:
- 插入结点
- 删除结点
在链表开头插入新的结点:
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st student1 = {1,'a'};
st student2 = {2,'b'};
st student3 = {3,'c'};
student1.p = &student2;
student2.p = &student3;
st *next;
next = (st *) malloc(sizeof(st));
if(next != NULL)
{
next -> id = 4;
next -> sex = 'd';
student3.p = next;
}
// st *start;
// start = &student1;
// for (int i = 0; i < 4; ++i) {
// printf("id:%d\tsex:%c\n",start->id,start->sex);
// start = start -> p;
// }
st *p_new;
p_new = (st *) malloc(sizeof(st));
if(p_new!=NULL)
{
p_new -> id = 0;
p_new -> sex = 'e';
p_new -> p = &student1;
}
st *start;
start = p_new;
for (int i = 0; i < 10; ++i) {
printf("id:%d\tsex:%c\n",start -> id,start -> sex);
start = start -> p;
}
return 0;
}
在链表结尾插入结点:
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st student1 = {1,'a'};
st student2 = {2,'b'};
st student3 = {3,'c'};
student1.p = &student2;
student2.p = &student3;
st *next;
next = (st *) malloc(sizeof(st));
if(next != NULL)
{
next -> id = 4;
next -> sex = 'd';
student3.p = next;
}
// st *start;
// start = &student1;
// for (int i = 0; i < 4; ++i) {
// printf("id:%d\tsex:%c\n",start->id,start->sex);
// start = start -> p;
// }
//开头插入链表结点
st *p_new;
p_new = (st *) malloc(sizeof(st));
if(p_new!=NULL)
{
p_new -> id = 0;
p_new -> sex = 'e';
p_new -> p = &student1;
}
//结尾插入链表结点
st *bottom;
bottom = (st *)malloc(sizeof(st));
if(bottom!=NULL)
{
bottom -> id = 5;
bottom -> sex = 'f';
bottom -> p = NULL;
next -> p = bottom;
}
st *start;
start = p_new;
for (int i = 0; i < 10; ++i) {
printf("id:%d\tsex:%c\n",start -> id,start -> sex);
start = start -> p;
}
return 0;
}
在链表中间出插入结点;
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char sex;
struct student *p;
};
int main(){
typedef struct student st;
st student1 = {1,'a'};
st student2 = {2,'b'};
st student3 = {3,'c'};
student1.p = &student2;
student2.p = &student3;
st *next;
next = (st *) malloc(sizeof(st));
if(next != NULL)
{
next -> id = 4;
next -> sex = 'd';
student3.p = next;
}
// st *start;
// start = &student1;
// for (int i = 0; i < 4; ++i) {
// printf("id:%d\tsex:%c\n",start->id,start->sex);
// start = start -> p;
// }
//开头插入链表结点
st *p_new;
p_new = (st *) malloc(sizeof(st));
if(p_new!=NULL)
{
p_new -> id = 0;
p_new -> sex = 'e';
p_new -> p = &student1;
}
//结尾插入链表结点
st *bottom;
bottom = (st *)malloc(sizeof(st));
if(bottom!=NULL)
{
bottom -> id = 5;
bottom -> sex = 'f';
bottom -> p = NULL;
next -> p = bottom;
}
st *temp;
temp = (st *) malloc(sizeof(st));
if(temp!=NULL)
{
temp -> id = 11;
temp -> sex = 'y';
temp -> p = next;
student3.p = temp;
}
st *start;
start = p_new;
for (int i = 0; i < 10; ++i) {
printf("id:%d\tsex:%c\n",start -> id,start -> sex);
start = start -> p;
}
return 0;
}
删除链表中的结点:
用到的函数free()释放内存;
学生系统:
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
char name;
char sex;
char age;
struct student *next;
};
typedef struct student st;
void show();
int get_choose();
void show_all_students(st *head);
int sum_student(st *head);
void insert_student(st *head);
void del_student(st *head);
void select_student(st *head);
st *p_head;
int main() {
int choose;
p_head = (st *) malloc(sizeof(st));
p_head -> next = NULL;
while(1)
{
show();
choose = get_choose();
switch (choose)
{
case 1:show_all_students(p_head);break;
case 2:insert_student(p_head);break;
case 3:del_student(p_head);break;
case 4:select_student(p_head);break;
case 5:break;
default:break;
}
if(choose == 5)
{
break;
}
}
return 0;
}
void show()
{
puts("请选择你的操作:\n1.显示是所有学生信息\n2.插入学生信息\n3.删除学习信息\n4.搜索学生信息\n5.结束系统\n");
}
int get_choose()
{
int choose_item = 0;
printf("----------------------你选择的操作是:----------------------\n");
scanf("%d",&choose_item);
if(choose_item>=1 && choose_item<=5)
{
return choose_item;
}
else
{
puts("----------------------输入有误,退出程序----------------------\n");
return (7);
}
}
void show_all_students(st *head)
{
st *p;
p = head -> next;
int count = 0;
while(p)
{
if(count == 0)
{
puts("账号\t姓名\t性别\t年龄\n");
}
printf("id:%d\tname:%c\tsex:%c\tage:%d\n", p->id, p->name, p->sex,p ->age);
count ++;
p = p -> next;
}
if(count == 0)
{
puts("----------------------无学生信息----------------------\n");
return;
}
puts("----------------------以上是所有学生信息----------------------");
}
int sum_student(st *head)
{
int count;
st *p;
p = head -> next;
count = 0;
while(p) {
count++;
p = p->next;
}
return count;
}
void insert_student(st *head)
{
int pos,count;
count = sum_student(head)+1;
puts("----------------------输入你想要插入的位置----------------------\n");
printf("----------------------范围在1~%d----------------------\n",count);
scanf("%d",&pos);
if(pos< 1 || pos>count)
{
puts("----------------------输入错误,请重新输入!----------------------\n");
}
else {
st *new;
new = (st *) malloc(sizeof(st));
if (new != NULL) {
puts("----------------------请输入学生信息----------------------");
scanf("%d %c %c %s", &new->id, &new->name, &new->sex, &new->age);
}
st *p_front;
p_front = head;
for (int i = 1; i < pos; ++i) {
p_front = p_front->next;
}
st *temp;
temp = p_front->next;
p_front->next = new;
new->next = temp;
}
}
void del_student(st *head)
{
int count,pos;
count = sum_student(head);
if(count == 0)
{
puts("----------------------无学生信息,操作无效----------------------\n");
}
else
{
printf("目前数据库内存有的学生资料一共有:%d\n",count);
puts("请输入你要删除的学生资料:");
scanf("%d",&pos);
st *p_front;
p_front = head;
for (int i = 1; i < pos; ++i) {
p_front = p_front -> next;
}
st *temp;
temp = p_front -> next;
p_front -> next = temp -> next;
free(temp);
puts("----------------------删除成功----------------------");
}
}
void select_student(st *head)
{
int pos,id,a = 0;
pos = sum_student(head);
if(pos == 0)
{
puts("----------------------无学生信息,操作无效----------------------\n");
}
else {
printf("目前数据库一共有:%d样本。\n请输入你要搜索的学生id:", pos);
scanf("%d", &id);
st *p;
p = head->next;
while (p) {
if (id == p->id) {
printf("id:%d\tname:%c\tsex:%c\tage:%d\n", p->id, p->name, p->sex, p->age);
a = 1;
puts("----------------------以上是所有学生信息----------------------\n");
break;
}
p = p -> next;
}
if(a == 0)
{
puts("----------------------数据库内查无此人。----------------------\n");
}
}
}
联合(类似创建一个万能类型的变量,所以联合常常作为构造体的元素):
联合体的定义和结构体是相似的;
特殊点:联合内所有的变量都是指代同一储存空间中的数据;
1.因为所有成员均指代同一数据,最后写入的数据会覆盖之前所写的数据;
2.为了得到正确的数据,应该使用最后赋值的成员变量读取数据;
union 联合体类型名
{
数据类型1 :成员名1;
数据类型2 :成员名2;
.......
}
#include <stdio.h>
#include <stdlib.h>
union all{
short grade;
char title;
short work_year;
};
typedef union all un;
struct school{
short name;
char sex;
short age;
char profession;
un un1;
};
typedef struct school sc;
void show(sc list[4]);
int main(){
sc list[4] = {
{1,'m',24,'t'},
{2,'n',23,'s'},
{3,'w',21,'s'},
{4,'w',22,'w'}
};
list[0].un1.title = 'q';
list[1].un1.grade = 3;
list[2].un1.grade = 3;
list[3].un1.work_year = 8;
show(list);
// for (int i = 0; i < 4; ++i) {
// printf("%hd\t%c\t%hd\t%c\n",list[i].name,list[i].sex,list[i].age,list[i].profession);
//
// }
return 0;
}
void show(sc *p)
{
puts("姓名\t性别\t年龄\t职业\t年级/工龄/职称\n");
for (int i = 0; i < 4; ++i) {
printf("%c\t%c\t%hd\t%c\t",p ->name,p ->sex,p ->age,p ->profession);
if(p ->profession == 't')
{
printf("%c\n",p ->un1.title);
}
else if(p ->profession == 's')
{
printf("%hd\n",p ->un1.grade);
}
else if(p ->profession == 'w')
{
printf("%hd\n",p ->un1.work_year);
}
else
{
;
}
}
}
枚举(受到限制的整数常量,经常与switch一起使用;):
enum 枚举类型名 {枚举常量1,枚举常量2,枚举常量3,......};
字符串:
字符串赋值:
char list[] = "hello world!";
字符串输出:
#include <stdio.h>
int main(){
int i;
char list[] = "hello world!";
puts(list);
printf("%s\n",list);
while(list[i]!='\0')
{
printf("%c",list[i]);
i++;
}
return 0;
}
字符串的输入:
//空格不会打断输入
#include <stdio.h>
int main(){
int i;
char list_a[20];
gets(list_a);
puts(list_a);
return 0;
}
//空格会打断输入
#include <stdio.h>
int main(){
int i;
char list_a[20];
scanf("%s",list_a);
printf("%s",list_a);
return 0;
}
字符串的操作:
string.h库
1.复制:
char *p1 = strcpy(arr2,arr1);
2.相加:
//将src指向发字符串,复制到的dest地址开始的字符串结尾处;返回dest地址的指针
char *strcat(char *dest,char *src)
//将src指向的字符串的前n个字符,复制到dest地址开始的字符串的结尾处,返回dest地址
char *strncat(char *dest,char *src,int n)
3.修改:
//将s指向的字符串中的所有字符设置成字符C,返回指向s的指针
char *strset(char *s,char c)
//将s指向的字符串中的前你个字符设置成字符c,返回指向是的指针
char *strnset(char *s,char c,int n)
4.比较
//比较s1与s2指向的字符串的大小
int strcmp(char *s1,char *s2)
//比较s1与s2指向字符串的大小,不分大小写;
int stricmp(char *s1,char *s2)
//tui
int strncmp(chat *s1,char *s2,int n)
//tui
int strnicmp(char *s1,chat *s2,int n)
//返回一个整数
s1 < s2 :返回值 < 0;
s1 = s2 ;返回值 = 0;
s1 > s2 ;返回值 > 0'
其他操作:
//大小写转换
char *strlwr(char *p) //小写
char *strupr(char *p) //大写
int strlen(char *s)//字符中的个数
char *strrev(char *s)//反转字符串
//还有定位函数,详见string的说明文档
文件
fopen()
在这里插入代码片
预编译:
宏(起到替换作用):
//生成宏
#define add 5
//取消宏
#undef add
条件编译(为了适应不同硬件,选择性编译代码):
#if
#include <stdio.h>
int main(int argc,char *argv[]){
#if 2 >3
puts("1");
#else
puts("2");
#endif
return 0;
}
#ifdef
#include <stdio.h>
#define add 3
int main(int argc,char *argv[]){
#ifdef add
puts("1");
#else
puts("2");
#endif
return 0;
}
#ifndef
#include <stdio.h>
#define add 3
int main(int argc,char *argv[]){
#ifndef add
puts("1");
#else
puts("2");
#endif
return 0;
}