C程序设计(谭浩强第五版)总结
本篇文章主要是总结谭浩强第五版C语言书上的重点和易漏点的知识点,其目的主要是给高校期末考试的同学们点参考。本文所参考的书籍是谭浩强的《C程序设计(第五版)》和明日科技所著的《C语言从入门到精通》,整体文章脉络框架是作者大学C语言老师所给的期末考试的知识点索引表。作者能力有限,文章中有不全不妥之处欢迎大家批评指正,我也非常希望读者能从此文章中获益!
目录
C语言和程序设计 2
1.计算机语言的发展阶段 2
2.学习C语言的目的及C语言的应用 2
3.C语言的程序结构 3
算法基础 3
1.算法基本概念和特性 3
2.算法的表示方法 3
C语言基础 4
1.标识符(用来表示常量名,变量名,函数名及数组名等) 4
2.常量类型 4
3.变量类型及用法 5
运算符与表达式 5
1.强制类型转换 5
2.自增自减运算 5
3.逗号运算符与逗号表达式 6
4.复合赋值运算符 6
5.C语言中复合运算优先级 6
6.简述for(循环语句)以及break,continue(转移语句)语句区别 6
选择程序结构设计 7
1.#if语句(注意if后用else if和if区别,后者是为并列) 7
2.#Switch语句 8
循环结构程序设计 9
1.#While语句 9
2.#for语句 10
3.#双重循环(设计一个九九乘法表) 10
4.#多重循环(排出a,b,c于x,y,z的对阵表//教材中的拔高题) 11
数组 11
1.不同数组类型的定义 11
2.字符串函数 12
3.#逆序输出 12
4.#求最大值及下标 12
5.#Fibonacci序列 13
6.#杨辉三角序列 13
7.#排序输出(冒泡法和选择法)//拔高题 14
用函数实现模块化设计 15
1. 函数的说明(注意点) 15
2. 定义函数的方法 15
3. 函数调用的一般形式 15
4.#函数的嵌套调用(比较四个数字的最大值) 15
5.#函数的递归调用(此类题不好想可以记住死套路编写) 16
6.#数组函数的代码编程题 17
7.全局和局部声明 18
指针 18
1. 指针相关用法 18
2. #数组与指针 18
3. #指针作为函数参数(将输入的两个数进行交换) 19
结构体 20
1. 结构体变量定义和使用 20
2. #结构体数组(比较三个学生成绩最高的输出) 20
3.#结构体指针(输出三个学生的信息) 21
C语言和程序设计
1.计算机语言的发展阶段
起初的计算机使用的是0,1组成的一串指令(机器语言阶段)人类为了方便起见设计一种以英文或符号代替机器语言的二进制代码(汇编语言阶段)由于汇编语言的助记符多且难记并且汇编语言依赖于硬件系统给软件开发者带来麻烦,于是人类设计了语法和格式类似于英文的语言并且此语言远离硬件可直接操作(高级语言阶段)
2.学习C语言的目的及C语言的应用
C语言是一种面向过程的语言,同时具有汇编语言和高级语言的优点。学习C语言能够了解底层开发,清楚系统与程序之间的“恩恩怨怨”,是初学者的首选。
C语言应用:
1.单片机领域(C语言是单片机开发的主流语言);
2.Linux(这个操作系统由C语言开发)平台上;
3.嵌入式系统(汽车,家电,工业机器);
4.游戏开发(五子棋,Quake);
…….
3.C语言的程序结构
1.源程序文件(一个程序往往由一个或多个源文件组成(看其复杂程度))
预处理命令:比如#include<stdio.h>就是将stdio.h中的头文件中内容读取进来),#表示预处理的命令。还有比如#define
全局声明;在此声明的常量或变量在所有的函数中都可以利用。
函数定义;比如要利用main和max函数要对其进行定义(如int main())。
2.函数
函数是C程序的主要组成部分,同样在一个源文件中可能包含着若干个函数(方便调试和管理),使得容易呈现程序的模块化。
一个函数包括两个部分;①函数首部(int main())int函数类型main函数名,并且一个函数名后面必须跟个小括号可以是参数也可以是void括号。②函数体,它包括声明部分(生命本函数中用到的变量和调用的韩式)和执行部分(由若干个语句构成)。
main函数是可执行函数的入口函数,程序总是从main函数开始执行,然后进入main函数中,执行main()中的内容。程序最后写return 0表示程序结束。
3.C语句
程序要求计算机的操作总是C语句中完成的。
在每个数据声明和语句的后面都要加上分号。
C语句中本身不包括输入输出函数(其由stdio.h文件中获取)。输入函数有:getchar(A=getchar()//getchar中用于输入字符),gets(gets(“hello”)//gets中存字符数串串),scanf(scanf(“%d”,&a)//切记输入的数据名称前有地址符号&,但scanf可输入所有类型的数据)
输出函数有:putchar(putchar(A)//putchar=getchar),puts(puts(A)//puts=gets),printf(//printf=scanf,但是printf中不需要地址符)。
4.注释
一个好的、有使用价值的源程序都应该加上必要的注释,以增强程序的可读性(在代码后边加上//来写注释,编译器对此部分不会进行识别)。
算法基础
1.算法基本概念和特性
算法与程序设计及数据结构密切相关,是解决一个问题的完整步骤的描述,是解决一个问题的策略、规则和方法。(程序=数据结构+算法)
特性有:有穷性(必须在有穷时间内完成不能无限执行)、确定性(每个过程不能有二义性)、可行性(每一步都应该有意义)。
2.算法的表示方法
C语言基础
1.标识符(用来表示常量名,变量名,函数名及数组名等)
所有标识符都必须以字母或下划线开头(int numberint _number正确示范),不能以符号或数字开头(int !number/int 9number错误示范 ),除开头外其他位置可由字母、下划线或数组组成。
2.常量类型
数值型常量(整型常量、实型常量)
字符型常量(字符常量’a’、字符串常量”lakers”//两者的定界符不同且长度也不同)
符号常量(用一个符号代替一个固定的值)
//还有转义字符奥(n表示换行,t表示横向跳转一个位置,r表示回车)
3.变量类型及用法
运算符与表达式
1.强制类型转换
举例理解
①Int i;
float q=3.6;
要想把q的值以整型赋给i,则需要
i=(int)q;
那么i所得的值是3(系统自动把小数点后数字删掉)
②int sum;
float x=3.5,y=9.2;
sum=(int)(x+y);//注意将表达式的整体括起来
2.自增自减运算
举例说明(a++和++a的区别)
int a=0;
int b;
b=a++;
printf(“%d”,a);//输出是0
printf(“%d”,b);//输出是1
int a=0;
int b;
b=++a;
printf(“%d”,a);//输出是1
printf(“%d”,b);//输出是1
sum up:a++返回值是0,++a返回值是1。
3.逗号运算符与逗号表达式
1式,2式,3式…n式—>最后的结果是n式的值(逗号表达式求解式从1式开始求到n式)
注意y=1+3,2+3,3+3这个结果式4不是6,因为等于号优先于逗号,所以正确表示为y=(1+3,2+3,3+3)这样所得结果才是6
4.复合赋值运算符
举例说明
a+=3等价于a=a+3
a%=3等价于a=a%3
a*=x+3等价于a=a*(x+3)
5.C语言中复合运算优先级
%,*,/ +,- ==,!= &&>|| +=,*=
//优先级相同(在式子中按照左右顺序从高到低)
6.简述for(循环语句)以及break,continue(转移语句)语句区别
当执行到for语句时,程序首先计算第一个表达式的值,接着计算第二个表达式的值。当第二个表达式为真时,程序接着计算第三个表达式的值,并以此类推直到第二个表达式的值为假,退出循环。//for(表达式1;表达式2;表达式3){}(注意for循环语句默认只循环下一行的语句,要是有很多语句需要循环要整体‘{}’,这不仅仅是for语句)
Continue语句只跳出本次循环接着进行下一次循环,而break直接结束所有循环即程序结束运行。
选择程序结构设计
1.#if语句(注意if后用else if和if区别,后者是为并列)
①比较三个数字的大小(比数大小题最常见)
#include<stdio.h>
int main()
{
int a,b,c,temp;
printf("请输入你想输入的三个数的值(用douhao隔开):n");
scanf("%d,%d,%d",&a,&b,&c);
if(a<b)
{
if(b>c)
{
temp=b;
b=a;
a=temp;
}
else
{
temp=c;
c=a;
a=temp;
}
}
printf("这三个数的大小排序为%d>%d>%dn",a,b,c);
}
②分段函数输x求y值(课本例题练习题均有此题目)
#include<stdio.h>
int main()
{
int x,y;
printf("请输入你想输入的x值:n");
scanf("%d",&x);
if(x<1)
y=x;
if(x>=10)
y=3*x-11;
else
y=2*x-1;
printf("此函数中y的值为%d",y);
}
2.#Switch语句
形式:(switch意思为分支,case意思为当,default意思为默认)
Switch(表达式)
{
Case 常量:
语句;break
Case 常量:
语句;break
. .
. .
. .
Default 常量:
语句;
}
注意:
- 最后一个case/default的句子时可以没有break,其他子句最后得以其结尾(default位置随意,不必一定在最后)。
- 多个case标号可以共用一组执行语句(如下面的题)。
- Case后面跟的必须是常量,且case常量后面跟的是冒号。
题目:要求利用switch设计一个学生输分查评语的程序。
#include<stdio.h>
int main()
{
int a,b,c,d;
printf(" 欢迎访问学校教务系统:n");
printf("请输入你的成绩:n");
scanf("%d",&a);
b=a/10;
switch (b)
{
case 10:
printf("you are the best student!n");break;
case 9:
case 8:
printf("you have a smart brain,but you must to make a higher pointn ");break;
case 7:
case 6:
printf("contulations!you pass the exam!n");break;
case 5:
case 4:
printf("i want to see you next term!n");break;
default:
printf("you are really stupid!");
}
}
循环结构程序设计
1.#While语句(while(){ }=do{ }while())(所有用while的用for都能实现)
求最大公因数和最小公倍数
#include<stdio.h>
int main()
{
int i,a,b,c,max;
i=1;
printf("请输入你想输入的两个数字(a<b):n");
scanf("%d,%d",&a,&b);
while(i<b)
{
if(a%i==0&&b%i==0)
{
c=i;
}
i++;
}
printf("这两个数的最大公约数是%d",c);
i=1;
while(i<a*b)
{
if(i%a==0&&i%b==0)
{
max=i;
}
i++;
}
printf("两个数的最小公倍数是:%d",max);
}
2.#for语句
累加、累乘(求阶层)
#include<stdio.h>
int main()
{
int i;
float j,n,k,sum;
n=1.0,j=2.0;
sum=0;
for(i=1;i<99;i++)
{
k=n/j;
sum=sum+k;
n++;
j++;
}
printf("从1/2+2/3.....+99/100=%fn",sum);
}
#include<stdio.h>
int main()
{
int i,mul,sum;
sum=0,mul=1;
for(i=1;i<=20;i++)
{
mul=i*mul;
sum=sum+mul;
}
printf("1!+2!+...+20!=%d",sum);
}
3.#双重循环(设计一个九九乘法表)
#include<stdio.h>
int main()
{
int i,j,k;
printf(" 九九乘法表n");
for(i=1;i<=9;i++)
{
for(j=1;j<=i;j++)
{
printf("%d*%d=%dt",i,j,i*j);
}
printf("n");
}
}
4.#多重循环(排出a,b,c于x,y,z的对阵表//教材中的拔高题)
#include<stdio.h>
int main()
{
int i,j,k;
for(i='x';i<='z';i++)//排列第一个队员的对手
{
for(j='x';j<='z';j++)//排列第二个队员的对手
{
for(k='x';k<='z';k++)//排列第三个队员的对手
{
if(i!='x'&&k!='x'&&k!='z'&&i!=j&&i!=k&&j!=k)
printf("甲队A--->乙队%cn甲队B--->乙队%cn甲队C--->乙队%cn",i,j,k);
}
}
}
}
数组
1.不同数组类型的定义
①一维数组的定义(类型说明符//int,float,char 数组标识符//名称[常量表达式]//存放的量)
初始化三种方式:
int A[3]={1,2,3}、int A[]={1,2,3}、int A[3]={1}//表明后面两个存储的数字为0
②二维数组定义(类型说明符//int,float,char 数组标识符//名称[常量表达式1][常量表达式2]//前者被称为行下标,后者被称为列下标)
初始化四种方式:
int a[2][2]={1,2,3,4}、int a[2][2]={{2,1},{3,4}}、int a[][2]={1,2,3,4}//前可不赋值、int a[2][2];a[0][0]=1……;
③字符数组定义(char 数组标识符//名称[常量表达式])
Char a[]={‘c’,’h’,’i’,’n’,’a’};、char a[]=”china”;系统会给字符串后自动加上”0”。(在定义字符串的长度时应+1为‘0’的长度)
2.字符串函数
Strlen函数—测字符串长度( char str[]="china";printf("%d",strlen(str));)
Strlwr函数—将大写转换为小写(char str[]="CHINA";printf("%s",strlwr(str));)
Strupr函数—将小写转换为大写(char str[]="china";printf("%s",strupr(str));)
Strcmp函数—字符串的比较(字符串比较用if(strcmp(str1,str2)>0)不用if(str1>str2))
Strcat函数—字符串的链接(char str1[]="china",str2[]="japanese";printf("%s",strcat(str1,str2));)
Strcpy函数—字符串的复制( char str1[10],str2[6]="china";strcpy(str1,str2);printf("%s",str1);)
3.#逆序输出
#include<stdio.h>
int main()
{
int a;
int A[10];
for(a=0;a<10;a++)
A[a]=a;
for(a=9;a>=0;a--)
printf("%dn",A[a]);
}
4.#求最大值及下标
#include<stdio.h>
int main()
{
int max,i,j,heng,zong;
int A[3][3];
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
scanf("%d",&A[i][j]);
}
}
max=A[0][0];
heng=0,zong=0;
for(i=0;i<3;i++)
{
for(j=0;j<3;j++)
{
if(A[i][j]>max)
{
max=A[i][j];
heng=i;
zong=j;
}
}
}
printf("这些数组中最大值是%d,横下标为%d,纵下标为%dn",max,heng,zong);
}
5.#Fibonacci序列
#include<stdio.h>
int main()
{
int i;
int a[20]={1,1};
for(i=2;i<20;i++)
{
a[i]=a[i-1]+a[i-2];
}
for(i=0;i<20;i++)
printf("%dt",a[i]);
}
6.#杨辉三角序列
#include<stdio.h>
int main()
{
int a,b;
int c[20][20]={1};
for(a=0;a<20;a++)
c[a][0]=1;
for(a=1;a<20;a++)
{
for(b=1;b<a;b++)
{
c[a][b]=c[a-1][b-1]+c[a-1][b];
}
}
for(a=0;a<20;a++)
{
for(b=0;b<a;b++)
{
printf("%dt",c[a][b]);
}
printf("n");
}
}
7.#排序输出(冒泡法和选择法)//拔高题
#include<stdio.h>
int main()
{
int i,j,temp;
int A[10]={21,43,2,45,67,879,60,34,234,456};
for(i=0;i<9;i++)
{
for(j=0;j<9-i;j++)
{
if(A[j]>A[j+1])
{
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
for(j=0;j<10;j++)
{
printf("%dt",A[j]);
}
}//牢记冒泡的for公式(for(i=0;i<n-1;i++)for(j=0;j<n-1-i;j++)用A[j]和A[j+1]比较)
#include<stdio.h>
int main()
{
int i,j,temp;
int A[10]={21,43,2,45,67,879,60,34,234,456};
for(i=0;i<9;i++)
{
for(j=i+1;j<10;j++)
{
if(A[j]>A[j+1])
{
temp=A[j];
A[j]=A[j+1];
A[j+1]=temp;
}
}
}
for(j=0;j<10;j++)
{
printf("%dt",A[j]);
}
}//牢记选择法的for公式(for(i=0;i<n-1;i++)for(j=i+1;j<n;j++)同要用A[j]和A[j+1]比较)
用函数实现模块化设计
函数的说明(注意点)
- C函数的执行是从main函数开始的,同样也是在main函数中结束运行
- 函数之间可以互相调用,但main函数不能调用,main函数是系统调用的
- 函数有两种(从用户角度看)库函数和自己定义的函数
- 从函数的形式来看函数分为有参函数和无参函数
定义函数的方法
定义无参函数(函数类型 函数名(){函数体})
定义有参函数(函数类型 函数名(参数列表){函数体})
定义空函数(函数类型 函数名(){})
函数调用的一般形式
函数调用语句(一般调用为空函数)
函数调用表达式(c=max(a,b))
函数调用参数(c=max(a,max(b,c)))
4.#函数的嵌套调用(比较四个数字的最大值)
#include<stdio.h>
int main()
{
int max(int a,int b,int c,int d);
int a,b,c,d,big;
printf("请输入你想输入的四个数字(中间用逗号间隔)n");
scanf("%d,%d,%d,%d",&a,&b,&c,&d);
big=max(a,b,c,d);
printf("这四个数字最大的是:%dn",big);
return 0;
}
int max(int a,int b,int c,int d)
{
int f;
int compare(int x,int y);
f=compare(a,b);
f=compare(f,c);
f=compare(f,d);
return f;
}
int compare(int x,int y)
{
int z;
if(x>y)
z=x;
else
z=y;
return z;
}//注意子函数在哪个函数声明被哪个函数调用
5.#函数的递归调用(此类题不好想可以记住死套路编写)
//求数字n的阶层
#include<stdio.h>
int main()
{
int fac(int n);
int c,f;
printf("请输入你像输入的数字:n");
scanf("%d",&c);
f=fac(c);
printf("你输入的数字的阶层是:%dn",f);
}
int fac(int n)
{
int h;
if(n<0)
printf("the data is error!n");
else if(n==0||n==1)
h=1;
else
h=fac(n-1)*n;
return h;
}//注意你在子函数设定的参数为n(在主函数传过来的是c),那么你在子函数中编码也应该用n而不用c(相当于在子函数中用n代替了c)
6.#数组函数的代码编程题
一维数组作形参(比较得出数组中的最大值)
#include<stdio.h>
int main()
{
int A[10];
int compare(int A[],int n);
int i,q;
printf("请输入你想输的10个数字:n");
for(i=0;i<10;i++)
scanf("%d",&A[i]);
q=compare(A,10);
printf("这个数组中的最大值是%dn",q);
}
int compare(int A[],int n)
{
int c,i;
c=A[0];
for(i=1;i<10;i++)
{
if(c<A[i])
{
c=A[i];
}
}
return c;
}//首先(int max(int A[10])==int max(int A[],int n))但要注意函数输入max(A)而不是max(A[10]),后者为(max(A,10)),这定位哪种形式据题而定
二维数组作形参(比较得出数组中的最大值)
#include<stdio.h>
int main()
{
int A[3][4]={{1,2,3,4},{5,6,7,8},{12,13,14,15}};
int compare(int A[3][4]);
int i,q;
q=compare(A);
printf("这个数组中的最大值是%dn",q);
}
int compare(int A[3][4])
{
int c,i,j;
c=A[0][0];
for(i=1;i<3;i++)
{
for(j=0;j<4;j++)
{
if(c<A[i][j])
{
c=A[i][j];
}
}
}
return c;
}
7.全局和局部声明
全局变量的作用是增加函数间的数据联系渠道;局部变量的作用范围仅限函数内部的所有语句块,局部变量能够在子函数中屏蔽全局变量。
指针
指针相关用法
Int a=10;
Int *p;
P=&a;(表示把a的地址给p即这个地址对应的10给p)
当A[10]={1,2,3,4};p=A;
注意:指针变量只能接受地址,不能接收数值(int *p=10;是错误的语法)!
//此章最为难点并不要求掌握多深,但也要有一定深度的理解
#数组与指针
一维数组与指针( 将数组逆序排列)
#include<stdio.h>
int main()
{
int inuvers(int *p,int n);
int A[7]={1,2,3,4,5,6,7};
int *p;
p=A;
inuvers(p,7);
}
int inuvers(int *p,int n)
{
int i;
int a[10];
for(i=n-1;i>=0;i--)
{
a[i]=*(p+i);
printf("%dt",a[i]);
}
}
字符串与指针(将a[20]中的字符串赋给b[20])
#include<stdio.h>
int main()
{
int i;
char a[20]="i am a lakes fan";
char b[20];
int *p1,*p2;
p1=a,p2=b;
for(i=0;*p1!='0';i++,*p1++,*p2++)
*p2=*p1;
*p2='0';
printf("%s",b);
}
#指针作为函数参数(将输入的两个数进行交换)
#include<stdio.h>
int main()
{
int swap(int *p1,int *p2);
int a,b;
int *p1,*p2;
printf("请输入你想输入的数字:n");
scanf("%d,%d",&a,&b);
p1=&a;
p2=&b;
swap(p1,p2);
}
int swap(int *p1,int *p2)
{
int temp;
temp=*p1;
*p1=*p2;
*p2=temp;
printf("交换后的数字为:%d,%d",*p1,*p2);
}//此例题中的指针交换套路是常见套路
结构体
结构体变量定义和使用
- Struct 结构体名//struct person
{
成员表列//char name[10];int age;int number;
}变量名表列;//student[2]={{“zy”,19,000003},{“gt”,18,0000002}}
- struct 结构体名//struct peson
{成员列表};// student[2]={{“zy”,19,000003},{“gt”,18,0000002}}
类型名 成员名// person student[2]={{“zy”,19,000003},{“gt”,18,0000002}}
#结构体数组(比较三个学生成绩最高的输出)
#include<stdio.h>
struct student
{
char name[10];
int number;()
int score;
};
int main()
{
struct student stu[3]={{"zy",0003,100},{"yh",0004,80},{"hw",0002,50}};
int i,max;
max=stu[0].score;
for(i=0;i<3;i++)
{
if(stu[i].score>max)
max=stu[i].score;
}
printf("他们三个的最大成绩是:%d",max);
}//注意struct结构体放到main哈结束之前,否则main函数中找不到你在struct中的声明量
3.#结构体指针(输出三个学生的信息)
#include<stdio.h>
struct student
{
char name[10];
int number;
int score;
}stu[3]={{"zy",0003,100},{"yh",0004,80},{"hw",0002,50}};
int main()
{
int i;
struct student *p;//注意是声明指向struct结构体的指针
p=stu;
printf("姓名 学号 成绩n");
for(i=0;i<3;i++)
printf("%s %d %dn",(*p).name,(*p).number,(*p).score);//注意指针加括号
}
2019.12.27