未分类 · 2021年10月28日

计算机二级C语言复习知识点

第一章C语言概述

第二章变量及表达式

  • 教学重点,难点分析

1. C语言概述

知识点所占分值考核几率专家点评
C语言概述0-1分 20%简单识记
C语言程序的构成0-1分 30%简单识记
标识符1-2分  60%简单,属重点识记知识点
常量1-2分   80%简单,属重点识记知识点
变量2-3分100% 难度适中,重点理解重点掌握

注意:从几年的试题分析看C语言的概述和程序的构成合起来考试已经是一个惯例了。

2. 运算符与表达式

知识点所占分值考核几率 专家点评
C运算符简介0-1分 10%简单识记
运算符的结合和优先级0-1分60%简单识记
强制类型转换运算符0-1分30%简单识记
逗号运算符和逗号表达式0-1分40%简单,属重点识记知识点
基本的算术运算符1-2分100%简单,属重点识记知识点
算术表达式和运算符的1-2分100%难度适中,重点理解重点掌握
优先级与结合、自增自减运算符2-3分100%难度适中,重点理解重点掌握
赋值运算符和赋值表达式2-4分100%简单,重点掌握重点理解
复合的赋值运算符1-2分80%偏难,不是重点
赋值运算中的类型转换0-1分75%偏难,不是重点
位运算符和位运算0-1分80%偏难,属重点识记知识点
  • 教学讲点
  • C语言的基本构成和格式

#include “stdio.h”

main()

{

   int a,b,sum;/* 定义变量*/

   a=10;     /*把整数10赋值给变量a*/

   b=20;     /*把整数20赋值给变量b*/

   sum=a+b; /*把两数之和赋值给变量 sum*/

   printf(“a=%d,b=%d,sum=%d\n”,a,b,sum);/*输出计算结果*/

}

(1).C程序由函数组成,一个程序必须且只能有一个主函数(main()),C程序总是从主函数开始执行,在主函数中结束。

(2).定义函数时函数名后必须有一对小括号,函数体必须放在一对花括号内,在函数体中,函数体有两个部分:定义部分和执行部分。定义语句必须出现在执行语句之前,我们先定义了a,b,sum,然后才给它们赋值。

(3).C语言中每条语句都以分号“;”结束,分号时C语句的一部分。即使是程序的最后一个语句也不例外。分号是语句结束的标志。

(4). 一行可以写多条语句,一条语句也可以分在多行上写,但是,不能将一个整体分开。

  例如:i nt 是错误的,而int正确。

(5). C语言的注释必须放在“/*”和“*/”之间,“/”和“*”之间不允许有空格。“/*”和“*/”之间不允许再插入“/*”或“*/”。注释可以出现在程序中的任意位置。注释部分不被执行。

(6).C语言程序书写格式自由,语句可以从任一列开始书写,一行内可以写多个语句。但是过于“自由”的程序书写格式往往使人们很难读懂程序,初学者应该从一开始就养成好的习惯,是程序便于阅读。

  • 标识符
  • 标识符只能由字母、数字和下划线组成。
  • 标识符的第一个字符必须是字母或下划线。

(3) 标识符的大小写字母是有区别的,如abc和ABC是两个完全不同的标识符。 

  • 标识符的分类:

关键字:关键字是具有特定的含义的、专门用来说明C语言特定成分的一类标识符。详细的查阅附录二。

预定义标识符:在C语言中它也有特定的含义。预定义标识符可以用位“用户表标识符”使用,只是这将使这些标识符失去了原来的意义。

用户标识符:由用户根据需要定义的标识符被成为用户标识符。用户标示符用来给变量、函数、数组或者指针等命名。

  • C语言的数据类型

3.1数据可以分为常量和变量。常量是指在程序执行中不变的量,常量分为:整型常数、实型常数、字符常量、字符串常量。

整型数据:

进制间的转换

3.11.二、八、十六进制转为十进制

规则:“按权相加”

3.12.十进制转为二、八、十六进制

规则:

整数部分:基数除取余,逆序排列

小数部分:基数乘取整,顺序排列

3.13.二进制转为八、十六进制

规则:三(四)合一,按序相拼(整数部分,从右向左取,小数部分从左向右取,位数不足补零)。

3.14.八、十六进制转为二进制

规则:一分三(四),按序相拼

3.2整型数据在内存中的存放形式

1字节=8位,1Byte=8bit

字长:指CPU能同时处理的二进制位数。由CPU的型号而定。如:16位微机的字长就是16位或2字节。

1GB=1024MB,1MB=1024KB,1KB=1024B

B:表示字节,字节是表示存储容量的最小单位。位(bit):是计算机中信息表示的最小单位。

3.21.正整数在内存中用“原码”形式存放。(直接转换为二进制即可)。

如:5

0000000000000101

二字节能存放的最大数是:32767

0111111111111111

对带符号数,最高位是符号位,用0表示正,用1表示负。

3.22.负整数在内存中用“补码”形式存放。

取补码的步骤:

(1)忽略负号,求出原码。

(2)将原码按位取反(0 、1 互换)。

(3)在第二步的基础上加1。

如:取-5的补码。

(1)

0000000000000101

(2)

1111111111111010

(3)

1111111111111011

将补码转换成相应的整数的步骤:

(1)将补码按位取反加1。

(2)将步骤1得到的二进制数转换成十进制数,然后加上负号即可。

例如:

1000000000000000

按位取反加1

0111111111111111

                                             +1

1000000000000000

转换成十进制:1×21532768

加负号:-32768

几个特殊的带符号整数:

1000000000000000   -32768

0111111111111111     32767

1111111111111111     -1

3.23.无符号整数:只有正整数,没有负整数,最高位不表示符号位,每一位均参与转换。

二进制带符号整数无符号整数
1111111111111111-165535
1000000000000000-3276832768

例2-12:若有:int a=-1; unsigned b=65535;则

printf(“%d,%u,%d,%u”,a,a,b,b);  输出结果是:-1,65535,-1,65535

数据益出问题:

例2-13:若有int a=32767;则a=a+1的结果是:

-32768

例2-14:若有unsigned b=65536;则b的值是:0

分析:32767:01111111111111111

                          +1

100000000000000

将100000000000000按照带符号数转为十进制为-32768

65535:1111111111111111

+1

1111111111111111

+1

10000000000000000

65536

unsigned b=655536;而b属于无符号整型,在内存中只占两字节,所以只能包括16位。

 标准C没有具体要求规定各类型数据所占内存的字节数, 现以这次考试标准viusal c++6.0为例,说明各类型变量所占的位数。

类型所占位数所占字节数 类型所占位数所占字节数
short162unsigned int  324
int 324unsigned long 324
long324float 324
unsigned short162double 64 8

3.3实型数据(浮点数)

3.31.实型常量

(1)小数形式:由数字和小数点组成,必须有小数点,小数点的某一侧可以没有数字。如:.23 ,123.876 ,123.

(2)指数形式:用“e”或“E”后接一个整数,表示以10为底的幂数。

注意: “e”或“E”之前之后必须有数字,且之后的数字必须是整数。他们和前后的数字之间不能有空格。

例如:

例2-15:下列合法的常量是( )。

A.-32169    B.0128  C.0XDEFG  D.13E0.5

例2-16:下列合法的实型常量是(  )。

(A) 0Xff  (B)124E  (C) 1.23E5.0  (D) 3.E2  (E) 1.25E+2  (F).23e+02 

3.32.实型变量

单精度型 float 占 4 字节

双精度型 double 占 8 字节

长双精度 long double 占 16字节(较少用)

  • 表达式与运算符

4.1算术运算符及其表达式:+  -  *  /  %

%:(求余运算)

注意:

(1)%两边必须是整型数据。12.0%3 表达式是错误的。

(2)求余(%)的方法是:忽略符号,求出余数,再将所得余数的符号定为与被除数相同。

 例如:17%3 结果是:2

17%-3 结果是:2,-17%3 结果是:-2,-17%-3 结果是:-2

4.2强制类型转换

强制类型表达式:(类型名)表达式

注意:类型名(表达式)这种形式是C++的强制类型表达方式。

5.赋值运算符及其表达式

5.1.赋值运算符 =

 格式:变量名=表达式

功能:将表达式的值赋给左边的变量。

注:

(1)赋值运算符左边只能是一个变量,不能是常量,也不能是表达式。

a+b=3    4=3 是非法的表达式

a=6  a+(b=3) 都是合法的表达式

a=b=20  a=(b=10)/(c=2) 都是合法的表达式

(2)实型数据赋给整型变量时,小数部分被舍去,整型数据赋给实型变量时,系统自动将整型数据转换为实型数据。

例如:float a; int b;

表达式a=10%3 的值是1.0

表达式b=a=10%3的值是1

5.2.复合赋值运算符及其表达式:+= -=  *=  /=  %=  &=  |=  ^=  >>=  <<=

例如:a+=3 相当于a=a+3,a/=b+4 相当a/=(b+4) 或a=a/(b+4)

例:若a=12,则执行表达式a+=a-=a+a后a的值是多少?

分析:a+=a-=(a+a)  /*a的值是12*/

a+=a-=24    /*a的值是12*/

a+=a=a-24   /*a的值是12*/

a+=a=-12    /*a的值是12*/

a+=-12      /*a的值是-12*/

a=a+(-12)    /*a的值是-12*/

a=-24       /*a的值是-24*/

5.3.自增、自减运算符及其表达式

++   --

注意:

(1)只能用于变量,不能用于常量和表达式。

如:6++ (a+b)-- 都是错误的。

(2)当它们用于变量名前时,表达式的值为变量的值加一或减一。当位于变量名后时,表达式的值为变量原来的值。不论位于变量名前还是变量名后,只要进行了自增、自减运算,变量的值都会在原来的基础上加1或减1。

如:a=3 则 a++ 表达式的值是3 运算之后变量的值是 4

a=3 则 ++a 表达式的值是 4之后变量的值是 4

a=3 则 a-- 表达式的值是3 之后变量的值是 2

a=3 则 --a 表达式的值是2 之后变量的值是 2

(3)口诀:

   j=i++;这个表达式是先引用后增值。即:先把i的初始值给变量j,然后 i再自加1。

   j=++i;这歌表达式是先增值后引用。即:i先自加1,然后再将我们自加后的值赋值给变量 j。

   但是记住它们是一起执行的,就是说:例如j=i++先引用后增值实际上是一起执行的,它们之间不存在先后关系,我们只是位了好记才用到了上面的方法。老师在上课的时候先不要说,但是你们必须知道。j=i--,j=--i和上面j=i++,j=++i的方法是一样。

5.4逗号运算符及其表达式

1.格式:表达式1,表达式2,…,表达式n

注意:1.逗号表达式的值是整个逗号表达式中最后一个表达式的值。

2.求值顺序是从左到右依次求解。

例如:a=(3,b=1)的值是1 运算结束后a的值是1, b的值是 1。    

  • 相关试题

1.2008年4月相关试题

(11)以下叙述中正确的是

A)C程序中的注释只能出现在程序的开始位置和语句的后面

B)C程序书写格式严格,要求一行内只能写一个语句

C)C程序书写格式自由,一个语句可以写在多行上

D)用C语言编写的程序只能放在一个程序文件中

(12)以下选项中不合法的标识符是

A)print B)FOR C)&a D)_00

(13)以下选项中不属于字符常量的是

A) 'C'  B) "C"  C)'\xCC0'  D) '\072'

(14)设变量已正确定义并赋值,以下正确的表达式是

A)x=y*5=x+z B)int(15.8%5)

C)x=y+z+5,++y D)x=25%5.0

填空(7)设变量已正确定义为整型,则表达式n=i=2,++i,i++的值为【7】。

2.2007年9月相关试题

(11)C语言源程序名的后缀是

       A).exe               B).C                  C).obj               D).cp

(12)可在C程序中用作用户标识符的一组标识符是

       A) and               B) Date                     C) Hi                 D) case

              _2007                  y-m-d                   Dr.Tom                Big1

(13)以下选项中,合法的一组C语言数值常量是

       A) 028               B) 12.                C) .177                     D) 0x8A

              .5e-3                    0Xa23                 4e1.5                   10,000

              -0xf                      4.5e0                   0abc                            3.e5

(14)以下叙述中正确的是

       A)C语言程序将从源程序中第一个函数开始执行

       B)可以在程序中由用户指定任意一个函数作为主函数,程序将从此开始执行

       C)C语言规定必须用main作为主函数名,程序将从此开始执行,在此结束

       D)main可作为用户标识符,用以命名任意一个函数作为主函数

(16)以下关于long、int和short类型数据占用内存大小的叙述中正确的是

       A)均占4个字节                                B)根据数据的大小来决定所占内存的字节数

       C)由用户自己定义                      D)由C语言编译系统决定

(17)若变量均已正确定义并赋值,以下合法的C语言赋值语句是

       A)x=y==5;        B)x=n%2.5;             C)x+n=i;           D)x=5=4+1;

3.2007年4月相关考题

(12)下列叙述中错误的是(D )
A)计算机不能直接执行用C语言编写的源程序
B)C程序经C编译程序编译后,生成后缀为.obj的文件是一个二进制文件
C)后缀为.obj的文件,经连接程序生成后缀为.exe的文件是一个二进制文件
D)后缀为.obj和.exe的二进制文件都可以直接运行

(13)按照C语言规定的用户标识符命名规则,不能出现在标识符中的是(B )
A)大写字母   B)连接符   C)数字字符   D)下划线

(14)以下叙述中错误的是(C )
A)C语言是一种结构化程序设计语言
B)结构化程序有顺序、分支、循环三种基本结构组成
C)使用三种基本结构构成的程序只能解决简单问题
D)结构化程序设计提倡模块化的设计方法

(15)对于一个正常运行的C程序,以下叙述中正确的是(A)
A)程序的执行总是从main函数开始,在main函数结束
B)程序的执行总是从程序的第一个函数开始,在main函数结束
C)程序的执行总是从main函数开始,在程序的最后一个函数中结束
D)程序的执行总是从程序的第一个函数开始,在程序的最后一个函数中结束

(19)有以下程序,其中%u表示按无符号整数输出(B )
main()
{unsigned int x=0xFFFF;   /* x的初值为十六进制数 */
        printf(“%u\n”,x);
}/*注意:x是占两个字节*/
程序运行后的输出结果是
A)-1      B)65535     C)32767   D)0xFFFF

第三章 顺序结构

一.教学重点、难点

知识点所占分值考核几率专家点评
C语句分类0-130% 简单识记
字符输出函数putchar()1-270%难度适中,重点掌握
字符输入函数getchar()1-270%难度适中,重点掌握
格式输入函数printf() 3-4100%难度适中,重点理解重点掌握
格式输出函数scanf()3-4100%难度适中,重点理解重点掌握

二.教学内容

1.语句

 C语句共分为5类:

1.1控制语句

1.2函数调用语句:

printf(“this  is a c statement”);

1.3表达式语句

每一个合法的表达式后加上分号(;)就构成了表达式语句。

++a;i+j;

语句和表达式的区别:

表达式有唯一确定的值,而语句没有值。

1.4赋值语句

格式:赋值表达式;

i=1,j=2是逗号表达式

i=1; j=2;是两条赋值语句

i++; i--;++i;--i;都是赋值语句

等价于i=i+1;或i=i-1;

1.5空语句:只有一个单独的分号构成的语句。如: ;就是一条空语句。

1.6复合语句:用一对{}将若干语句括起来构成一条复合语句。

2.输入输出语句

在使用库函数时必须先用预编译命令#include<头文件名> 或 #include“头文件名”将相应的头文件包含到源程序中。

如:#include<stdio.h>

2.1.printf()函数

格式:printf(“格式控制”,输出列表);

功能:按格式控制指定的格式输出数据。

注意:格式控制包括以%开头的“格式说明符”和原样输出的普通字符。

如:printf(“a=%d,a+b=%d”,30,4+7);

输出结果是:a=30,a+b=11

(1)d格式

%d:按实际长度输出十进制整数。

%md:输出占m列,若小于m列,左边补空格,若大于m列,按实际输出。

%-md:输出占m列,若小于m列,右边补空格,若大于m列,按实际输出。

%ld:输出长整型数据,输入输出长整型数据时必须用该格式。

例如:printf(“%d,%6d,%-6d,%ld”,386,1234,3456,12345L);

输出结果:386,  1234,3456  ,12345

printf(“%2d”,12345);

输出结果:12345

(2)u格式

 %u:以无符号十进制形式输出整数。

printf(“%u”,-1); 65535

ptintf(“%u”,-32768);32768

(3)o格式

%o:以无符号八进制形式输出整数,不输出前导符0。

printf(“%d,%o”,-1,-1); -1,177777

(4)x或X格式

%x或%X以无符号十六进制形式输出整数。不输出前导符0x或0X,小写对小写,大写对大写。

printf(“%d,%x,%X,%x”,-1,-1,0xabc,0XAbc);

-1,ffff,ABC,abc

注:若要输出十六进制和八进制的前导符,则要用%#o和%#x、%#X格式。

printf(“%#o,%#x,%#X”,-1,-1,0xaBc);

0177777,0xffff,0XABC

(5)c格式

%c用来输出一个字符,不输出单引号定界符。%c和%d可以相互转换。

printf(“%c,%d”,’a’,’a’);  a,97

printf(“%c,%d”,100,100); d,100

(6)s格式

用来输出一个字符串,不输出双引号和字符串结束符。

%s:输出字符串的有效字符。

printf(“%s”,”china\0yunnan”); china

%ms:输出占m列,若小于m列,左边补空格,大于m列,按实际输出。

printf(“%5s,%-5s,%2s”,”swfc”,”swfc”,”swfc”);

 swfc,swfc ,swfc

%m.ns:输出占m列,只输出字符串的左n个字符到m列的右端。

如:printf(“%7.5s”,”yunnan”);

    yunna

(7)f格式:按小数形式输出实型数据。

%f:默认输出6位小数。

如:printf(“%f,%f”,543.12,5.4312e+2);

543.120000,543.120000

%m.nf:输出占m列,其中有n位小数。若超过m列,确保n位小数后按实际输出。注意四舍五入问题。

如:printf(“%7.3f,%-7.3f,%4.2f”,3.1415726,3.1415926,314.5926);

3.142,3.142  ,314.59

(8)e格式

以指数形式输出一个实数。小数点前只有一位非零数,5位小数,3位指数。

如:printf(“%e,%e”,123.4,123.45e-7);

234000e+002,1.234500e-005

(9)g格式

自动在%f和%e中选择较短的一种输出,对于小数部分不输出无意义的0。

如:printf(“%g,%g”,123.45,123.45e-2);

123.45,1.2345

printf(“%g”,123000000.0);

23e+08

小结:

(1)%%表示输出一个%。

如:printf(“%%d=%d”,10,10);

%d=10

(2)除了x,e,g大小写均可外,其它都只能小写。

如:printf(“%d=%D”,20,20);

20=%D

(3)输出格式说明符所能操作的数据类型必须与输出项的类型一致。

如:printf(“%d”,1.234);/*出错*/

2.2. scanf()函数

格式:scanf(“格式控制”,地址列表);

注意:

(1)可指定数据所占的列数,输入后由系统自动截取相应的位数。

如:scanf(“%3d%2d”,&a,&b);

若输入:3863018

则:a的值是:386

b的值是:30

若输入:3863

      a的值是:386

b的值是:3

scanf(“%3c%2d”,&ch,&c);

若输入:3863018

则: ch的值是:’3’

b的值是:30

(2)%*md:表示跳过m列不读。

如:scanf(“%*3d%3d%4d”,&a,&b);

若输入:123456

则:a的值是:456

b的值是:原来的值。

(3)不能在scanf()函数中指定输入数据的小数位数。

如:scanf(“%7.5f”,&a);/*出错*/

在scanf()函数中,输入时普通字符原样输入。

如:scanf(“a=%d,b=%d”,&a,&b);

若要给a赋值5,b赋值10,正确的输入是:a=5,b=10

scanf(“%d*,%d#,%d”,&a,&b,&c);

若要让a,b,c分别得到1,2,3,正确的输入是:1*,2#,3<回车>

若两个格式说明符之间没有其它字符,则在输入数据时,两数据之间要用回车或空格分隔,回车或空格可以是多个。但是,%c格式除外。

如:scanf(“%d%d”,&a,&b);

若想让a的值为5,b的值为10。则正确的输入是:

5 空格10<回车> 或 5<回车>

                    10<回车>

或5空格 空格 空格10<回车>

(6)多个%c格式之间没有其它字符,仍然不能用回车或空格来分隔。

如:scanf(“%c%c%c”,&a,&b,&c);

若输入:a空格b空格c<回车>

a的值是’a’,b的值是空格,c的值是’b’。

(7)格式说明符所能操作的数据类型必须与对应变量的类型相同。

如:int a; scanf(“%f”,&a); /*出错*/

总结:

1.普通字符原样输入,原样输出。

2.对于%d格式,指定宽度小于输出宽度,原样输出。

3.%#o,%#x,%#X表示要输出八进制的前导符数字0,和十六进制的前导符0x,0X。

4.%x,%X格式,小写对小写,大写对大写。

5.%*md:表示跳过相应的输入项。

6.注意进制间的转换,以及无符号数和带符号数之间的转换。

7.在scanf()函数中,给double类型变量输入数据时,应该使用%lf类型说明符,而输出时,可以用%lf,也可以用%lf。

  • 试题分析

1.2008年4月试题分析

(16)有以下程序段

char ch; int k;

ch='a'; k=12;

printf("%c,%d,",ch,ch,k); printf("k=%d\n",k);

已知字符a的ASCll十进制代码为97,则执行上述程序段后输出结果是

A)因变量类型与格式描述符的类型不匹配输出无定值

B)输出项与格式描述符个数不符,输出为零值或不定值

C)a,97,12k=12

D)a,97,k=12

2.2007年9月试题分析

(15)若在定义语句:int  a,b,c,*p=&c; 之后,接着执行以下选项中的语句,则能正确执行的语句是

       A)scanf("%d",a,b,c);                           B)scanf("%d%d%d",a,b,c);  

       C)scanf("%d",p);                                 D)scanf("%d",&p);

(18)有以下程序段

         int   j;      float   y;      char   name[50];

         scanf("%2d%f%s", &j, &y, name);

当执行上述程序段,从键盘上输入55566  7777abc 后,y的值为

       A)55566.0        B)566.0                   C)7777.0          D)566777.0

填空(6)执行以下程序时输入1234567<CR>,则输出结果是 【6】 。

       #include   <stdio.h>

       main()

       {  int  a=1,b;

          scanf("%2d%2d",&a,&b);  printf("%d  %d\n",a,b);

       }

3.2007年4月试题分析

(16)设变量均已正确定义,若要通过scan(“%d%c%d%c”,&a1,&c1,&a2,&c2);语句为变量a1和a2赋数值10和20,为变量c1和c2赋字符X和Y。以下所示的输入形式中正确的是(注:□代表空格字符)( D)
A)10□X□20□Y〈回车〉    B)10□X20□Y〈回车〉 
C)10□X〈回车〉            D)10X〈回车〉
      20□Y〈回车〉                 20Y〈回车〉

填空(6) 执行以下程序后的输出结果是       。
main()
{int a=10;
       a=(3*5,a+4);    printf(“a=%d\n”,a);
}

第四章 选择结构

一.教学重点、难点

知识点所占分值考核几率专家点评
关系运算符及优先次序0-140% 简单识记
关系表达式0-150%简单,属重点识记知识点
逻辑运算符及优先级1-250%简单识记
逻辑表达式1-250%简单,属重点识记知识点
if语句的几种形式1-2100%简单识记
if语句的嵌套1-2 100%难度适中,重点掌握
条件运算符0-1100%难度适中,重点掌握
switch语句2-4100%简单,重点掌握重点理解
语句标号0-110%偏难,不是重点
goto1-210%简单识记

二.教学内容

1.关系运算与逻辑运算

1.1逻辑值

真(非零值)            假(零)

1.2关系运算符及其表达式

<  <=  >  >=   ==  !=

关系运算符优先级别低于算术运算符,高于赋值运算符。

( <  <=  >  >=)优先级别高于(==  !=)

如:a>b+c 等价于a>(b+c)

a==b<c等价于a==(b<c)

a=b<c等价于a=(b<c)

4==4 表达式的值为“真”。

4=4 表达式不合法

关系表达式的值只有1和0,其中1表示“真”,0表示“假”。

1.3逻辑运算符及其表达式

&& 逻辑“与” || 逻辑“或” !逻辑“非”

优先级别:! 》&& 》||

运算规则:

逻辑&&:遇假则假

逻辑||:遇真则真

逻辑!:真假互换

逻辑表达式的值:1(真)、0(假)

例如:3>4 结果是:0

3&&4结果是:1

!3&&4结果是:0

0||3结果是:1

注意:在求解逻辑与(&&)表达式时,若&&运算符左边表达式的值为0(假),则不再进行&&右边表达式的运算,且将整个&&表达式的值定为0;在求解逻辑或(||)表达式时,若||左边表达式的值为非0值(真),则不再进行||右边表达式的运算,且将整个逻辑||表达式的值定为1(真)。

2.if语句

2.1.if语句格式:

1)  if(表达式)       2)if(表达式)

       语句1;          语句1;

    else           

       语句2;

 称为:全if             单if

注意:

(1)if 后的表达式必须用()括起,else后没有表达式。

(2)if和else都只能控制紧跟它的一条语句,若要控制多条语句,必须用一对{}括起构成一条复合语句。

2.2执行方式:

2.21 if语句的执行方式:首先判断表达式的值是否为“真”,若“真”,则执行语句部分。如果表达式的值为“假”,则“跳过”语句部分执行if语句后面的其它语句。

2.22 if-else语句的执行方式:首先判断表达式的值是否为“真”,若“真”,则执行语句部分。如果表达式的值为“假”,则执行else语句后面的语句。

例1:main()

{int m=5;

 if(m++>5) printf(“m=%d”,m);

 else printf(“m=%d”,m--);

}

例2:main()

{int m=5;

 if(++m>5) printf(“m=%d”,m);

 else printf(“m=%d\n”,m--);

     printf(“m=%d”,m);

}

2.3 if 语句的嵌套

if(表达式1)

   if(表达式2) 语句1;

   else         语句2;

else

   if(表达式3) 语句3;

   else           语句4;

else总是与前面最近的且未配对的if语句配对,组成一对if-else语句。

if(表达式1)

  if(表达式2)  语句1;

else

   if(表达式3) 语句2;

   else           语句3;

第一个else语句有的同学会把它误以为和第一个if配对,但是实际的情况是和第二个if语句配对,即:

   if(表达式1)

      if(表达式2)  语句1;

else

         if(表达式3) 语句2;

         else           语句3;

例1.请分析下列程序的输出结果。

main()

{ int s,t,a,b;

   sanf(“%d%d”,&a,&b);

   s=1;t=1;

   if(a>0) s=s+1;

if(a>b) t=s+1;

   else if(a==b) t=s;

else t=2*s;

printf(“%d\n”,t);

}

若运行时输入5  10 回车,则程序的执行结果是?

main()

{ int s,t,a,b;

   sanf(“%d%d”,&a,&b);

   s=1;t=1;

   if(a>0) {s=s+1;

if(a>b) t=s+1;}

   else if(a==b) t=s;

else t=2*s;

printf(“%d\n”,t);

}

若运行时输入5  10 回车,则输出结果是?

例2.分析下列程序的输出结果

main()

{ int a=4,b=3,c=5,t=0;

  if(a<b) t=a;a=b;b=t;

  if(a<c) t=a;a=c;c=t;

  printf(“%d %d %d\n”,a,b,c);

}

main()

{ int a=4,b=3,c=5,t=0;

  if(a<b){ t=a;a=b;b=t;}

  if(a<c) {t=a;a=c;c=t;}

  printf(“%d %d %d\n”,a,b,c);

}

联想交换的思想:若要交换a和b的值,通常的做法是:

{t=a;a=b;b=t;}

3.条件运算符和条件表达式

条件运算符:? :

是唯一一个三目运算符。优先级别高于赋值运算,结合方向自右向左。

格式:表达式1 ?表达式2 :表达式3

执行方式:先求“表达式1”的值,若其值为“真”,求出“表达式2”的值作为整个条件表达式的值;若其值为“假”,求出“表达式3”的值作为整个表达式的值。

例如:max=a>b?a:b;

相当于:if(a>b)

        max=a;

        else

        max=b;

a>b?a:c>d?c:d 

相当于a>b?a:(c>d?c:d)

注意:表达式1、2、3的值不要求具有相同的类型,最后结果的类型为表达式2、3中较高类型的一种。如:(x=6)>(y=5)?1:1.5 表达式的值是 1.0而不是1。

4.switch语句

格式:

switch(表达式)

{ case   常量表达式1:语句1;break;

 case   常量表达式2:语句2;break;

          …

case    常量表达式n:语句n;break;

default             :语句n+1;break;

说明:

  • switch、case、default、break都是关键字。花括号里面的语句叫做switch语句体。Switch语句体中可以没有break语句和default部分。
  • Switch语句的圆括号中表达式的值必须是整型或是字符型,不能为实型。case后的表达式可以是求得整型量的常量表达式,但是常量表达式中不能含有变量。
  • 执行Switch语句时,首先计算Switch后圆括号的表达式的值,然后将这个值与语句体中case后的常量表达式的值相比较,如果某个常量表达式的值与之相等,则执行该case后的语句块;如果没有任何一个常量表达式的值与之相等,则执行default后的语句块。
  • 在执行的时候如果遇到break语句,则跳出switch语句。如果执行完一个case或者default语句块后没有遇到break,则继续顺序往下执行,知道遇到break语句或者语句体被执行完毕为止。
  • default最多只能有一个,通常出现在switch语句的最后部分,但也可以出现在case之间或所有的case之前。

四.试题分析

1.2008年4月试题分析:

(17)已知字母A的ASCⅡ代码值为65,若变量kk为char型,以下不能正确判断出kk中的值为大写字母的表达式是

A)kk>='A'&&kk<='Z' B)!(kk>='A'||kk<='Z')

C)(kk+32)>='a'&&(kk+32)<='z' D)isalpha(kk)&&(kk<91)

(18)当变量c的值不为2、4、6时,值也为“真”的表达式是

A)(c==2)||(c==4)||(c==6) B)(c>=2&&c<=6)||(c!=3)||(c!=5)

C)(c>=2&&c<=6)&&!(c%2) D)(c>=2&&c<=6)&&(c%2!=1)

(19)若变量已正确定义,有以下程序段

int a=3,b=5,c=7;

if(a>b) a=b; c=a;

if(c!=a) c=b;

printf("%d,%d,%d\n",a,b,c);

其输出结果是

A)程序段有语法错 B)3,5,3 C)3,5,5 D)3,5,7

(20)有以下程序

#include <stdio.h>

main()

{ int x=1,y=0,a=0,b=0;

switch(x)

{ case 1:

switch(y)

{ case 0: a++; break;

case 1: b++; break;

}

case 2: a++; b++; break;

case 3: a++; b++;

}

printf(“a=%d,b=%d\n”,a,b);

}

程序的运行结果是

A)a=1,b=0 B)a=2,b=2

C)a=1,b=1 D)a=2,b=1

2.2007年9月试题分析

(20)有以下计算公式

若程序前面已在命令行中包含math.h文件,不能够正确计算上述公式的程序段是

       A) if(x>=0) y=sqrt(x);                          B) y=sqrt(x);

              else y=sqrt(-x);                                     if(x<0) y=sqrt(-x);

       C) if(x>=0) y=sqrt(x);                          D) y=sqrt(x>=0?x :-x);

              if(x<0) y=sqrt(-x);

(21)设有条件表达式:(EXP)? i++ :j--  ,则以下表达式中与(EXP)完全等价的是

       A)(EXP==0)           B)(EXP!=0)             C)(EXP==1)            D)(EXP!=1)

(23)已有定义:char  c; ,程序前面已在命令行中包含ctype.h文件。不能用于判断c中的字符是否为大写字母的表达式是

       A)isupper(c)                                        B)'A'<=c<='Z'

       C)'A'<=c&& c <='Z'                           D)c <=('z'-32)&&('a'-32)<= c

(7)以下程序的功能是:输出a、b、c三个变量中的最小值。请填空。

       #include <stdio.h>

       main( )

       {   int  a,b,c,t1,t2;

           scanf("%d%d%d",&a,&b,&c);

           t1= a<b ?  【7】 ;

           t2= c <t1 ? 【8】 ;

           printf("%d\n", t2 );

    }

3.2007年4月试题分析

(20)设变量x和y均已正确定义并赋值,以下if语句中,在编译时将产生错误信息的是(C )
A)if(x++);                           B)if(x>y&&y!=0); 
C)if(x>y) x- -                        D)if(y<0) {;}
  else y++;                           else x++;

(21)以下选项中,当x为大于1的奇数时,值为0的表达式( )
A)x%2==1      B)x/2      C)x%2!=0    D)x%2==0

(22)以下叙述中正确的是(C )
A)break语句只能用于switch语句体中
B)continue语句的作用是:使程序的执行流程跳出包含它的所有循环
C)break 语句只能用在循环体内和switch语句体内
D)在循环体内使用break语句和continue语句的作用相同

(23)有以下程序( )
main()
{int k=5,n=0;
 do
 {switch(k)
  {case1:    case3:n+=1; break;
default;n=0;k--;
case2:  case4:n+=2;k--;break;
}
printf(“%d”,n);
}while(k>0&&n<5);
}
程序运行后的输出结果是
A)235     B)0235    C)02356     D)2356

第五章  循环结构

一.教学重点、难点

知识点所占分值 考核几率专家点评
while语句2-3100%重点理解重点掌握
do...while语句2-3100%重点理解重点掌握
for语句5-7100%重点理解重点掌握
循环嵌套4-6 100%重点理解重点掌握
循环比较0-120%简单识记
break语句2-370% 难度适中,重点掌握
continue语句2-350%难度适中,重点掌握

注意:循环在这一章中的知识点比较少,但是它贯穿了整个的C语言的章节中,老师在教学中一定要把它它当做重点中的重点来抓!

二.教学内容 

1.while语句

格式:    while(表达式)

{

循环体语句

}

注意:

1.1.while是C语言的关键字。

1.2.while后必须有小括号将表达式括起,里面的表达式是C语言中任意的表达式,作用是控制循环。其值为“真”(非0)则执行循环体语句,否则跳出while循环。

1.3.while语句也只能控制紧跟它的一条语句。若需要控制多条语句,必须用{}括起,构成一条复合语句。

1.4.圆括号内的表达式不能省略。循环体中的可以由一条空语句构成,表示循环体部分不做任何的操作。如:while(表达式);/*;是循环体,它是一条空语句*/

例如:分析下列程序的输出结果。

1.5.执行过程:

   (1)计算圆括号中表达式的值。若为非0则执行循环体语句,若为0则跳出循环。

   (2)执行完循环体语句后重复过程(1)。

main()

{ int i=1,sum=0;

  while(i<=100){

     sum=sum+I;

     i++;

}

  printf(“sum=%d”,sum);

}

这是学习C语言基础循环的最好的练习,老师让学生练习的时候可以把i控制在10以内,让学生知道什么是循环.

2.d0-while语句

格式:   do

         循环体

while(表达式);

注意:

2.1.do是C语言的关键字,需要和while一起搭配使用。

2.2.while后必须有小括号将表达式括起,里面的表达式是C语言中任意的表达式,作用是控制循环。其值为“真”(非0)则执行循环体语句,否则跳出while循环。

2.3.while语句也只能控制紧跟它的一条语句。若需要控制多条语句,必须用{}括起,构成一条复合语句。

2.4.圆括号内的表达式不能省略。循环体中的可以由一条空语句构成,表示循环体部分不做任何的操作。如: do{;}while(表达式);/*;是循环体,它是一条空语句*/

2.5.由于do-while循环结构整个语法上也是C语言语句,因此最后的分号必不可少,它同样表示语句的结束。

2.6.执行过程:

   (1)执行循环体语句。

   (2)计算圆括号中表达式的值。若为非0则重复(1),否则跳出循环。

3.for语句

格式:

for(表达式1;表达式2;表达式3)

循环体

3.1.for是C语言的关键字.

3.2for之后的圆括号内一共有三个表达式,以分号“;”隔开。一般情况下,表达式1的作用是赋初值;表达式2的作用是控制循环;表达式3的作用是赋值。

3.3.for语句也只能控制紧跟它的一条语句。若需要控制多条语句,必须用{}括起,构成一条复合语句。

3.4. 表达式1、2、3均可以省略,若省略表达式2,则认为表达式2的值始终为真。而两个分号绝不能省。

3.5执行过程:

  (1)计算表达式1;

  (2)计算表达式2,若其值为非0,转步骤(3);若其值为0则转步骤(5);

  (3)执行一次for循环体。

  (4)计算表达式3,转步骤(2)。

  (5)结束循环,执行for语句后面的语句。

4.循环结构的嵌套

在一个循环体内,又包含另一个循环。

三种循环语句可以相互嵌套。

main()

{ int i,j;

 for(i=1;i<3;i++)

for(j=1;j<4;j++)            

   printf(“\ni=%d,j=%d”,i,j); printf(“\ni=%d,j=%d”,i,j);

}

for(i=1; ;i++) printf(“%d”,i);

/*表达式2的值始终为真,这是死循环*/

5.break 和 continue 语句

break 语句用于结束循环或switch结构。

continue 语句用于结束本次循环,跳过循环中continue后尚未执行的语句,继续进行下一次循环条件的判断。

注意:break 语句只能控制直接包含它的switch结构或循环。

continue语句只能控制直接包含它的循环。

例1:

main( )

{ int i,s1=0,s2=0,s3=0;

  for(i=1;i<=10;i++)

{switch(i%5)

  {case 1:s1++;

   case 2:s2++;break;

   case 3:s3++;contiune;

   }

 s1++;

}

printf(“%d,%d,%d”,s1,s2,s3);

}

例2:

把1~100之间能被4整除的数输出。(老师一定要教会学生这中方法!)

main()

{

   int i;

for(i=1;i<=100;i++)

{

  if(i%4!=0) continue;

  printf(”%3d”,i);

}

}

三.试题分析

1.2008年4月试题分析

(21)有以下程序

#include <stdio.h>

main()

{ int x=8;

for( ; x>0; x--)

{ if(x%3) {printf(“%d,”,x--); continue;}

printf(“%d,”,--x);

}

}

程序的运行结果是

A)7,4,2 B)8,7,5,2

C)9,7,6,4 D)8,5,4,2

(22)以下不构成无限循环的语句或者语句组是

A)n=0; B)n=0;

do{++n;}while(n<=0); while(1){n++;}

C)n=10; D)for(n=0,i=1; ;i++) n+=i;

while(n);{n--;}

(31)有以下程序

#include <stdio.h>

main()

{ int s[12]={1,2,3,4,4,3,2,1,1,1,2,3},c[5]={0},i;

for(i=0;i<12;i++) c[s[i]]++;

for(i=1;i<5;i++) printf(“%d”,c[i]);

printf(“\n”);

}

程序的运行结果是

A)1 2 3 4 B)2 3 4 4 C)4 3 3 2 D )1 1 2 3

(32)有以下程序

#include <stdio.h>

void fun(int *s,int nl,int n2)

{ int i,j,t;

i=nl; j=n2;

while(i<j) {t=s[i];s[i]=s[j];s[j]=t;i++;j--;}

}

main()

{ int a[10]={1,2,3,4,5,6,7,8,9,0},k;

fun(a,0,3); fun(a,4,9); fun(a,0,9);

for(k=0;k<10;k++)printf(“%d”,a[k]); printf(“\n”);

}

程序运行的结果是

A)0987654321 B)4321098765

C)5678901234 D)0987651234

(33)有以下程序

#include <stdio.h>

#include <string.h>

void fun(char *s[ ],int n)

{ char *t; int i,j;

for(i=0;i<n-1;i++)

for(j=i+1;j<n;j++)

if(strlen(s[i])>strlen(s[j])) {t=s[i];s[i]=s[j];s[j]=t;}

}

main()

{char *ss[]={“bcc”,”bbcc”,”xy”,”aaaacc”,”aabcc”};

fun(ss,5); printf(“%s,%s\n”,ss[0],ss[4]);

}

程序的运行结果是

A)xy,aaaacc B)aaaacc,xy C)bcc,aabcc D)aabcc,bcc

(35) 有以下程序

#include <stdio.h>

void fun(char *a,char *b)

{while(*a==’*’) a++;

while(*b=*a) {b++;a++;}

}

main()

{char *s=”****a*b****”,t[80];

fun(s,t); puts(t);

}

程序的运行结果是

A)*****a*b B) a*b C) a*b**** D) ab

(8)若有定义:int k;,以下程序段的输出结果是【8】。

for(k=2;k<6;k++,k++) printf(“##%d”,k);

(9)以下程序段的定义语句中,x[1]的初值是【9】,程序运行后输出的内容是【10】。

#include<stdio.h>

main()

{ int x[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},*p[4],i;

for(i=0;i<4;i++)

{ p[i]=&x[2*i+1];

printf(“%d ”,p[i][0]);

}

printf(“\n”);

}

2.2007年9月试题分析

(19)若变量已正确定义,有以下程序段

              i=0;

              do  printf("%d, ",i);  while( i++ );

              printf("%d\n",i);

其输出结果是

       A)0,0                B)0,1                C)1,1                D)程序进入无限循环

(22)有以下程序

       #include   <stdio.h>

       main()

       {  int   y=9;

          for(  ;  y>0;  y--)

             if(y%3==0)  printf("%d", --y);

       }

程序的运行结果是

       A)741               B)963               C)852               D)875421

(24)有以下程序

       #include   <stdio.h>

       main()

       {  int   i,j, m=55;

          for(i=1;i<=3;i++)

            for(j=3; j<=i; j++)  m=m%j;

          printf("%d\n ", m);

       }

程序的运行结果是

       A)0                   B)1                   C)2                  D)3

(34)有以下程序

       #include   <stdio.h>

       void  fun(int  *a, int  n) /* fun函数的功能是将a所指数组元素从大到小排序 */

       {  int   t, i, j;

          for (i=0; i<n-1;i++)

            for (j=i+1; j<n; j++)

              if (a[i]<a[j])  {  t=a[i]; a[i]=a[j]; a[j]=t;  }

       }

       main()

       {  int   c[10]={1,2,3,4,5,6,7,8,9,0},i;

          fun(c+4, 6);

          for (i=0;i<10; i++)  printf("%d,", c[i]);

          printf("\n");

       }

程序的运行结果是

       A)1,2,3,4,5,6,7,8,9,0,                          B)0,9,8,7,6,5,1,2,3,4,

       C)0,9,8,7,6,5,4,3,2,1,                          D)1,2,3,4,9,8,7,6,5,0,

(8)以下程序的输出结果是 【9】 。

       # include   <stdio.h>

       main()

       {  int   n=12345, d;

          while(n!=0){  d=n%10;  printf("%d", d);  n/=10;  }

       }

(9)有以下程序段,且变量已正确定义和赋值

         for(s=1.0, k=1; k<=n; k++)  s=s+1.0/(k*(k+1));

         printf("s=%f\n\n", s);

请填空,使下面程序段的功能与之完全相同

         s=1.0; k=1;

         while(  【10】 )  {  s=s+1.0/(k*(k+1)); 【11】 ;  }

         printf("s=%f\n\n", s);

(10)以下程序的输出结果是 【12】 。

       #include   <stdio.h>

       main()

       {  int   i;

          for(i='a'; i<'f'; i++,i++)  printf("%c",i - 'a' + 'A');

          printf("\n");

    }

3.2007年4月试题分析

(22)以下叙述中正确的是(C )
A)break语句只能用于switch语句体中
B)continue语句的作用是:使程序的执行流程跳出包含它的所有循环
C)break 语句只能用在循环体内和switch语句体内
D)在循环体内使用break语句和continue语句的作用相同

(23)有以下程序( )
main()
{int k=5,n=0;
 do
 {switch(k)
  {case1:    case3:n+=1; break;
default;n=0;k--;
case2:  case4:n+=2;k--;break;
}
printf(“%d”,n);
}while(k>0&&n<5);
}
程序运行后的输出结果是
A)235     B)0235    C)02356     D)2356

(24)有以下程序
mian()
{int i,j;
  for(i=1;i<4;i++)
{for(j=i;j<4;j++) printf(“%d*%d=%d “,i,j,i*j);
printf(“\n”);
}
}
程序运行后的输出结果是( )
A)    1*1=1  1*2=2  1*3=3          B) 1*1=1  1*2=2  1*3=3
2*1=2  2*2=4                    2*2=4  2*3=6
3*1=3                           3*3=9
C) 1*1=1                         D) 1*1=1
1*2=2   2*2=4                   2*1=2   2*2=4
1*3=3   2*3=6   3*3=9           3*1=3   3*2=6  3*3=9

}

(7) 当执行以下程序时,输入1234567890<回车>,则其中while循环体将执行       次。
#include <stdio.h>
main()
{char ch;
   While((ch=getchar())==’0’)  printf(“#”);
}

  字符型数据   位运算

一.教学内容

1.字符型数据

1.1字符常量:用一对单引号括起的一个字符。

例如:’A’,’a’,’6’是合法的字符型常量。

”a”,’ab’,A, 5,‘12’都是不合法的字符型常量。

1.2转义字符常量:必须以一个反斜杠“\”开头.常见的转义字符见表5-1。

\n:回车换行  \t:横向跳格 \v:竖向跳格

\b:退格      \r:回车     \f:换页

\\: \          \’:’        \”:”

1.3  \ddd:ddd表示最多可以有三位8进制数。

1.4  \xhh:hh表示最多可以有二位16进制数。

注意:三位8进制数不一定以0开头,只要是0~7之间的数字即可。

例:下列字符常量中合法的是( )

A.\027  B.’\028’  C.’\x12’  D.’\0x1f’

E.’\1234’  F.’\xffh’  G.’AB’   H.’123’

I.’\12’  J.”A”  K.’\xf’

例:下列字符常量中合法的是( )

A.’/’  B.’/t’   C.’ ’ ’   D.’ ” ’ E.’\b’

F.’\’   G.’\\’   H.’//’   I,’\’’  J.’\”’

1.5字符型变量

关键字:char ,字符型变量在内存中占1字节。

例:char a=’5’;

‘a’字符的ASCII码值是97

‘A’ 字符的ASCII码值是65

同一字母的大小写之差是32,那么我们要把小写字母变成大写字母就相应的字母减去32即可,同样大写字母加上32后就变成了与其相对应的小写字母。

数字’0’~’9’对应的ASCII码值是48~57。

2.字符数据的输入输出

2.1.putchar()和printf( )

格式:putchar(字符),  printf(“%c”,ch);

功能:输出一个字符,但不输出单引号。其中“字符”可以是一切合法的字符型或整型数据。它会自动将整型数据转换为相应的字符输出。

putchar(‘a’);a         printf(“%c”,’a’); a

putchar(65);A          printf(“%c”,65); A

char ch=‘g’;putchar(ch);输出:g

char ch=‘g’;printf(“%c”,ch); 输出:g

2.2.getchar()

格式:getchar()

功能:接收一个从键盘输入的字符。

注意:1.它可以接收从键盘上输入的任何字符,包括回车符、空格符等。

2.任何输入都是在回车后方按顺序送入内存中,即才被函数接收。如:char a,b;a=getchar();b=getchar();

若输入:1<回车> 则变量a的值为字符 ‘1’ 变量b的值为 回车符。

2.3.scanf函数输入数据:在进行字符数据输入的时候,空格符、回车、横向跳格都是合法有效的字符,都将被读入并赋值给相应的变量。

3.位运算(详细的见课本52页)

二.试题分析

1.2008年试题分析

(13)以下选项中不属于字符常量的是

A) 'C'  B) "C"  C)'\xCC0'  D) '\072'

(16)有以下程序段

char ch; int k;

ch='a'; k=12;

printf("%c,%d,",ch,ch,k); printf("k=%d\n",k);

已知字符a的ASCll十进制代码为97,则执行上述程序段后输出结果是

A)因变量类型与格式描述符的类型不匹配输出无定值

B)输出项与格式描述符个数不符,输出为零值或不定值

C)a,97,12k=12 D)a,97,k=12

(17)已知字母A的ASCⅡ代码值为65,若变量kk为char型,以下不能正确判断出kk中的值为大写字母的表达式是

A)kk>='A'&&kk<='Z' B)!(kk>='A'‖kk<='Z')

C)(kk+32)>='a'&&(kk+32)<='z' D)isalpha(kk)&&(kk<91)

(38)变量a中的数据用二进制表示的形式是01011101,变量b中的数据用二进制表示的形式是11110000。若要求将a的高4位取反,低4位不变,所要执行的运算是

A)a^b B)a|b C)a&b D)a<<4

2.2007年9月试题分析

(23)已有定义:char  c; ,程序前面已在命令行中包含ctype.h文件。不能用于判断c中的字符是否为大写字母的表达式是

       A)isupper(c)                                        B)'A'<=c<='Z'

       C)'A'<=c&& c <='Z'                           D)c <=('z'-32)&&('a'-32)<= c

(26)已知字符'A'的ASCII代码值是65,字符变量c1的值是'A',c2的值是'D'。执行语句printf("%d, %d", c1, c2-2 ); 后,输出结果是

       A)A,B               B)A,68                    C)65,66                   D)65,68

#include   <stdio.h>

       main()

       {  int   i;

          for(i='a'; i<'f'; i++,i++)  printf("%c",i - 'a' + 'A');

          printf("\n");

    }

3.2007年4月试题分析

(25)以下合法的字符型常量是( )
A)‘\x13’     B)‘\018’       C)‘65’       D)‘\n’

(27)已知大写字母A的ASCII码是65,小写字母aASCII码是97,以下不能将变量c中大写字母转换为对应小写字母的语句是( )
A)c=(c-A)%26+’a’                    B)c=c+32
C)c=c-‘A’+’a’                              D)c=(‘A’+c)%26-‘a’

(7) 当执行以下程序时,输入1234567890<回车>,则其中while循环体将执行       次。
#include <stdio.h>
main()
{char ch;
   While((ch=getchar())==’0’)  printf(“#”);
}

第六章  函数

一.教学重点、难点

知识点所占分值考核几率专家点评
库函数1-260%简单,重点识记知识点
函数的定义0-150%简单,重点识记知识点
形参和实参及函数调用2-380%难度适中,重点理解重点掌握
函数调用的一般形式和调用方式2-3 90%偏难,重点掌握重点理解
函数的说明及其位置0-160%简单识记
函数的嵌套调用1-390%偏难,重点掌握重点理解
函数的递归调用1-280%偏难,重点掌握重点理解

二.教学内容

函数是C程序的基本单位。

  1. 函数的定义:

函数返回值的类型名  函数名(类型名1  形参名1,类型名2  形参名2,….)

{

说明部分

语句部分

}

说明:

1.1一个C程序可以由一个或多个源程序文件组成。一个源程序文件可以由一个或多个函数组成。 C程序 > 源程序 > 函数

1.2函数返回值的类型名缺省时,返回值类型默认为int型,而不是没有返回值。若没有返回值的时候应该为void.

1.3函数名是用户自定义标识符,唯一且独有,不得与同一程序中其他函数相同。主函数的函数名必须是main。

1.4函数后面的括号是必不可少的,括号中的为形式参数列表。形式参数用于数据的传递,同样是用户标识符。在同一函数内形式参数必须是唯一的。如果函数不带形式参数,则形式参数列表可以省略。

1.5函数体部分的一对花括号必不可少。

1.6函数之间的关系是相互平行、独立的,不是相互隶属的。

1.7函数不能嵌套定义,不能在一个函数体内定义另一个函数。

1.8函数可以相互调用,但不能调用main()函数。

1.9函数的分类:

1.从形式分:

无参函数:如:main()  getchar()

带参函数:如:strlen(“abc”)

2.从用户使用的角度分

标准函数(库函数):如:getchar()

用户自定义函数:double add(int a,int b)

{函数体}

1.10函数的定义的比较

类型名 函数名(类型名 形参1,类型名 形参2,…)/*函数首部*/

{函数体}

int min(int x, int y)          int min( x,y)

{函数体}                   int x,y;

/*现代方式*/                {函数体}/*传统方式*

例如:

float fun(int x,int y)    float fun(x,y)

{     }           int x;

int y;

{   }

以上函数的定义是合法的。

int fun(int x,y)

{ … }

int fun(int x;int y)

{ … }

int fun(int x,y)

int y;

{   …   }

int fun(x,y)

{int x,y;

}

int fun(x,y)

int x,y,z;

{ … }

以上函数的定义均是非法的。

2. 函数的参数和函数值

2.1.函数的参数可以分为:形式参数和实际参数。

形参:函数定义时函数名后小括号内的参数。

实参:函数调用时函数名后小括号内的参数。

注意:

(1)形参只有在该函数被调用时才占内存单元,即该变量才可用;函数调用结束时形参所占的内存单元被释放,即不可用。

(2)实参和形参的数据类型应该对应相同。否则,必须将函数的定义放在函数调用之前或在调用之前对函数作原型声明。

例如:

void sum(int x,int y)//函数定义,x,y 是被调用函数的参数,我们叫它形参

{

printf(“%d”,x+y);

}

main( )

{

sum(3,5);//函数调用,这里的3和5是调用函数的参数,我们叫为实参

}/*类型对应不相同*/

2.2.函数值:

函数的返回值即函数值。

return 语句的格式:

retrun 表达式;或return (表达式);

功能:将表达式的值作为函数值返回给主调函数,并结束本函数的执行。

注意:

2.21.函数值应通过return语句返回,一个函数中可以有多条return语句,只要执行其中任何一条return语句,该函数立即结束执行,并将该retrun后表达式的值返回。

例如:int max(int a,int b)

{

if(a>b)  return a;

          else     return b;

}

2.22.函数值的类型保持与函数定义时所指定的类型相同,而与retrun后表达式的值的类型无关。若定义函数时不指定函数的类型,则默认是int。

max(float a,float b)      int max(float a,float b)

{return a/b;}           {return a/b;}

2.23.为了明确函数无返回值,可将函数指定为空类型(void)。

例如:void fun( int a)

{

printf(“%d”,a);

}

3.函数调用

调用格式:函数名(实参)

无参调用格式:函数名() clrscr();

带参调用格式:函数名(实参列表)

3.1调用函数时,函数名必须一致。函数名是唯一区别函数的标志。

3.2实参和形参的类型匹配,个数一致,形式上一一对应。

3.3一般情况下,函数应该先定义后调用。

3.4函数可以直接或者间接调用自己,称为递归调用。

例如:

void swap(int a,int b)/*函数定义*/

{

a=a+b;b=a-b;a=a-b;

}

main()

{

int a=2,b=5;

   swap(a,b);/*函数调用*/

   printf(“a=%d,b=%d”,a,b);

}

4.函数的原型声明

格式:函数类型 函数名(形参类型1,形参类型2,…);  或

函数类型 函数名(形参类型1 形参名1,形参类型2 形参名2…);

对上例中的swap函数作原型声明的格式:

void swap(int,int);

void swap(int a,int b);

void swap(int x,int y);

注意:

若被调函数定义在主调函数之前时,可以不作原型声明。若被调函数定义在主调函数之后,则在调用前应作原型声明。

例如:

void swap(int a,int b)/*函数定义*/

{a=a+b;b=a-b;a=a-b;}

main()

{int a=2,b=5;

 swap(a,b);/*函数调用*/

 printf(“a=%d,b=%d”,a,b);

}

main()

{int a=2,b=5;

void swap(int,int);/*原型声明*/

 swap(a,b);/*函数调用*/

 printf(“a=%d,b=%d”,a,b);

}

void swap(int a,int b)/*函数定义*/

{a=a+b;b=a-b;a=a-b;}

如果在程序文件的开始就对函数作外部原型声明,则在各主调函数中不必再作原型声明。

例:

void swap(int,int);/*外部原型申明*/

main()

{int x=1,y=2;

 swap(x,y);

 swap(x+1,y+1);

}

void swap(int a,int b)

{……}

补充:若果形参中有数组,则作原型声明时数组的中括号不能省略。

例如:float fun(double b[])

{      }

可以用以下方式原型声明:

float fun(double []);

float fun(double a[]);

而以下的声明方式是错误的:

float fun(double b);

5.函数的嵌套调用和递归调用

嵌套调用:在一个函数内调用另一个函数。

递归调用:在一个函数内直接或间接调用它本身。若在函数A内直接调用函数A称为直接递归。若函数A调用函数B,函数B又调用函数A则称为间接递归调用。

例1:

long fun(int k)

{

if(k==1||k==2) return 1;

   else return fun(k-1)+fun(k-2);

}

main()

{

int n;

 scanf(“%d”,&n);

 printf(“%ld”,fun(n));

}

例2:

int func(int a,int b)

{

return (a+b);

}

main()

{

int x=2,y=5,z=8,r;

   r=func(func(x,y),z);

   printf(“%d\n”,r);

}

6.函数的参数传递

     C语言中,函数参数之间的数据传递仅仅通过实参向形参的单向数据传递,即‘“值传递“。不能我们不能通过形参的改变来改变实参。

总结:

  • 数据只能从实参向形参单向传递。
  • 到目前为止,函数之多能返回一个值。就是return 带回来的值。

例如:

void swap(int a1,int b1)/*函数定义*/          void swap(int *a3,int *b3)

{                                      {

    int t1;                                  int t2;

t=a1;a1=b1;b1=t;                            t2=*a3;*a3=*b3;*b3=t;                           

}                                       }

main()                                  main()

{                                      {

int a=2,b=5;                            int a2=2,b2=5;

   swap(a,b);/*函数调用*/                  swap(&a2,&b2);/*函数调用*/

   printf(“a=%d,b=%d”,a,b);               printf(“a2=%d,b2=%d”,a2,b2);

}                                       }

地址变量
10002a
10025b
1004 a1
1006 b1
1008  
1010  
1012  
1014  
1016  

用地址表来讲解这些问题比较好。

三.试题分析

1.2008年4月试题分析

(34)有以下程序

#include <stdio.h>

int f(int x)

{int y;

if(x==0||x==1) return (3);

y=x*x-f(x-2);

return y;

}

main()

{int z;

z=f(3); printf(“%d\n”,z);

}

程序的运行结果是

A)0 B)9 C)6 D)8

(12)以下程序的输出结果是【13】。

#include<stdio.h>

void fun(int x)

{ if(x/2>0) fun(x/2);

printf(“%d ”,x);

}

main()

{fun(3); printf(“\n”);}

2.2007年9月试题分析

(25)若函数调用时的实参为变量时,以下关于函数形参和实参的叙述中正确的是

       A)函数的实参和其对应的形参共占同一存储单元

       B)形参只是形式上的存在,不占用具体存储单元

       C)同名的实参和形参占同一存储单元

       D)函数的形参和实参分别占用不同的存储单元

(27)以下叙述中错误的是

       A)改变函数形参的值,不会改变对应实参的值

       B)函数可以返回地址值

       C)可以给指针变量赋一个整数作为地址值

       D)当在程序的开头包含头文件stdio.h时,可以给指针变量赋NULL

3.2007年4月试题分析

(8) 以下程序的运行结果是       。
int  k=0;
void fun(int  m)
{  m+=k; k+=m; printf(“m=%d\n  k=%d  ”,m,k++);}
main()
{ int i=4;
 fun(i++); printf(“i=%d  k=%d\n”,i,k);
}      

第七章 数组

一.教学重点、难点

知识点所占分值考核几率专家点评
一维数组的定义及引用1-380%简单,重点掌握
一维数组的初始化1-280%简单,重点掌握
二维数组的定义及引用3-490%偏难,重点掌握重点理解
二维数组的初始化1-2 90%简单,重点掌握
通过赋初值定义二维数组1-260%偏难,重点理解

二.教学讲点

8.1一维数组的定义和引用

8.1.1一维数组的定义

格式:类型名 数组名[常量表达式];

例如:int a[8];

注意:

1.数组名属于用户标识符,必须满足用户标识符的命名规则。

如:int do[5]; float 3com[10];

char a-b[5]; 都是非法的定义

2.定义数组时,方括号必不可少,方括号中的表达式不能含有变量,且表达式的值必须是大于0正整数,表示数组元素的个数,也成为数组的长度。

如:int a[5.3]; int a[-4]; int a[n]; int a[0]; {int N=5; int a[N];} 都是非法的定义

 #define M 5

int a[M];

3.同一数组元素在内存中所占的存储空间是依次连续的,每个数组只能有一个下标,数组下标是从0开始,到数组长度减4结束。

例如:int a[5];

      

a[0]   a[1]   a[2]   a[3]   a[4]

8.1.2一维数组元素的引用

格式:数组名[下标表达式]

如:double a[10];/*定义数组*/

int b=a[4];/*引用数组元素a[4]*/

int b=a[2*2]; /*引用数组元素a[4]*/

说明:

  1. 数组中的元素其实就是一个变量,占一个存储单元。如数组b中的变量就是int型的变量。
  2. 引用数组元素时,下标表达式的值的上限为定义是常量表达式减一,下限为0.在引用时保证下标不能超过定义时的常量表达式减一,即下标不能越界。
  3. 数组是一个构造类型,是集合的概念,因此不能整体引用数组里面的所用元素。企图简单地通过数组名b体代表其中的4个int类型的变量是不行。

注意:不能对数组进行整体引用,只能单独引用其元素。

int a[10];

int b[10]=a;/*错误的*/

int b[10]=a[10];/*错误的,没有元素a[10]*/

float a[10],b[10];

b=a;/*错误,a代表整个数组,不能整体引用*/

b[0]=a[0];b[1]=a[1];等

for(i=0;i<100;i++)

a[i]=b[i];

8.1.3一维数组的初始化

在定义一维数组的同时可以将各元素的初值依次放在一对{}中赋给数组,初值之间用逗号隔开。

例如:int a[10]={1,2,3,4,5,6,7,8,9,10};

int a[5]=1,2,3,4,5; 错

int a[5]={1;2;3;4;5}; 错

注意:

(1)若{}中的初值个数多于数组元素的个数(即数组长度),则出错;若初值个数少于数组元素的个数,则将初值依次赋给前面的元素,而未得到初值的元素自动赋零。

例如:int a[5]={1,2,3,4,5,6};

int a[5]={1,2,3};

int a[4]={2*2};

int a[3]={0};

(2)可以通过赋初值来定义数组的大小。此时数组的长度可以省略。若定义时,未赋初值,则长度绝不能省略。

例如:int a[ ]={1,2,3,4}; 数组的长度是4。

int a[ ]; 是非法的。

(3)只能在定义时可以用{}给数组整体赋值,不是定义时,则只能单独给每个数组元素赋值。

例如:int a[4];

a={1,2,3};或a[4]={1,2,3,4};是非法的。

int a[4]={1,2,3};

本节习题:

下列一维数组定义中正确的是(                 )。

A.int a[n];

B.int a[ ];

C.int a();

D.int ­ _abc[100*2];

E.int a[2]={1,3,4};

F.int a[0]={0};

G.int a[5]={0};

H.int a[5]; a[5]={123,456};

I.int a[5]; a={1,2,3,4,5};

J.int a[N=5];

K.{int n=5; int a[n];}

L.int a[2*3];

M.int a[3]={1,2,34};

8.2 二维数组

8.2.1二维数组的定义

格式:类型名 数组名[常量表达式1][常量表达式2],….

例如:int a[2][3];

a[0][0]a[0][1]a[0][2]
a[1][0]a[1][1]a[1][2]

在内存中的存放形式:(依次连续)

a[0][0]a[0][1]a[0][2]a[1][0]a[1][1]a[1][2]

8.2.2二维数组元素的引用

格式:数组名 [下标表达式1][ 下标表达式2]

注意:

1.不论是一维数组还是二维数组都不能整体引用。

例如:int a[3][4];

int b[3][4]=a;/*是非法的*/

int a[3][4]={0},int b,n=2;

b=a[2][n];

执行上述语句后,问b的值是多少?

2.引用数组元素时,下标可以是C语言中任何合法的表达式,且可以含有变量。

int a[2][3]={1,2,3,4,5,6};

int b;

b=a[10.5%5][2];/*错误*/

8.2.3二维数组初始化

1.直接赋值

int a[3][4]={1,2,3,4,5,6,7,8,9};

问a[2][0]的值是多少?9

   a[2][2]的值是多少?0

int a[2][2]={0,0,0,0,0};/*非法的*/

2.按行赋值

int a[3][3]={{1,2,3},{4,5,6},{7,8,9}};

注意:

1.其中里层的{}的对数不能多于行数。花括号内初值个数不能多于列数。不能出现空花括号{}对。

 int a[3][4]={{1,2,3,4},{5,6,7,8,9},{10,11,12,13}};

int a[3][4]={{1,2,3,4},{5,6,7,8,9},{10,11,12,13},{1,2}};

int a[3][4]={{1,2,3,4},{},{10,11,12,13}};

int a[3][4]={1,2,3,4},{5,6,7,8,},{10,11,12,13};

以上定义均是非法的。

2.若在定义二维数组的同时进行初始化,则定义时可以不写第一维的长度,第二维则不能省略。若定义时未赋初值,则各维的长度均不能省略。

例如:int a[ ][3]={1,2,3,5,4,6};

int a[ ][3];或int a[3][ ];都是非法的。

例:有如下程序

main( )

{int a[3][3]={{1,2},{3,4},{5,6}};

 int i,j,s=0;

 for(i=1;i<3;i++)

   for(j=0;j<i;j++)

    s+=a[i][j];

   printf(“%d\n”,s);

}

输出结果是?

三.试题分析

1.2008年4月考试试题分析

(24)以下错误的定义语句是

A)int x[][3]={{0},{1},{1,2,3}};

B)int x[4][3]={{1,2,3},{1,2,3},{1,2,3},{1,2,3}};

C)int x[4][]={{1,2,3},{1,2,3},{1,2,3},{1,2,3}};

D)int x[][3]={1,2,3,4};

(26)若有定义:int a[2][3];,以下选项中对a数组元素正确引用的是

A)a[2][!1] B)a[2][3] C)a[0][3] D)a[1>2][ !1]

(31)有以下程序

#include <stdio.h>

main()

{ int s[12]={1,2,3,4,4,3,2,1,1,1,2,3},c[5]={0},i;

for(i=0;i<12;i++) c[s[i]]++;

for(i=1;i<5;i++) printf(“%d”,c[i]);

printf(“\n”);

}

程序的运行结果是

A)1 2 3 4 B)2 3 4 4 C)4 3 3 2 D )1 1 2 3

2.2007年9月试题分析

(31)若有定义语句:int  a[3][6]; ,按在内存中的存放顺序,a数组的第10个元素是

       A)a[0][4]          B)a[1][3]           C)a[0][3]           D)a[1][4]

3.2007年4月试题分析

(13)设有定义语句:int a[][3]={{0},{1},{2}};,则数组元素a[1][2]的值为           

(14)执行以下程序的输出结果是 【18】 。

       #include   <stdio.h>

       main()

       {  int   i,  n[4]={1};

          for(i=1;i<=3;i++)

          {  n[i]=n[i-1]*2+1;  printf("%d ",n[i]);  }

       }

第八章  指针、数组与指针

一.教学重点、难点

知识点所占分值考核几率专家点评
指针变量的定义和引用2-360%简单识记
指针变量作为函数参数2-390%简单,重点掌握
指向数组元素的指针3-4100% 难度适中,重点掌握重点理解
用数组名作为函数参数2-390%难度适中,重点掌握
指向多维数组的指针3-4100%偏难,重点理解
返回指针值的函数1-280%简单,重点掌握

二.教学内容

1.变量的地址

内存中的每一个字节都有一个唯一的编号,这个编号就是该字节的地址。

int a=15,b=20;

15
 
20
 

2001

2002

2003

2004

变量的地址:是对应存储单元的首地址(起始地址)。那么a的地址就是2001,b的地址是2003.

2.指针变量

2.1指针:变量的地址就是该变量的”指针”,(指针就是地址,地址就是指针)。

2.2指针变量:用于存放变量地址的变量称为指针变量。

2.3指针变量的定义

格式:类型名 *指针变量名;

如:int *p;  int a,*q;

例1:int *p, a=20;

p=&a;

因为变量p存放了a的地址,所以p是指向a的指针变量。

例2:int *p=20; /*出错*/

int a=20,*p=a;/*出错,指针变量只能用于存放地址值*/

2.4指向指针变量的定义:

   格式:类型名  **指向指针变量名

   如:int **q;

   例:int *p,**q,a=5;/*我们定义了一个 int型的指针变量、一个int型的指向指针变量和一个int型的变量 */

2.5 指针变量的赋值:

   int *p, a=20;    或  int a=20,*p=&a;

p=&a;                           /*这两种赋值是等价的,第二种是定义的时候赋值,第一种形式是先定义后赋值,学生会对第二种形式有些模糊,老师一定要讲到位*/

int *p,**q,a=5;     或   int a=5,*p=&a,**q=&p;

p=&a,q=&p;/*我们必须知道,指针变量只能存取变量的地址或是和它相同类型指针的值。指向指针只能存取指针变量的地址。学生在学习的时候一定要让他们知道变量间的赋值必须是相同类型的才可以真确的赋值成功。*/

2.6 给指针变量赋“空值”

   P=NULL;

   NULL是在stdio.h头文件中的预定义符,因此在使用NULL时,应该在程序前面写上:#include “stdio.h”

   NULL的代码值是0,所以等价:p=0;或p=’\0’;

注意:当p指向NULL时候, p并不是指向地址为0的存储单元,而是具有一个确定的值“空”,如果通过一个空指针去访问一个存储单元,将会得到一个出错的信息。

3.对指针的操作

3.1引用存储单元

   除了取地址运算符“&”与指针变量有关外,C语言还有一个指针运算符(也叫间接访问运算符)“*”也与指针变量有关。

int a=20,*p=&a;

那么 a=*p,a++等价与(*p)++。这里*p意味着取指针变量指向变量的内容。

(1)指针变量定义中的“*”和间接访问运算符“*”有本质的区别。当定义一个指针变量的时候,“*”是说明一个变量是指针变量,而“*”作为间接访问运算符的时候意味着取指针变量所指向变量的内容。

(2)间接访问运算符必须出现在运算对象的左边,运算对象可以是地址或存放了地址的指针变量。

一.教学重点、难点

知识点所占分值考核几率专家点评
指向数组元素的指针3-4100% 难度适中,重点掌握重点理解
用数组名作为函数参数2-390%难度适中,重点掌握
指向多维数组的指针3-4100%偏难,重点理解
二级指针及指针数组1-390%偏难,重点掌握重点理解

二.教学讲点

1.一维数组与指针

(1)在C语言中,数组是占用一串连续的存储单元。数组中每个元素都可以看作一个变量,因此每个数组元素都有一个地址。

那么:int *p,a[5]={1,2,3,4,5};

指针p的基类型是int,数组a的各个元素也是int类型的。我们用p=&a[0],将指针p指向数据元素a[0]。由于数组元素在内存中是连续的,因此我们可以通过移动指针p来访问数组中的每一个元素。

(2)C语言规定数组名代表数组在内存中的起始地址,即可以用a表示数组a的首地址。因此p=a是让指针p指向数组a的起始地址。

(3)a是一个地址常量,它永远指向a数组的首地址。因此我们不能对a进行重新赋值。如:a=&I,a++都是错的。

  • 通过指针引用一维数组元素

(1)通过指针引用数组元素

     int *p,a[5]={1,2,3,4,5};             int *p,a[5]={1,2,3,4,5};

     p=&a[0];                             p=a;

   指针变量p指向数组元素a[0],          指针变量p指向数组元素a[0],

   因此可以用间接访问运算符“*”         因此可以用间接访问运算符“*”

   来引用变量a[0]。如:*p=10;是       来引用变量a[0]。如:*p=10;是

   对指针的存储空间赋值,即a[0]=10

   原来a[0]=1,那么通过指针赋值现在

   变成了10.

(2)通过数组的首地址引用数组元素

   int a[5];

   由于a是数组的首地址,我们把a当作一个指针常量。因此*a等价于a[0];

*(a+1)等价于a[0]。a等价于&a[0]。

(3)用带下标的指针变量引用一维数组元素

     int *p,a[5]={1,2,3,4,5};           

    p=a; 

    p[0]来表示a[0],p[1]来表示a[1]……

(4)对数组元素a[i]等价的引用方法:

a[i]; p[i]; *(a+i); *(p+i).

(5)补充

若指针变量P指向了一维数组a的首地址,即:int a[10]; int *p=a;

则有下面的等价关系:

(1)a+i等价于p+i,都是&a[i]。

(2)*(a+i) 等价于*(p+i) 都与a[i]相同

(3)a[i]等价于p[i]

(4)p++、++p、p+=1、p=p+1作用都是让p指向下一个元素。p--、--p、p-=1、p=p-1作用都是让p指向前一个元素。

(5)*p++与*(p++)等价,都是得到p当前所指向的元素的值,并让p指向下一个元素。*p--与*(p--)等价,都是得到p当前所指向的元素的值,并让p指向前个元素。

(6)*++p与*(++p)等价,都是先让p指向下一个元素,再取出重新指向的元素。*--p与*(--p)等价,都是先让p指向前一个元素,再取出重新指向的元素。

(7)(*p)++、++(*p)、++*p的作用都是让p当前所指的元素值增加1。(*p)--、--(*p)、--*p的作用都是让p当前所指的元素值减小1。

3.指向多维数组的指针和指针变量

int a[3][4];

a a+1 a+2  
a[0][0]a[0][1]a[0][2]a[0][3]
a[1][0]a[1][1]a[1][2]a[1][3]
a[2][0]a[2][1]a[2][2]a[2][3]

3.1.列指针:加1跳过一个元素的指针。

(如:一维数组名)

3.2.行指针:加1跳过一行的指针。

(如:二维数组名)

3.3.对列指针进行一次指针(下标)运算得到的是元素。

例如:int a[5]={1,2,3,4,5},*p=a;

 则a[3]等价于p[3]等价于*(p+3),都得到元素a[3]的值4。

3.4.对行指针进行一次指针(下标)运算得到的列指针(即元素的地址),而不是元素。若要通过行指针引用元素,必须进行两次指针运算或下标运算。

若a是一个二维数组,则有:

a+i是行指针,指向行号为i的一整行。

*(a+i)和a[i]等价,都是一个列指针,指向的是元素。都表示行号为i的最前面元素的地址,即&a[i][0]。

*(a+i)+j和a[i]+j等价,即&a[i][j]。

*(*(a+i)+j)、*(a[i]+j)、(*(a+i))[j] 和a[i][j]相同。

例.若有以下定义:

  float a[2][3];

 则对a数组元素非法引用的是(      )。

A.*(a[0]+2)   B.*(a+1)[2]  C.a[0][0]  D.*(a[1]+2)  E.*(a[1]+3)   F.(*(a+1))[2]

4.指向多维数组元素的指针变量

指向多维数组元素的指针变量的定义和引用与指向普通变量的指针变量的定义和引用的方法一样。

例如:int a[3][4];

int *p=&a[1][2];

则:

表达式所指元素
P+1a[1][3]
P+2a[2][0]
P+4a[2][2]

常用于取二维数组a元素地址的方式:&a[i][j] 、a[i]+j、*(a+i)+j

5.指向由m个元素组成的一维数组的指针变量

它是一个行指针,对它加1要跳过m个元素。

而指向一维数组的指针变量是一个列指针。对它加1跳过1个元素。

定义格式:

基类型 (*指针变量名)[m];

定义后该指针变量与具有m列的二维数组名具有相同的性质,即该指针变量可以指向一个具有m列的二维数组。通过该指针变量名引用二维数组元素时,引用方式与通过二维数组名的引用方式一样。

int a[5][7];

int (*p)[7];

p=a;

此时p[0][0]与a[0][0]对应 

p[4][3]与a[4][3] 对应

char b[10][80];

char (*r)[80];

r=b+5;

例1.请分析r[0][0]和r[2][3]分别对应的元素是             和                 。  

例2.若有int t[3][2];能正确表示t数组元素地址的表达式是( )。

A.&t[3][0]  B.t[3]  C.t[1]  D.*t[2]

6.指针数组

定义格式:

类型名 *数组名[常量表达式];

例如:

int a[10];普通数组

int *a[10];指针数组

int (*a)[10];指向由10个元素组成的一维数组的指针变量

int (*a)();指向函数的指针变量

int *a()返回指针值的函数

{ … }

注意:

1.指针数组的每一个元素都是指针类型,即它的每一个元素相当于一个指针变量。

2.指针数组的数组名是一个行指针。

以下程序的输出结果是

main()

{char ch[3][4]={“321”,”654”,”212”},*q[3];

int i;

for(i=0;i<3;i++) q[i]=ch[i];

for(i=0;i<3;i++) printf(“%s”,q[i]);

}

有下列语句

float (*a)[6],*b[6];

则sizeof(a)、sizeof(b)的值各是?结果:4,24

int a;     int a[10];

int *a;    int *a[10];

三.试题分析

1.2008年4月试题分析

(9)以下程序段的定义语句中,x[1]的初值是【9】,程序运行后输出的内容是【10】。

#include<stdio.h>

main()

{ int x[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16},*p[4],i;

for(i=0;i<4;i++)

{ p[i]=&x[2*i+1];

printf(“%d ”,p[i][0]);

}

printf(“\n”);

}

(11)以下程序的输出结果是【12】。

#include<stdio.h>

main()

{ int a[5]={2,4,6,8,10}, *p;

p=a; p++;

printf(“%d”,*p);

}

2.2007年9月试题分析

(31)若有定义语句:int  a[3][6]; ,按在内存中的存放顺序,a数组的第10个元素是

       A)a[0][4]          B)a[1][3]           C)a[0][3]           D)a[1][4]

(33)若有定义语句:int  a[2][3],*p[3]; ,则以下语句中正确的是

       A)p=a;             B)p[0]=a;          C)p[0]=&a[1][2];     D)p[1]=&a;

(34)有以下程序

       #include   <stdio.h>

       void  fun(int  *a, int  n) /* fun函数的功能是将a所指数组元素从大到小排序 */

       {  int   t, i, j;

          for (i=0; i<n-1;i++)

            for (j=i+1; j<n; j++)

              if (a[i]<a[j])  {  t=a[i]; a[i]=a[j]; a[j]=t;  }

       }

       main()

       {  int   c[10]={1,2,3,4,5,6,7,8,9,0},i;

          fun(c+4, 6);

          for (i=0;i<10; i++)  printf("%d,", c[i]);

          printf("\n");

       }

程序的运行结果是

       A)1,2,3,4,5,6,7,8,9,0,                          B)0,9,8,7,6,5,1,2,3,4,

       C)0,9,8,7,6,5,4,3,2,1,                          D)1,2,3,4,9,8,7,6,5,0,

3.2007年4月试题分析

(36) 有以下程序
void f(int  *q)
{int i=0;
for( ; i<5;i++)(*q)++;
}
main()
{int a[5]={1,2,3,4,5},i;
f(a);
for(i=0;i<5;i++)printf(“%d,”,a[i]);
}
程序运行后的输出结果是( )
A)2,2,3,4,5,     B)6,2,3,4,5,    C)1,2,3,4,5,      D) 2,3,4,5,6,

(16)以下程序的输出结果是       
int fun(int*x,int n)
{  if(n==0)  return x[0];
else        return x[0]+fun(x+1,n-1);
}
main()
{int  a[]={1,2,3,4,5,6,7}; printf(“%d\n”,fun(a,3));}

字符串

1.字符串常量

用一对双引号括起的若干个字符,可以0个字符,若为0个字符,则称为空串(” ”)。

例如:“I LOVE YOU” 

“A”和’A’区别

注意:

(1)没有字符串变量,不能将一个字符串赋给一字符变量。字符串要用字符数组来存放。

例如:char a=”A”; 不合法

char a[]=”A”; 合法

char a=’A’; 合法

(2)每一个字符串的末尾都有一个字符串结束符’\0’,在书写时可写可不写,一般不写。

例如:“china”  和“china\0” 是等价的。

2.字符数组

2.1.字符数组的定义方法和普通数组一样,只是将类型名改为char。

2.2.三个标号的区别

0:数值0

‘\0’:字符,其ASCII码值为0。

‘0’:是0字符,其ASCII码值为48。

注意:

(1)在定义字符数组时,可以用字符串的形式给数组初始化,且{}可以省略。也可以将字符串拆成单个字符后依次放在一对花括号中给数组初始化。

char s[]={“china”};

char s[]=“china”;

char s[]={’c’,’h’,’i’,’n’,’a’,’\0’};

char s[6]={“china”};

char s[6]={’c’,’h’,’i’,’n’,’a’};

/*其中最后一个元素自动赋0即’\0’*/

char a[5]=”china’’;/*是非法的,没有元素存放’\0’*/

(2)注意区别以下几种定义方式

1)char a[]=”abcd”;

abcd\0

数组a共有5个元素,正确存放了字符串“abcd”。

2)char a[]={’a’,’b’,’c’,’d’};

abcd

数组a共有4个元素,不能正确存放字符串“abcd”。

3)char a[]=”abc\0cd\0”;

abc\0cd\0\0

数组a共有8个元素,正确存放了字符串”abc”。

4)char a[]={’a’,’b’,’c’,’\0’,’c’,’d’,’\0’};

abc\0cd\0

数组a共有7个元素,正确存放了字符串”abc”。

3.字符数组的输入输出

(1)用%s格式输入输出时,输入列表和输出列表均必须是用于存放字符串的起始地址(如字符数组名)。

char  a[10];

scanf(“%s”,a);/*数组名前,不能加地址运算符(&)*/

printf(“%s”,a);

scanf(“%s”,&a);/*错误*/

(2)用%s格式在输入时,遇到空格符或回车符就表示结束输入;输出时,遇到串结束符’\0’表示结束。

例如:char a[5];scanf(“%s”,a);

若输入:ab空格cd回车,则数组a的值是“ab”。

char a[10]=”abc\0823\0”;

printf(“%s”,a);

输出结果是:abc

(3)在scanf语句中,两个相邻的%s格式之间不能有其他字符。

例如:scanf(“%s,%s”,a,b);/*不能正确读取数据*/

(4)若定义的数组长度比输入的字符个数小,则会出错。

例如:char a[4];

scanf(“%s”,a);

若输入:abcde<回车>,则出错。

4.字符串的指针和指向字符串的指针变量

字符串在内存中所占的连续的存储单元的首地址,称为字符串的指针。

abcde\0

char *p=”abcde”;

/*将字符串”abcde”的首地址赋给指针变量p*/

p+2指向字符’c’。

char a[10];

a=”abcde”;/*出错*/

5.字符串处理函数

#include”string.h” 用于字符串处理函数

#include”stdio.h” 用于标准输入输出函数

5.1.puts 函数

格式:puts(字符数组)

功能:在屏幕上输出字符数组中的字符串。

注意:该函数输出与%s格式输出一样,只是该函数输出会自动将串结束符转为换行输出。

例如:puts(“abc”); puts(“abc”);

输出结果:abc

          abc

printf(“%s”,”abc”); printf(“%s”,”abc”);

输出结果:abcabc

char a[10]=”abde”;

puts(a);

输出结果:abde

5.2.gets( )函数

格式:gets(字符数组)

功能:从键盘读取一个字符串赋给字符数组。

注意:用gets函数输入字符时,只有遇到回车符才结束接收字符。(与%s格式不同)。

例如:char a[10];        char b[10];

     gets(a);      scanf(“%s”,b);

对上面两个程序段,输入时均输入:

ab空格cd回车

则a的内容是:ab空格cd  b的内容是:ab

5.3.strcat()函数

格式:strcat(s1,s2);

功能:将字符串s2连接到字符串s1的末尾,并自动覆盖s1末尾的’\0’;

例如:char a[18]=”yunnan”;

char b[10]=”china”;

strcat(a,b);

执行上述语句后:数组a的内容是:

“yunnanchina”

char s1[10]=”abcd\0\0efg”;

char s2[10]=”123\089”;

strcat(s2,s1);

s1:

abcd\0\0efg\0

s2:

123\089\0\0\0\0

执行了strcat(s2,s1);语句后:

123abcd\0\0\0

注意:字符数组1的长度必须大于等于字符数组1和字符数组2中存放的字符串的长度之和。

5.4.strcpy()函数

格式:strcpy(s1,s2);

功能:将s2中的字符串复制到s1中。最后s1和s2中的字符串一样。

例如:char s1[10]=”123456”;

char s2[10]=”abc”;

strcpy(s1,s2);

s1:

1(a)2(b)3(c)4(\0)56\0\0\0\0

s1=s2;/*非法的,不能整体赋值*/

5.5.strcmp()函数

格式:strcmp(s1,s2)

功能:比较s1和s2两字符串的大小,并非比较长度。函数的返回值为两字符串中第一个不相同字符的ASCII码值之差,若差大于0,则s1大于s2,若差小于0,则s2大于s1,若差等于0,则s1和s2相等。

例如:strcmp(“abc”,”abc”) 值为:0

strcmp(“abc”,”abdc”) 值为:-1

strcmp(“abcdef”,”abd”) 值为:-1

“abd”大于“abcdef”。

strcmp(“abc”,ab”) 值为:99

注意:不能用关系运算符来直接进行字符串大小的比较。

“abc”==“abc”

“abd”>”abc”

/*均是非法的*/

例如:

 if(strcmp(s1,s2)>0)

  puts(s1);

 else

   puts(s2);

5.6.strupr()函数

格式:strupr(s1)

功能:将s1中所有的小写字符转成大写字母。

例如:char s[10]=”abcABC12”;

strupr(s);

puts(s);

结果是:ABCABC12

5.7.strlwr()函数

格式:strlwr(s1)

功能:将s1中所有大写字母转为小写。

例如:char s[10]=”abcABC12”;

strlwr(s);

puts(s);

结果:abcabc12

5.8.strlen()函数

格式:strlen(s1)

功能:求出s1中字符串的有效长度(不包括串结束符’\0’)。

例1:char a[10]=”swfc”;

printf(“%d %d”,strlen(a),sizeof(a));

4 10

5.10.sizeof() 操作符

sizeof是C语言的一种单目操作符,如C语言的其他操作符++、--等。它并不是函数。sizeof操作符以字节形式给出了其操作数的存储大小。操作数可以是一个表达式或括在括号内的类型名。操作数的存储大小由操作数的类型决定。 

格式:sizeof(s1)

功能:求出参数s1在内存中所占的字节数。

例1:printf(“%d,%d,%d”,sizeof(int),sizeof(double),sizeof(long));

4,8,4

例2:char a[]=”def\018\0”;

printf(“%d,%d”,strlen(a),sizeof(a));

def\018\0\0

例3:char a[10]=”ab0\tm\nd\015”;

printf(“%d,%d”,strlen(a),sizeof(a));

ab0\tm\nd\015\0\0