C语言简单总结

                       #**第 1 章  程序设计和C语言**

1,先写一个最简单的C语言程序

#include"stdio.h"
int main()
{
	printf("This is a C program.\n");
	return 0;
}

c语言程序的结构
(1)程序由一个或多个源程序文件组成(此处还要增加内容)
程序设计和c语言课后习题详解链接待补充

                       #**第 2 章   算法----程序的灵魂**

2.1 程序 = 算法 + 数据结构
2.4 算法的特性
(1)有穷性。
(2)确定性
(3)有零个或多个输入
(4)有一个或多个输出
(5)有效性
算法----程序的灵魂课后习题详解链接待补充

                       #**第 3 章   最简单的C程序设计——顺序程序设计**

3.1顺序程序设计举例(举一个例子吧)

/*
  题目:计算存款利息。有1000元,想存一年。有3 种方法可选
  (1)活期,年利率为r1
  (2)一年期定期,年利率为r2
  (3)存二次半年定期,年利率为r3.
  请分别计算出一年后按3 种方法所得到的本息和。
*/
#include"stdio.h"
int main()
{
	float p0 = 1000,r1 = 0.0036,r2=0.0225,r3=0.0198,p1,p2,p3;
	p1 = p0*(1+r1);
	p2 = p0*(1+r2);
	p3 = p0*(1+r3/2)*(1+r3/2);
	printf("p1=%f\np2=%f\np3=%f\n",p1,p2,p3);
	return 0;
}

3.2数据的表现形式及其运算
3.2.1
1.常量
(1).整型常量。如1000,12345,0等都是整型常量
(2).实型常量。有二种表现形式
<1>十进制小数形式,有数字和小数点组成。如123.456,0.345-56.79等
<2>指数形式,如12.34e3(12.341010*10),大写和小写E,e都行,不过,e,E 之前必须有数字,且e和E之后必须为整数。
(3).字符常量。有二种形式的字符常量:
<1>普通字符,单撇号里只能是一个字符,字符常量只能是一个字符。字符常量存储在计算机中,并不是存储字符本身,而是以其代码(一般采用ASCII代码)存储的。例如:a是97
<2>转义字符,意思是将“ \ ”后面的字符转换成另外的意义。例如:‘ \ 101 ’ 代表八进制数101的ASCII字符,即’ A ‘(八进制的101相当于十进制的65)。’ \x41 '代表十六进制41的ASCII的字符,即‘ A ’(十六进制的41相当于十进制的65)。
(4).字符串常量。如“boy”,"123"等,用双撇号把若干字符括起来。
(5).符号常量。用#define指令,指定用一个符号名称代表一个常量。(例如#define PI 3.1416 原理是:预处理器先对PI进行处理,把所有的PI全部置换为3.1416)
2.变量
变量必须先定义,后使用
3.常变量
定义变量时,前面加一个关键字const.如 const int a = 3;定义a为一个整形变量,指定其值为3,而且在变量的存在期间其值不能改变。
常变量与常量的异同:常变量具有变量的基本属性:有类型,占存储单元,只是不允许改变其值。可以说,常变量是有名字的不变量,而常量是没有名字的不变量。有名字就便于在程序中引用。
符号常量与常变量的异同:符号常量的名字是不分配存储单元的,就是在编译时进行字符替换。而常变量要占用存储单元,有变量值,只是改值不改变而已。
标识符
在计算机高级语言中,用来对变量,符号常量名,函数,数组,类型等明明的有效字符序列统称为标识符,c语言规定标识符只能由字母,数字和下画线3种符号组成,且第一个字符必须为字母或下画线。
3.2.2数据类型
所谓类型,就是对数据分配存储单元的安排,包括存储单元的长度(占多少字节)以及数据的存储形式。
3.2.3整型数据
1.整型数据的分类
(1)基本整型(int型)。例如:以两个字节的int型为例:5的补码 00000000 00000101;求-5的补码过程为:5的原码00000000 00000101,按位取反11111111 11111010,再加1(-5的补码)11111111 11111011
(2)短整型(short int)
短整型2个字节。一个短整型变量的值的范围是-32768~35767
(3)长整型(long int)
长整型4个字节。一个长整型变量的值的范围是-2147483648~2147483647
(4)双长整型(long long int)
双长整型8个字节
2.整型变量的符号属性
3.2.4字符型数据
1.字符与字符代码
2.字符变量
3.2.5浮点型数据
(1)float型(单精度浮点型)
为每一个float变量分配4个字节,float型数据能得到6位有效数字
(2)double型(双精度浮点型)
为每一个double变量分配8个字节,double型数据能得到15位有效数字
(3)long double型数据(长双精度)型
3.2.6怎样确定常量类型
整型常量
不带小数点的数值是整型常量,但应注意其有效范围。
浮点型常量
凡以小数形式或指数形式出现的实数均是浮点型常量,在内存中都以指数形式存储。
3.3运算符和表达式
3.3.1C运算符
C语言提供了以下运算符:
(1)算数运算符(+ - * / % ++ --)
(2)关系运算符(> < == >= <= !=)
(3)逻辑运算符(!&& ||)
(4)位运算符(<< >> ~ | ^ &)
(5)赋值运算符(=及其扩展赋值运算符)
(6)条件运算符(?:)
(7)逗号运算符(,)
(8)指针运算符(和&)
(9)求字节数运算符(sizeof)
(10)强制类型转换运算符((类型))
(11)成员运算符(.->)
(12)下标运算符([ ])
(13)其他(如函数调用运算符())
3.3.2 基本的算术运算符
-由于键盘无 X 号,运算符 X 以 * 代替
-%运算符要求参加运算的运算对象(即操作数)为整数,结果也是整数。如8%3,结果为2。
3.3.3 自增(++),自减(–)运算符
++i,–i(使用i之前,先使i的值加(减) 1 )
i++,i–(使用i之后,使i的值加(减)1)
3.3.5 不同类型数据间的混合运算
<1>+,-,
,/ 运算的两个数中有一个数为 float 或 double 型,结果是 double 型,因为系统将所有 float 型数据都先转换为 double 型,然后进行运算。
<2>如果 int 型与 float 或 double 型数据进行运算,先把 int 型和 float 型数据转换为 double 型,然后进行运算,结果是 double 型。
<3>字符(char)型数据与整型数据进行运算,就是把字符的ASCII代码与整型数据进行运算。 如:12+‘ A ’ ,由于字符A的ASCII代码是65,相当于12+65,等于77.如果字符型数据与实型数据进行运算,则将字符的ASCII代码转换为double型数据,然后进行运算。
以上都是由编译系统自动完成的,用户不必过问。
3.3.6 强制类型转换运算符
(类型名)(表达式)
3.4.2 最基本的语句——赋值语句
为便于理解和记忆,可以这样理解a+=b:
<1>a+=b (其中a为变量,b为表达式)
<2>a+=b (将下画线的“a+”移到右侧)
<3>a=a+b (在=左侧补上变量名a)
变量赋初值时,不能写成 int a = b = c =3;应该写成int a = 3,b = 3,c = 3;
3.5 数据的输入输出
<1>在进行 scanf 输入时,输入双精度型变量的值要用格式声明**“% lf ”**
<2>指定数据宽度和小数位数,用%m.nf
<3>在进行 printf 输出时,用%f进行输出,但是注意,float 型数据的存储单元只能保证6位有效数字,double 型数据能保证15位有效数字。
<4>在使用 scanf 时,输入数值时,在两个数值之间需要插入空格(或其他分隔符),以使系统能区分两个数值。在连续输入字符时,在两个字符之间不要插入空格或其他分隔符(除非在 scanf 函数中的格式字符串中有普通字符,这时在输入数据时要在原位置插入这些字符),系统能区分两个字符
3.5.5 字符的输入输出函数
<1>用 putchar 函数输出一个字符
<2>用 getchar 函数输入一个字符

#include"stdio.h"
int main()
{
	char a,b,c,d;
	a = getchar();
	b = getchar();
	c = getchar();
	d = getchar();
	putchar(a);
	putchar(b);
	putchar(c);
	putchar(d);
	putchar("\n");
	return 0;
}

特别注意:不要在按B后马上按回车键,这样就会把回车也作为回车也作为一个字符输入
最简单的C程序设计----顺序程序设计课后习题详解链接待补充

                       # **第   4   章    选择结构程序设计**

先简单看一个 if 结构(**注意:**用到数学公式时,要加上math.h头文件)

#include"stdio.h"
#include"math.h"      //要用到根式
int main()
{
	double a,b,c,disc,x1,x2,p,q;
	printf("请输入二元方程的三个系数:");
	scanf("%lf%lf%lf",&a,&b,&c);
	disc = b*b-4*a*c;
	if(disc<0)
		printf("此方程无实根!");
	else
	{
		p =  -b/(2*a);
		q = sqrt(disc)/(2*a);
		x1 = p + q;
		x2 = p - q;
		printf("这个方程的解:x1=%7.2f\tx2=%7.2f\n",x1,x2);
	}
	return 0;
}

4.2.2 if 语句的一般形式
<1>if (表达式) 语句1
<2>if(表达式) 语句 1
else 语句2
<3>if(表达式1) 语句1
else if(表达式2) 语句2
else if(表达式3) 语句3
. .
. .
else if(表达式m) 语句m
else 语句m+1
4.4.1 逻辑运算符及其优先次序
–有三种逻辑运算符:逻辑与(&&),逻辑或(||),!(逻辑非)
–运算符的优先级:(由高到低来排列)!(非)->算术运算符->关系运算符->&&和||->赋值运算符
4.4.2 逻辑表达式
注意:
<1>a&&b&&c。只有 a 为真(非0)时,才需要判别b的值。只有当 a 和 b 都为真的情况下才需要判别c的值。如果a为假,就不必判别 b 和 c (此时整个表达式已确定为假)。如果a为真,b为假,不判别c。
<2>a || b || c。只要a为真(非0),就不必判断 b 和 c 。只有 a 为假,才判别 b 。a 和 b都为假才判别 c。
例如:(m = a > b)&& (n = c > d)
当a=1,b=2,c=3,d=4,m和n的原值为1时,由于“a > b”的 值为0,因此m=0,此时已能判定整个表达式不可能为真,不必再进行“n=c>d”的运算,因此n的值不是0而仍保持原值1.
4.5 条件运算符和条件表达式
表达式 1 ?表达式 2 :表达式 3
4.6 选择结构的嵌套
<1>if() if() 语句1;else 语句2;
else
.
.
4.7 用 swith 语句实现多分支选择结构 (swith语句是多分支选择语句)

//要求按照考试成绩的等级输出百分制分数段,A等为85分以上,
//B等为70到84分,C等为60到69分,D等为60分以下,成绩的等级有键盘输入
#include"stdio.h"
int main()
{
	char grade;
	printf("请输入你的成绩等级:");
	scanf("%c",&grade);
	switch(grade)
	{
	case'A':
		printf("成绩在85分以上!\n");
		break;
	case'B':
		printf("成绩在70到84分之间!\n");
		break;
	case'C':
		printf("成绩在60到69分之间!\n");
		break;
	case'D':
		printf("成绩在60分以下!\n");
		break;
	default:
		printf("您输入的成绩等级有误!\n");
	}
	return 0;
}

注意:
<1>上面switch一般形式中括号内的" 表达式 ",其值的类型应为整数类型(包括字符型)
<2>case 标号只起标记作用。在执行 switch 语句时,根据 表达式的值找到匹配的入口标记,并不在此进行条件检查,在执行完一个 case 标号后面的语句后,就从此标号开始执行下去,不再进行判断(前提,没有 break 语句)。

//  写一程序,判断某一年是否为闰年
#include"stdio.h"
int main()
{
	int year,leap;
	printf("请输入一个年份:");
	scanf("%d",&year);
	if(year%4==0)
	{
		if(year%100==0)
		{
			if(year%400==0)
				leap = 1;
			else
				leap = 0;
		}
		else
			leap = 1;
	}
	else
		leap = 0;
	if(leap == 1)
		printf("%d是闰年!\n",year);
	else
		printf("%d不是闰年!\n",year);
	return 0;
}

优化版

#include"stdio.h"
int main()
{
	int year;
	printf("请输入一个年份:");
	scanf("%d",&year);
	if((year%4==0&&year%100!=0) || (year%400==0))
		printf("%d是闰年!\n",year);
	else
		printf("%d不是闰年!\n",year);
	return 0;
}

求二元方程的解的完整版

#include"stdio.h"
#include"math.h"
int main()
{
	double a,b,c,disc,p,q,x1,x2;
	printf("请输入二元方程的各系数:");
	scanf("%lf%lf%lf",&a,&b,&c);
	disc = b*b-4*a*c;
	if(fabs(a) <=1e-6)        //因为1e-6基本上接近零了
		printf("此方程不是二元方程!\n");
	else
	{
		if(fabs(disc)<=1e-6)
			printf("方程的二个同根为:%f\n",-b/(2*a));
		else if( disc > 1e-6)
		{
			x1 = (-b+sqrt(disc))/(2*a);
			x2 = (-b-sqrt(disc))/(2*a);
			printf("方程的二个根分别为x1=%8.4f,x2=%8.4f\n",x1,x2);
		}
		else
		{
			p = -b/(2*a);
			q = sqrt(-disc)/(2*a);     //因为disc为负数,所以要加负号
			printf("方程的二个共轭复根分别为:\n");
			printf("%8.4f+%8.4fi\n",p,q);
			printf("%8.4f-%8.4fi\n",p,q);
		}
	}
	return 0;
}

选择结构程序设计课后习题详解链接待补充

                       #**第   5   章  循环结构程序设计**

5.2 用 while 语句实现循环
<> while (表达式) 语句

// 用while实现1到100相加
#include"stdio.h"
int main()
{
	int i=1,sum=0;
	while(i<=100)
	{
		sum = sum + i;
		i++;
	}
	printf("1到100的和为:%d\n",sum);
	return 0;
}

5.3 用 do…while 语句实现循环
<>do 语句
while(表达式);

//用do...while实现1到100相加
#include"stdio.h"
int main()
{
	int i=1,sum = 0;
	do
	{
		sum = sum +i;
		i++;
	}while(i<=100);
	printf("1到100的和为:%d\n",sum);
	return 0;
}

while 和 do…while之间的比较:
当 while 后面的表达式 的第1次的值为“ 真 ”时,两种情况得到的结果相同;否则,二者的结果不相同(指二者具有相同的循环体的情况)。
5.3 用for语句实现循环

//用for循环实现1到100的相加
#include"stdio.h"
int main()
{
	for(int i=1,sum=0;i<=100;i++)
		sum = sum + i;
	printf("1到100的和为:%d\n",sum);
	return 0;
}

逗号表达式内按自左至右顺序求解,整个逗号表达式的值为最右边的表达式的值。
注意: 从终端键盘向计算机输入时,是按 Enter 键以后才将一批数据一起送到内存缓冲区中去的。因此不是从终端输入一个字符马上输出一个字符,而是在按 Enter 键后数据才送入内存缓冲区,然后每次从缓冲区读一个字符,在输出该字符。
5.7.1 用 break 语句提前终止循环

//1000人进行捐款,到100000就终止,统计人数和每人捐款的数目
#include"stdio.h"
#define SUM 100000
int main()
{
	int amount,aver,sum=0;
	for(int i=1;i<1000;i++)
	{
		printf("第%d个人的捐款金额为:",i);
		scanf("%d",&amount);
		sum =  sum +amount;
		if(sum > SUM)
			break;
	}
	aver = sum/i;
	printf("捐款的人数为%d,平均每人捐了%d\n",i,aver);
	return 0;
}

注意: break 语句只能用于循环语句和switch语句之中,而不能单独使用。
5.7.2 用 continue 语句提前结束本次循环

//输出100到200之间的不能被3整除的数
#include"stdio.h"
int main()
{
	for(int i=100;i<=200;i++)
	{
		if(i%3==0)
			continue;
		printf("%d ",i);
	}
	printf("\n");
	return 0;
}

5.7.3 break 语句和 continue 的区别
continue语句值结束本次循环,而不是终止整个循环的执行。而break 语句则是结束整个循环过程,不再判断执行循环的条件是否成立
5.8 循环程序举例

//  求π得的近似值
#include"stdio.h"
#include"math.h"
int main()
{
	double PI =0.0,term=1.0,n = 1.0;
	int sign = 1;
	while(fabs(term)>=1e-6)
	{
		PI = PI + term;
		n = n+2;
		sign = -sign;
		term = sign/n;
	}
	PI = 4*PI;
	printf("π的近似值为:%10.8f\n",PI);
	return 0;
}
//Fibonacci(斐波那契)数列
#include"stdio.h"
int main()
{
	int f1 = 1,f2 = 1,f3;
	printf("%12d\n%12d\n",f1,f2);
	for(int i=1;i<20;i++)
	{
		f3 = f1 + f2;
		printf("%12d\n",f3);
		f1 = f2;
		f2 = f3;
	}
	return 0;
}
``//Fibonacci(斐波那契)数列(改进版)
#include"stdio.h"
int main()
{
	int f1 = 1,f2 = 1;
	for(int i=1;i<20;i++)
	{
		printf("%d\t%d\t",f1,f2);
		if(i%2==0)
			printf("\n");
		f1 = f1+f2;
		f2 = f2+f1;
	}
	printf("\n");
	return 0;
}                  
//判断是否为素数
#include"stdio.h"
int main()
{
	int n;
	printf("请输入一个数:");
	scanf("%d",&n);
	for(int i=0;i<n;i++)
	{
		if(i%n==0)
			break;
	}
	if(i<n)
		printf("%d不是素数\n",n);
	else
		printf("%d是素数\n",n);
	return 0;
}
```//判断是否为素数(改进版)
#include"stdio.h"
#include"math.h"
int main()
{
	int n,k;
	printf("请输入一个数:");
	scanf("%d",&n);
	k = sqrt(n);
	for(int i=1;i<k;i++)
	{
		if(n%i==0)
			break;
	}
	if(i<k)
		printf("%d不是素数!\n",n);
	else
		printf("%d是素数!\n");
	return 0;
}

```c
//输出100到200之间的素数
#include"stdio.h"
#include"math.h"
int main()
{
	int k,m=0;
	for(int i=101;i<=200;i=i+2)        //偶数可以不用看
	{
		k = sqrt(i);
		for(int j=2;j<=k;j++)
		{
			if(i%j==0)
				break;
		}
		if(j>=k+1)
		{
			printf("%d ",i);
			m = m+1;
		}
		if(m%10==0)
			printf("\n");

	}
	printf("\n");
	return 0;
}

循环结构程序设计课后习题详解链接待补充

                       **#第  6  章  利用数组处理批量数据**

6.1.1 怎样定义一维数组
类型符 数组名[ 常量表达式 ];
6.1.2 怎样引用一维数组元素
数组名[ 下标 ]
6.1.3 一维数组的初始化
<1> int a[10] = {0,1,2,3,4,5,6,7,8,9} (初始化列表的方法)
<2> int a[10] = {0,1,2,3,4} (后面5个值自动赋值为0)
<3> int a[ ] = {0,1,2,3,4} (自动计算数组长度为5)
**注意:**如果在定义数值型数组时,指定了数组的长度并对之初始化,凡为被“ 初始化列表 ”指定初始化的数组元素,系统会自动把它们初始化为0(如果是字符型数组,则初始化为’ \0 ',如果是指针型数组,则初始化为NULL,即空指针 )
6.1.4 一维数组程序举例

//用数组来处理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++)
	{
		if(i%5==0)
			printf("\n");
		printf("%12d ",a[i]);    //这里用%12d就是为了输出美观
	}
	printf("\n");
	return 0;
}
//用数组实现10个数大小排序,用冒泡法
#include"stdio.h"
int main()
{
	int a[10];
	int i,j,k;
	printf("请输入10个数:");
	for(i=0;i<10;i++)
		scanf("%d",&a[i]);    //此处一定要用&(取地址符)
	for(i=0;i<9;i++)
		for(j=0;j<9-i;j++)
			if(a[j]>a[j+1])
			{
				k = a[j];
				a[j] = a[j+1];
				a[j+1] = k;
			}
	printf("这10个数从小到大排序为:");
	for(i=0;i<10;i++)
		printf("%d ",a[i]);
	printf("\n");
	return 0;
}

6.2.1 怎样定义二维数组
<1>二维数组的定义:类型说明符 数组名 [ 常量表达式 ] [ 常量表达式 ]
<2>C语言中,二维数组中元素排列的顺序是按行存放的
6.2.2 怎样引用二维数组的元素
数组名 [ 下标 ] [ 下标 ]
注意:请大家一定要注意在定义数组时用的a[ 3 ] [ 4 ] 和引用元素时的 a[ 3 ][ 4 ]的区别。前者用a[ 3 ] [ 4 ] 来定义数组的维数和各维的大小,后者a[ 3 ] [ 4 ] 中的3和4是数组元素的下标值,a[ 3 ] [ 4 ] 代表行序号为3,列序号为4的元素(行序号和列序号均从0起算
6.2.3 二维数组的初始化
<1> 分行给二维数组赋值。例如: int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}
<2> 可以将所有数据写在一个括号内,按数组元素在内存中的排列顺序对个元素赋初值。 例如:int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}
<3> 可以对部分元素赋初值。例如:int a[3][4] = {{1},{5},{9}}(它的作用只对各行第一列(即序号为0的列)的元素赋初值,其余元素值自动为0)
<4> 如果对全部元素都赋初值(即提供全部初始数据),则定义数组时对第1维的长度可以不指定,但第2维的长度不能省略。在定义时也可以只对部分元素赋初值而省略第1维的长度,但应分行赋初值
6.2.4 二维数组的举例

//有一个3X4的矩阵,用打擂台的方法求出最大的数
#include"stdio.h"
int main()
{
	int i,j,row = 0,colum = 0,max=0;
	int a[3][4] = {{1,2,3,4},{9,8,7,6},{-10,10,-5,2}};
	for(i=0;i<3;i++)
		for(j=0;j<4;j++)
		{
			if(a[i][j]>max)
			{
				max=a[i][j];
				row = i;
				colum = j;
			}
		}
	printf("这个最大数为%d,所在行是%d,所在列是%d\n",max,row,colum);
	return 0;
}

6.3 字符数组
注意:C语言中没有字符串类型,也没有字符串变量,字符串是存放在字符型数组中的。
6.3.1 怎样定义字符数组
char c[4]; c[0]=‘I’;c[1]=’ ‘;c[2]=‘a’;c[3]=‘m’;
6.3.2 字符数组的初始化
<1> char c[10] = {‘I’,’ ‘,‘a’,‘m’,’ ‘,‘h’,‘a’,‘p’,‘p’,‘y’} (用初始化列表进行初始化)
<2> 如果提供的初值个数与预定的数组长度相同,在定义时可以省略数组长度,系统会自动根据初值个数确定数组长度。char c[ ] = {‘I’,’ ‘,‘a’,‘m’,’ ',‘h’,‘a’,‘p’,‘p’,‘y’}
6.3.3 怎样引用字符数组中的元素

//输出一个已知的字符串
#include"stdio.h"
int main()
{
	char a[11] = {'j','u','s','t',' ','d','o',' ','i','t','!'};
	int i;
	for(i=0;i<11;i++)
		printf("%c",a[i]);
	printf("\n");
	return 0;
}

注意:在上面这个例子中,字符串中的字符是逐个存放到数组元素中的。在该例中,字符串的实际长度与数组长度相等。
6.3.4 字符串和字符串结束标志
<1>C系统在用字符数组存储字符串常量时会自动加一个’ \0 ‘作为结束符。
<2>在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度。如果在一个字符数组中先后存放多个不同长度的字符串,则应使数组长度大于最长的字符串长度。
<3>有了以上的了解后,对字符串的初始化补充一种新方法。例如:char c[] = {“just do it !”} 或 char c[] = “just do it !”(注意:此时字符串长度是13,不是12)
注意:字符数组并不要求它的最后一个字符为’ \0 ‘,甚至可以不包含’ \0 ‘。是否加’\0’完全根据需要决定。例如:char c[4] = {‘N’,‘i’,‘K’,‘E’};
6.3.5 字符数组的输入输出
<1>逐个字符输入输出。用格式符“ %c ”输入或输出一个字符。
<2>将整个字符串一次输入或输出。用“ %s ”格式符,意思是对字符串的输入输出。
注意
<3>用“ %s ”格式符输出字符串时,printf函数输出项是字符数组名
<4>可以用scanf函数输入一个字符串。例如:scanf("%s",c); scanf函数中的输入项c是已定义的字符数组名。
<5>如果利用一个scanf函数输入多个字符串,则应在输入时以空格分隔。例如:char str1[5],str2[5],str3[5]; scanf("%s%s%s",str1,str2,str3);
<6>空格字符作为输入字符串之间的分隔符。
<7>用数组名输出字符串的原理是,按数组名找到其数组第一个元素的地址,然后逐个输出其中的字符,直到遇到’ \0 '为止。
6.3.6 使用字符串处理函数
1, puts函数——输出字符串的函数(输出时可以包括转义字符)
一般形式为:puts(字符数组)
2,gets函数——输入字符串的函数
一般形式为:gets(字符数组)
注意:使用puts和gets函数只能输出或输入一个字符串
3,strcat函数——字符串连接函数
一般形式为:strcat(字符数组 1,字符数组 2)
作用是把两个字符数组中的字符串连接起来,把字符串2接到字符串1的后面,结果放到字符数组1中,函数调用后得到一个函数值——字符数组1的地址
4,strcpy和strncpy函数——字符串复制函数
一般形式为:strcpy(字符数组 1,字符串 2)或(字符数组1,字符数组2)
作用是将字符串2复制到字符数组1中去。
可以用strcnpy函数将字符串2中前面n个字符复制到字符数组1中去。
strncpy(str1,str2,2)(作用是将str2中最前面的2个字符复制到str1中,取代str1中原有的最前面的2个字符)
5,strcmp函数——字符串比较函数
一般形式:strcmp(字符串1,字符串2)
原则是:
<1>如全部字符相同,则认为两个字符串相等;
<2>若出现不相同的字符,则以第1对不相同的字符的比较结果为准。
比较的结果由函数带回。
<1>如果字符串1与字符串2相同,则函数值为0。
<2>如果字符串1 > 字符串2,则函数值为一个正整数。
<3>如果字符串1 < 字符串2,则函数值为一个负整数。
6,strlen函数——测字符串长度的函数
一般形式为:strlen(字符数组)
函数的值为字符串的实际长度。例如:char str[10]=“China”,printf("%d",strlen(str))输出的值是5.
7,strlwr 函数——转换为小写的函数
一般形式为:strlwr(字符串)
函数的作用是将字符串中的大写字母换成小写字母。
8,strupr函数——转换为大写的函数
一般形式为:strupr(字符串)
函数的作用是将字符串中的小写字母换成大写字母。
注意:使用以上8个函数时,应当在程序文件的开头用#include<string.h>
6.3.7 字符数组举例

//输入一行字符,判断有多少个单词
#include"stdio.h"
int main()
{
	char a[50];
	int i,num=0,word=0;
	char c;
	gets(a);
	for(i=0;(c=a[i])!='\0';i++)
	{
		if(c==' ')
			word = 0;
		else if(word == 0)
		{
			word = 1;
			num++;
		}
	}
	printf("这个字符串包括%d个单词!\n",num);
	return 0;
}
//有三个字符串,找出最大的
#include"stdio.h"
#include"string.h"
int main()
{
	char str[3][20];
	char string[20];
	int i;
	for(i=0;i<3;i++)
		gets(str[i]);
	if(strcmp(str[0],str[1])>0)
		strcpy(string,str[0]);
	else
		strcpy(string,str[1]);
	if(strcmp(str[2],string)>0)
		strcpy(string,str[2]);
	printf("三个字符串最大的为:%s\n",string);
	return 0;
}

利用数组处理批量数据课后习题详解链接待补充

                       #第  7  章   用函数实现模块化程序设计

7.2.2 定义函数的方法
1,定义无参函数
类型名 函数名(void)(void加不加都行)
{函数体}
2,定义有参函数
类型名 函数名(形参表列)
{函数体} (函数体包括声明部分和语句部分)
3,定义空函数
类型名 函数名()
{}
7.3 调用函数
7.3.1 调用函数的形式
一般形式:函数名(实参表列)
7.3.2 函数调用时的数据传递
1,形式参数和实际参数。
2,实参和形参间的数据传递。
在调用函数过程中发生的实参与形参间的数据传递称为“ 虚实结合
7.3.3 函数调用过程
在定义函数中指定的形参,在未出现函数调用时,它们并不占内存中的存储单元。在发生函数调用时,函数的形参才被临时分配内存单元。应当注意返回值的类型与函数类型一致。调用结束,形参单元被释放。注意实参与形参是两个不同的存储单元。
注意:实参向形参的数据传递是“值传递”,单向传递,只能由实参传给形参。
7.3.4 函数的返回值
注意:函数的返回值是通过函数中的return 语句获得的;在定义函数时指定的函数类型一般应该和return 语句中的表达式一致;函数类型决定返回值类型。
7.4 对被调用函数的声明和函数原型
函数声明的一般形式有两种,分别为
<1>函数类型 函数名(参数类型 1,参数名 1,…,参数类型 n,参数名 n);
<2>函数类型 函数名(参数类型 1,参数类型 2,…参数类型 n);
注意:函数定义与函数声明的区别:函数的定义是指对函数功能的确定,包括指定函数名,函数值类型,形参及其类型以及函数体等,它是一个完整的,独立的函数单位。而函数的声明的作用则是把函数的名字,函数类型以及形参的类型,个数和顺序通知编译系统,以便在调用函数时系统按此进行对照检查,它不包含函数体。

//输入4个整数,找其中的最大值
#include"stdio.h"
int main()
{
	int max1(int,int,int,int);
	int a,b,c,d,k;
	printf("请输入4个数:");
	scanf("%d%d%d%d",&a,&b,&c,&d);
	k = max1(a,b,c,d);
	printf("最大数为:%d\n",k);
	return 0;
}

int max1(int a,int b,int c,int d)
{
	int max(int,int);
	int m;
	m = max(a,b);
	m = max(m,c);
	m = max(m,d);
	return m;
}
int max(int a,int b)
{
	return(a >= b ? a:b);
}

7.6 函数的递归调用
直接或间接的调用函数本身,称为函数的递归调用。

//有5个学生,大的比小的大2岁,已知最小的那个为10岁
#include"stdio.h"
int main()
{
	int age(int);
	printf("第5个学生的年龄为%d\n",age(5));
	return 0;
}

int age(int n)
{
	int c;
	if(n==1)
		c = 10;
	else
		c = age(n-1)+2;
	return c;
}
//求n的阶乘,采用递归的思想
#include"stdio.h"
int main()
{
	int fac(int);
	int n,k;
	printf("请输入一个数:");
	scanf("%d",&n);
	k = fac(n);
	printf("%d!=%d\n",n,k);
	return 0;
}
int fac(int n)
{
	int f;
	if(n<0)
		printf("您输入的数据有误!\n");
	else if(n==0 || n==1)
		f = 1;
	else
		f = fac(n-1) * n;
	return f;
}

7.7 数组作为函数参数
7.7.1 用数组元素作函数实参

//输入10个数,求最大数及其位置
#include"stdio.h"
int main()
{
	int max(int,int);
	int a[10],i,n,m;
	for(i=0;i<10;i++)
		scanf("%d",&a[i]);
	for(i=1,m=a[0];i<10;i++)
	{
		if(max(m,a[i])>m)
		{
			m = max(m,a[i]);
			n=i;
		}
	}
	printf("最大的数为:%d,是第%d个数!\n",m,n+1);
	return 0;
}
int max(int x,int y)
{
	return (x>y ? x:y);
}

7.7.2 一维数组名作函数参数
注意:用数组元素作实参时,向形参变量传递的是数组元素的值,而用数组名作函数实参时,向形参(数组名或指针变量)传递的是数组首元素的地址。

//用一个一维数组存放10个学生的成绩,求平均成绩
#include"stdio.h"
int main()
{
	float f1(float a[10]);
	float score[10],b;
	int i;
	printf("请输入10个数:");
	for(i=0;i<10;i++)
		scanf("%f",&score[i]);
	b = f1(score);
	printf("这些成绩的平均值为:%f\n",b);
	return 0;
}

float f1(float a[10])
{
	int i;
	float sum = a[0],aver;
	for(i=1;i<10;i++)
		sum = sum + a[i];
	aver = sum / 10;
	return aver;
}

注意:数组名作为函数实参时,传递的是是参数组的首元素的地址传递给形参数组

//用选择法对数组中的10个数进行排序
#include"stdio.h"
int main()
{
	void f1(int a[],int n);
	int b[10],i,n=10;
	printf("请输入10个数:");
	for(i=0;i<10;i++)
		scanf("%d",&b[i]);
	f1(b,n);
	printf("排序后的10个数为:");
	for(i=0;i<10;i++)
		printf("%d ",b[i]);
	printf("\n");
	return 0;
}
void f1(int a[],int n)
{
	int i,j,k,t;
	for(i=0;i<n-1;i++)
	{
		k=i;
		for(j=i+1;j<n;j++)
		{
			if(a[j]<a[k])
				k=j;
			t = a[k];
			a[k] = a[i];
			a[i] = t;
		}
	}
}

7.7.3 多维数组名作函数参数

//在3X4的矩阵中求最大数
#include"stdio.h"
int main()
{
	int max(int array[][4]);
	int a[3][4] = {{1,3,5,7},{2,4,6,8},{15,17,34,12}};
	printf("最大的数为:%d\n",max(a));
	return 0;
}
int max(int array[][4])
{
	int i,j,max;
	max = array[0][0];
	for(i=0;i<3;i++)
		for(j=0;j<4;j++)
			if(array[i][j]>max)
				max=array[i][j];
	return max;
}

7.8 局部变量和全局变量
7.8.1 局部变量
定义变量可能有3种情况:
<1>在函数的开头定义;
<2>在函数内的复合语句内定义;
<3>在函数的外部定义;
注意:在一个函数内部定义的变量只在本函数范围内有效。
7.8.2 全局变量
全局变量可以为文件中其他函数所用,它的有效范围从定义变量的位置开始到本源文件结束。
注意:如果全局变量与局部变量同名,在此范围内全局变量被局部变量屏蔽,相当于全局变量在此范围内不存在了。
7.9变量的存储方式和生存期(选看)
7.9.1 动态存储方式与静态存储方式
<1> 程序区
<2> 静态存储区(全局变量)
<3> 动态存储区
7.9.2 局部变量的存储类别
1,自动变量
在调用函数时,系统会给这些变量分配存储空间,在函数调用结束时就自动释放这些存储空间。这类局部变量称为自动变量。不写“auto”则隐含指定为“自动存储类别”,它属于动态存储方式。
2, 静态局部变量(static局部变量)
<1>如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符‘ \0 ’ (对字符变量)。而对自动变量来说,它的值是一个不确定的值。这是由于每次函数调用结束后存储单元已释放,下次调用时又重新另分配存储单元,而所分配单元的内容是不可知的。
<2>静态局部变量只能被本函数引用,而不能被其他函数引用。
3,寄存器变量(register 变量)
自动变量存储在动态存储区;静态局部变量存储在静态存储区;寄存器存储在CPU中的寄存器
7.9.3 全局变量的存储类别
1,在一个文件内扩展外部变量的作用域
如果需要在定义之前用外部变量,用关键字 extern 对该变量作“ 外部变量声明
2,将外部变量的作用域扩展到其他文件
在另一文件中对外部变量作 extern 声明
3,将外部变量的作用域限制在本文件中
若希望某些外部变量只限于被本文件引用,而不能被其他文件引用。这时可以在定义外部变量时加一个 static 声明。(即静态外部变量)
注意:用static声明一个变量的作用
<1> 对局部变量用 static 声明,把它分配在静态存储区,该变量在整个程序执行期间不释放,其所分配的空间始终存在。
<2> 对全局变量用 static 声明,则该变量的作用域只限于本文件模块(即被声明的文件中)。
从作用域的角度来看
凡有 static 声明的,其作用域都是局限的,或者局限于本函数内(静态局部变量),或者局限于本文件内(静态外部变量)。
7.10 关于变量的声明和定义
一般为了叙述方便:把建立存储空间的声明称定义,而把不需要建立存储空间的声明称为声明
有一个简单的结论:在函数中出现的对变量的声明(除了用 extern 声明的以外 )都是定义。在函数中对其他函数的声明不是函数的定义。
7.11 内部函数和外部函数
7.11.1 内部函数
如果一个函数只能被本文件中其他函数所调用,它称为内部函数。(或称静态函数)
static 类型名 函数名(形参表);
7.11.2 外部函数
如果在定义函数时,在函数首部的最左端加关键字 extern ,则此函数是外部函数,可供其他文件调用。(C语言规定,如果在定义函数时省略 extern ,则默认为外部函数)
extern int fun (int a,int b)
用函数实现模块化程序设计 课后习题详解链接待补充

                       #第  8  章   善于利用指针

8.1 指针是什么
内存区的每一个字节有一个编号,这就是“ 地址 ”,地址指向该变量单元,将地址形象化地称为“ 指针 ”。C语言中的地址包括位置信息(内存编号,或称纯地址)和它所指向的数据的类型信息。
注意:对变量的访问都是通过地址进行的。
直接按变量名进行别的访问,称为“ 直接访问 ”方式
将地址形象化地称为指针
注意:指针是一个地址,而指针变量是存放地址的变量
8.2 指针变量
8.2.2 怎样定义指针变量
类型名 * 指针变量名;
<1>指针变量的基类型用来指定此指针变量可以指向的变量的类型。
<2>一个变量的指针的含义包括两个方面,一是以存储单元编号表示的纯地址(如编号为2000的字节),一是它指向的存储单元的数据类型(如 int,char,float等)。
<3>指向整型数据的指针类型表示为“ int * ”,读作“ 指向int的指针 ”或简称“ int指针 ”
8.2.3 怎样引用指针变量
<1>给指针变量赋值。p = &a;(指针变量p的值是变量a的地址,p指向a)
<2>引用指针变量指向的变量。printf("%d",*p); 其作用是以整数形式输出指针变量p所指向的变量的值,即变量a的值。*p=1,即a=1;
<3>& 取地址运算符。&a是变量a的地址
<4> * 指针运算符(或称“ 间接访问 ”运算符),*p代表指针变量p指向的对象。
8.2.4 指针变量作为函数参数
由于“ 单向传送 ”的“ 值传递 ”方式,形参值的改变不能使实参的值随之改变
注意:不能企图通过改变指针形参的值而使指针实参的值改变;不可能通过执行调用函数来改变实参指针变量的值,但是可以改变实参指针变量所指变量的值。

//用指针的方法对3个整数从小到大输出
#include"stdio.h"
int main()
{
	void exchange2(int *,int *,int *);
	int a,b,c,*point1,*point2,*point3;
	printf("请输入三个数:");
	scanf("%d%d%d",&a,&b,&c);
	point1 = &a;
	point2 = &b;
	point3 = &c;
	exchange2(point1,point2,point3);
	printf("三个数从小到大输出为:%d %d %d\n",a,b,c);
	return 0;
}
void exchange2(int *pt1,int *pt2,int *pt3)
{
	void exchange1(int *,int *);
	if(*pt1 > *pt2)
		exchange1(pt1,pt2);
	if(*pt1 > *pt3)
		exchange1(pt1,pt3);
	if(*pt2 > *pt3)
		exchange1(pt2,pt3);
}
void exchange1(int *p1,int *p2)
{
	int temp;
	if(*p1 > *p2)
	{
		temp = *p1;
		*p1 = *p2;
		*p2 = temp;
	}
}

8.3 通过指针引用数组
8.3.1 数组元素的指针
所谓数组元素的指针就是数组元素的地址
注意:在C语言中,数组名(不包括形参数组名)代表数组首元素(即序号为0的元素)的地址。
8.3.2 在引用数组元素时的指针的运算
注意
<1>在指针已指向一个数组元素时,p+1指向同一数组中的下一个元素,p-1指向同一数组中的上一个元素
<2>如果p的初值是&a[0],则p+i和a+i就是数组元素a[i]的地址。
<3>(p+i)或(a+i)是p+i或a+i所指向的数组元素,即a[i]。即*(p+5),(a+5)和a[5]三者等价。
8.3.3 通过指针引用数组元素
<1>下标法,如a[ i ]形式
<2>指针法,如
(a+i) 或 (p+i),其中a是数组名,p是指向数组元素的指针变量,其初值p=a。
注意:数组名a代表数组首元素的地址,它是一个指针型常量,它的值在程序运行期间是固定不变的。既然a是常量,所以a++是无法实现的。
<3>指向数组元素的指针变量也可以带下标,如p[i];因为在程序编译时,对下标的处理方法是转换为地址的,对p[i]处理成
(p+i),如果p是指向一个整型数组元素a[0],则p[i]代表a[i].但是必须弄清楚p的当前值是什么!
8.3.4 用数组名作函数参数
实际上,C编译都是将形参数组名作为指针变量来处理的。例如:fun(int arr[ ]) 和 fun(int * arr) 是等价的。
说明:C语言调用函数时虚实结合的方法都是采用“ 值传递 ”方式,当用变量名作为函数参数时传递的是变量的值,当用数组名作为函数参数时,由于数组名代表的是数组首元素地址,因此传递的值是地址,所以要求形参为指针变量。
注意:实参数组名代表一个固定的地址,或者说是指针常量,但形参数组名并不是一个固定的地址,而是按指针变量处理的。

//将数组中n个整数按相反顺序存放
#include"stdio.h"
int main()
{
	void inv(int a[],int);
	int i,b[10] = {3,7,9,11,0,6,7,5,4,2};
	printf("交换前的10个数为:");
	for(i=0;i<10;i++)
		printf("%d ",b[i]);
	inv(b,10);
	printf("\n");
	printf("交换后的10个数为:");
	for(i=0;i<10;i++)
		printf("%d ",b[i]);
	printf("\n");
	return 0;
}
void inv(int a[],int n)
{
	int i,j,m,t;
	m = (n-1)/2;
	for(i=0;i<=m;i++)
	{
		j = n-1-i;
		t = a[i];
		a[i] = a[j];
		a[j] = t;
	}
}

总结:如果有一个实参数组,要想在函数中改变此数组中元素的值,实参与形参的对应关系有4种情况。
<1>形参和实参都用数组名。
<2>实参用数组名,形参用指针变量。
<3>实参形参都用指针变量。
<4>实参为指针变量,形参为数组名。

#include"stdio.h"
int main()
{
	void inv(int a[],int n);
	int b[10],i,* p;
	p=b;
	printf("请输入10个数:");
	for(i=0;i<10;i++)
		scanf("%d",&b[i]);
	inv(p,10);
	printf("它们从大到小排列为:");
	for(i=0;i<10;i++)
		printf("%d ",*(b+i));
	printf("\n");
	return 0;
}
void inv(int a[],int n)
{
	int i,j,k,t;
	for(i=0;i<n-1;i++)
	{
		k = i;
		for(j=i+1;j<n;j++)
			if(a[k] < a[j])
				k = j;
			if(k!=i)
			{
				t = a[k];
				a[k] = a[i];
				a[i] = t;
			}
	}
}

8.3.5 通过指针引用多维数组(带*号)
C语言对字符串常量是按字符数组处理的,在内存中开辟了一个字符数组用来存放该字符串常量,但是这个字符数组是没有名字的,因此不能通过数组名来引用,只能通过指针变量来引用。
可以通过字符指针变量输出它所指向的字符串。
通过字符数组名或字符指针变量可以输出一个字符串。

#include"stdio.h"
int main()
{
	char a[] = "I am a student.",b[20];
	int i;
	for(i=0;*(a+i)!='\0';i++)
		*(b+i) = *(a+i);
	*(b+i) = '\0';
	printf("string a is:%s\n",a);
	printf("string b is:");
	for(i=0;b[i]!='\0';i++)
		printf("%c",b[i]);
	printf("\n");
	return 0;
}

8.4.2 字符指针作函数参数
8.4.3 使用字符指针变量和字符数组的比较
<1>字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址。
<2>可以对字符指针变量赋值,但不能对数组名赋值。
<3>编译时为字符数组分配若干存储单元,以存放个元素的值,而对字符指针变量,只分配一个存储单元
<4>指针变量的值是可以改变的,而字符数组名代表一个固定的值(数组首元素的地址),不能改变。
<5>字符数组中各元素的值是可以改变的(可以对它们再赋值),但字符指针变量指向的字符串常量中的内容是不可以被取代的(不能对它们再赋值)。
<6>若字符指针变量指向字符串常量,就可以用指针变量带下标的形式引用所指的字符串中的字符。

  • 3
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值