|
学习C语言的方法
2 L7 {; C" B* {- i/ j, @
$ `+ c' L, Q! u6 I/ K) u! G在初学C语言时,可能会遇到有些问题理解不透,或者表达方式与以往数学学习中不同(如运算符等),这就要求不气馁,不明白的地方多问多想,鼓足勇气进行学习,待学完后面的章节知识,前面的问题也就迎刃而解了,这一方面我感觉是我们同学最欠缺,大多学不好的就是因为一开始遇到困难就放弃,曾经和好多同学谈他的问题,回答是听不懂、不想听、放弃这样三个过程,我反问,这节课你听过课吗?回答又是没有,根本就没听过课,怎么说自己听不懂呢?相应的根本就没学习,又谈何学的好? + |4 L; E2 p* `3 L1 h( Q
& _- W, |; }8 _ y- Z6 r5 Y, U! u 学习C语言始终要记住“曙光在前头”和“千金难买回头看”,“千金难买回头看”是学习知识的重要方法,就是说,学习后面的知识,不要忘了回头弄清遗留下的问题和加深理解前面的知识,这是我们学生最不易做到的,然而却又是最重要的。学习C语言就是要经过几个反复,才能前后贯穿,积累应该掌握的C知识。
4 T- d! L: h% z V/ N5 o$ q+ q7 ~
那么,我们如何学好《C程序设计》呢? 6 j- J) W; T; l2 U z3 C& ~5 C% E" u
" f' a: e4 _, a/ M: C* X. K$ ?
一.学好C语言的运算符和运算顺序 7 B) K& ]3 j0 h
0 b" j) o! y8 L8 {; @& b6 @& |% t 这是学好《C程序设计》的基础,C语言的运算非常灵活,功能十分丰富,运算种类远多于其它程序设计语言。在表达式方面较其它程序语言更为简洁,如自加、自减、逗号运算和三目运算使表达式更为简单,但初学者往往会觉的这种表达式难读,关键原因就是对运算符和运算顺序理解不透不全。当多种不同运算组成一个运算表达式,即一个运算式中出现多种运算符时,运算的优先顺序和结合规则显得十分重要。在学习中,只要我们对此合理进行分类,找出它们与我们在数学中所学到运算之间的不同点之后,记住这些运算也就不困难了,有些运算符在理解后更会牢记心中,将来用起来得心应手,而有些可暂时放弃不记,等用到时再记不迟。
) w( h @4 \9 {4 J& m/ f# R. J3 }6 U- D: `6 {2 |& E J# K
先要明确运算符按优先级不同分类,《C程序设计》运算符可分为15种优先级,从高到低,优先级为1 ~ 15,除第2、13级和第14级为从右至左结合外,其它都是从左至右结合,它决定同级运算符的运算顺序. 2 ^/ J0 @- q6 R6 a0 X1 U8 C
2 ]6 G! l/ B' [6 g0 ^" f5 I 二.学好C语言的四种程序结构 - ~+ [1 w2 V$ N
: J; |, f+ i- g (1)顺序结构
5 i% p: J; o& v& S
/ c5 m6 G, A4 b! d+ p 顺序结构的程序设计是最简单的,只要按照解决问题的顺序写出相应的语句就行,它的执行顺序是自上而下,依次执行。 . H2 c: b; k2 U5 J
& e7 {) `6 p5 K) A x
例如;a = 3,b = 5,现交换a,b的值,这个问题就好像交换两个杯子水,这当然要用到第三个杯子,假如第三个杯子是c,那么正确的程序为: c = a; a = b; b = c; 执行结果是a = 5,b = c = 3如果改变其顺序,写成:a = b; c = a; b = c; 则执行结果就变成a = b = c = 5,不能达到预期的目的,初学者最容易犯这种错误。 顺序结构可以独立使用构成一个简单的完整程序,常见的输入、计算,输出三步曲的程序就是顺序结构,例如计算圆的面积,其程序的语句顺序就是输入圆的半径r,计算s = 3.14159*r*r,输出圆的面积s。不过大多数情况下顺序结构都是作为程序的一部分,与其它结构一起构成一个复杂的程序,例如分支结构中的复合语句、循环结构中的循环体等。 : e. K9 ^. \" A. ~5 N% D
6 k2 ~( Z$ U Q (2) 分支结构 / B d# Q5 p! u& r9 z& O
; N L, l& v* _' \6 S3 i 顺序结构的程序虽然能解决计算、输出等问题,但不能做判断再选择。对于要先做判断再选择的问题就要使用分支结构。分支结构的执行是依据一定的条件选择执行路径,而不是严格按照语句出现的物理顺序。分支结构的程序设计方法的关键在于构造合适的分支条件和分析程序流程,根据不同的程序流程选择适当的分支语句。分支结构适合于带有逻辑或关系比较等条件判断的计算,设计这类程序时往往都要先绘制其程序流程图,然后根据程序流程写出源程序,这样做把程序设计分析与语言分开,使得问题简单化,易于理解。程序流程图是根据解题分析所绘制的程序执行流程图。
, y/ e, v T/ l& W( |* O& y
8 @4 y6 Z: i" G1 u 学习分支结构不要被分支嵌套所迷惑,只要正确绘制出流程图,弄清各分支所要执行的功能,嵌套结构也就不难了。嵌套只不过是分支中又包括分支语句而已,不是新知识,只要对双分支的理解清楚,分支嵌套是不难的。下面我介绍几种基本的分支结构。 5 e. m. T" S3 \) W+ g
9 M7 i; d% [ J3 Z" ^2 Q2 z
①if(条件)
! m4 e+ R0 S U# r6 V
0 K0 t4 _' @3 @8 ]9 r. Y5 b {分支体} ; ^1 O% }+ h7 [: s
( V* F& V) Z8 S1 O+ b" Q 这种分支结构中的分支体可以是一条语句,此时“{ }”可以省略,也可以是多条语句即复合语句。它有两条分支路径可选,一是当条件为真,执行分支体,否则跳过分支体,这时分支体就不会执行。如:要计算x的绝对值,根据绝对值定义,我们知道,当x>=0时,其绝对值不变,而x<0时其绝对值是为x的反号,因此程序段为:if(x<0) x=-x;
' _. P: Z2 T# `6 s! D. z
$ j8 l" x( L3 O. W+ Y ②if(条件) + s+ S& j2 }) X
; E: \' [4 o/ H) c. z
{分支1}
' P8 V, e+ a" h8 I6 ?1 N9 {" F1 h! r; {* u1 D, \+ L2 X8 F) \
else : Z) E4 l h$ l. R4 t( G& u& H0 b
- k- @; `3 D" e/ ~ {分支2} a( U0 D7 f5 ^+ [1 ~' Q8 D* a/ L
8 K% l1 c1 ^; U, j9 `
这是典型的分支结构,如果条件成立,执行分支1,否则执行分支2,分支1和分支2都可以是1条或若干条语句构成。如:求ax^2+bx+c=0的根
( S, A b- J, A% |6 n6 M( A
) \* C. q) l9 i1 L0 v" m! } 分析:因为当b^2-4ac>=0时,方程有两个实根,否则(b^2-4ac<0)有两个共轭复根。其程序段如下: 9 s( m# R( l1 t) N, e! L# p2 }% g) x. T
9 Z$ S& P4 g4 s& j m6 [ d=b*b-4*a*c;
, }( V% T6 ]5 v- g v% D) I0 l1 |6 a9 P
if(d>=0)
9 ^- n7 \5 q& r- a; v3 N) S8 y; z8 u8 E \# ~3 q+ O& |" C" D$ u
{x1=(-b+sqrt(d))/2a;
. f/ n; _$ N2 [8 |- _4 t
L2 G; [4 X4 A) o x2=(-b-sqrt(d))/2a;
$ C$ x' k0 @+ o* m. E! |
7 Z1 k' w1 ?3 U printf(“x1=%8.4f,x2=%8.4f\n”,x1,x2);
1 O9 W# S( Z1 `
. E0 G1 u% q2 J; Q3 |! ^ Y } # \5 ]7 j; p" }6 _) |
# Y: d8 i5 y$ H else ; b( ]' g1 e7 }6 g' c
7 r) d1 p8 X8 K% |
{r=-b/(2*a); @! W" _) f6 t3 \& g3 o
5 X8 K# S3 l4 x) }6 v i =sqrt(-d)/(2*a);
) @: ^6 N- I6 [* ?8 o4 R
2 O6 r/ x G& h+ E printf(“x1=%8.4f+%8.4fi\n”r, i);
s; \- x$ K9 y
7 w% b7 q8 w# R3 t, O printf(“x2=%8.4f-%8.4fi\n”r,i) : Z' U* Z* S8 X5 s' S
$ _1 Q% K/ y a& E s: r- T }
( F+ Q3 E' @5 b
4 w) O2 D: C& P. _) ^: { ③嵌套分支语句:其语句格式为:
' q: Y5 R+ N* }% U4 F) ~
b3 P( w2 H0 a& c, h7 O if(条件1) {分支1}; + C& Z0 ]) q" e! y' N
: G) c" x" K: d else if(条件2) {分支2}
, C: f3 f0 p- O- m" @
0 N" l2 v" U/ o else if(条件3) {分支3} & f& C$ R! |: k" X3 V6 C- I* Q
2 n1 Q/ @' m+ ?9 v+ r …… ; i9 W N% x- H h6 `
% i7 ]5 C8 p. R
else if(条件n) {分支n}
- y8 P! m# @9 M8 x5 J& q2 f2 w, n. S7 ^" _6 A& {9 i; X& Y
else {分支n+1}
* }% I- @) } `- r# P" ?8 T- j+ M" }6 T: f% s' u T% z) ]; R( v/ Z) E8 C
嵌套分支语句虽可解决多个入口和出口的问题,但超过3重嵌套后,语句结构变得非常复杂,对于程序的阅读和理解都极为不便,建议嵌套在3重以内,超过3重可以用下面的语句。
9 J0 G" V. r3 |) v2 G* Z: m
5 S; I$ x) K/ g: o- [) t/ z ④switch开关语句:该语句也是多分支选择语句,到底执行哪一块,取决于开关设置,也就是表达式的值与常量表达式相匹配的那一路,它不同if…else 语句,它的所有分支都是并列的,程序执行时,由第一分支开始查找,如果相匹配,执行其后的块,接着执行第2分支,第3分支……的块,直到遇到break语句;如果不匹配,查找下一个分支是否匹配。这个语句在应用时要特别注意开关条件的合理设置以及break语句的合理应用。 @/ D$ O9 _$ v2 L" p) l( V/ a
8 q$ X0 B5 U. B: ~ (3)循环结构:
! B# |; b; O( H3 F& h
3 B) z/ {, M; Q) i 循环结构可以减少源程序重复书写的工作量,用来描述重复执行某段算法的问题,这是程序设计中最能发挥计算机特长的程序结构,C语言中提供四种循环,即goto循环、while循环、do ?Cwhile循环和for循环。四种循环可以用来处理同一问题,一般情况下它们可以互相代替换,但一般不提倡用goto循环,因为强制改变程序的顺序经常会给程序的运行带来不可预料的错误,在学习中我们主要学习while、do…while、for三种循环。常用的三种循环结构学习的重点在于弄清它们相同与不同之处,以便在不同场合下使用,这就要清楚三种循环的格式和执行顺序,将每种循环的流程图理解透彻后就会明白如何替换使用,如把while循环的例题,用for语句重新编写一个程序,这样能更好地理解它们的作用。特别要注意在循环体内应包含趋于结束的语句(即循环变量值的改变),否则就可能成了一个死循环,这是初学者的一个常见错误。
2 d5 v, m; c' T# J3 D5 l8 ]
: d" e/ \- M; y7 g9 O 在学完这三个循环后,应明确它们的异同点:用while和do…while循环时,循环变量的初始化的操作应在循环体之前,而for循环一般在语句1中进行的;while 循环和for循环都是先判断表达式,后执行循环体,而do…while循环是先执行循环体后判断表达式,也就是说do…while的循环体最少被执行一次,而while 循环和for就可能一次都不执行。另外还要注意的是这三种循环都可以用break语句跳出循环,用continue语句结束本次循环,而goto语句与if构成的循环,是不能用break和 continue语句进行控制的。
/ _$ E: Y5 s# p& J
2 R" Q% n: a; J& c. S( q 顺序结构、分支结构和循环结构并不彼此孤立的,在循环中可以有分支、顺序结构,分支中也可以有循环、顺序结构,其实不管哪种结构,我们均可广义的把它们看成一个语句。在实际编程过程中常将这三种结构相互结合以实现各种算法,设计出相应程序,但是要编程的问题较大,编写出的程序就往往很长、结构重复多,造成可读性差,难以理解,解决这个问题的方法是将C程序设计成模块化结构。 : ~, x5 ?$ ~6 h6 s* c% m s
# x+ l& L: B0 L6 R5 b (4)模块化程序结构 - i% E" `& Y; g9 g% p
1 N+ h8 E+ S, @) c C语言的模块化程序结构用函数来实现,即将复杂的C程序分为若干模块,每个模块都编写成一个C函数,然后通过主函数调用函数及函数调用函数来实现一大型问题的C程序编写,因此常说:C程序=主函数+子函数。 因此,对函数的定义、调用、值的返回等中要尤其注重理解和应用,并通过上机调试加以巩固。 8 K0 {# ?0 c& \$ a
5 c5 m# _* N6 A 三.掌握一些简单的算法
1 O+ q. l! R* i/ I5 y2 W9 N+ a& D% q; g
编程其实一大部分工作就是分析问题,找到解决问题的方法,再以相应的编程语言写出代码。这就要求掌握算法,根据我们的《C程序设计》教学大纲中,只要求我们掌握一些简单的算法,在掌握这些基本算法后,要完成对问题的分析就容易了。如两个数的交换、三个数的比较、选择法排序和冒泡法排序,这就要求我们要清楚这些算法的内在含义 , x4 R5 j, q+ ?. ~5 W
( `5 z7 V# U% g+ D 结语:当我们把握好上述几方面后,只要同学们能克服畏难、厌学、上课能专心听讲,做好练习与上机调试,其实C语言并不难学 9 c) S3 C. S: Q2 q. Z) t: D% f/ z" V
/ K9 l- a% ~. @3 n# H3 B
C源程序的关键字--------------------------------------------------------------------------------------- 9 c& L; O/ @4 J4 k- _
b; T- k0 M% g
所谓关键字就是已被C语言本身使用, 不能作其它用途使用的字。例如关键字不能用作变量名、函数名等
' _' C+ ^6 d, m! @$ L. J
6 e @3 l p$ n+ u 由ANSI标准定义的C语言关键字共32个 : 2 r b6 c3 W& A- x- N. H
% z4 Y9 w. b; c* _! n1 A5 R. ^ auto double int struct break else long switch % Z) V- D+ x+ I
2 w* f3 d, i+ o: L" x
case enum register typedef char extern return union
+ |( ~% X* _- F! g4 l- Q4 H0 s) Y
: x D, [/ b4 N2 u$ x4 Y1 Y: Y; x const float short unsigned continue for signed void
. ]. q! k' {" o2 O: l i- O1 S, P
default goto sizeof volatile do if while static & ~9 ^8 e9 {9 H. J! @/ {
8 E+ F" r3 i6 A" E- R 根据关键字的作用,可以将关键字分为数据类型关键字和流程控制关键字两大类。 6 e0 K3 w* s! B% w3 c" ]$ ^
( d3 C- D* ?2 [& W/ Z! t 1 数据类型关键字
) Q9 U* H G( k3 U( ?3 K6 _
6 N( s3 \# |& Y5 G$ L4 \ A基本数据类型(5个) . X* `- m8 R" E+ K' V
0 F" Y$ d" j' L9 }, k
void :声明函数无返回值或无参数,声明无类型指针,显式丢弃运算结果 6 T* D7 V0 N' d i9 |4 n
- n _$ }4 D5 P5 w/ q char :字符型类型数据,属于整型数据的一种 * `" H. D9 S5 W/ A q9 {1 s
5 e# ^2 m) x& Z/ _ D# a int :整型数据,通常为编译器指定的机器字长
, U6 O( k- T3 ^& x) n: P3 B( F- [5 M1 N6 m; ~( G; C
float :单精度浮点型数据,属于浮点数据的一种 / {5 ^0 m" L! v6 A8 h
, z3 q# G7 r1 J
double :双精度浮点型数据,属于浮点数据的一种
$ [* K2 d6 C, ?
% G1 T! q: w* a+ { B 类型修饰关键字(4个)
' E; I! @( Z" X- \6 ^( X" `# ]3 R8 k7 Y3 @+ S% b, p
short :修饰int,短整型数据,可省略被修饰的int。 8 G; f$ l& w6 J/ \$ u/ ]2 R
( F8 `- N7 d, P% ~
long :修饰int,长整形数据,可省略被修饰的int。
" _) e# ~% e8 p' z5 D# j0 M: f: B" _4 b- H6 B6 d. S: A2 p
signed :修饰整型数据,有符号数据类型
0 g. `4 t' H, C4 B
+ r# p( j7 m8 O7 `; P! r4 q- ?# o unsigned :修饰整型数据,无符号数据类型
* P; F& y2 v( a+ W- D8 K
8 h& r6 e8 g7 F$ d1 B& Y C 复杂类型关键字(5个) 9 F2 W) z9 ^5 @7 W* I8 n3 q, s
( E& G, P0 O9 j2 `$ P struct :结构体声明 % U$ p* C6 v; e* Z0 T
E% R, L- o* u c( _. |0 x; f
union :共用体声明 ) R7 T; o0 j* r! z
( _) z, s! D: _9 F enum :枚举声明
6 K6 g0 Y9 E0 F2 w$ t9 M- S3 ]1 ~2 B Y$ H" H, X
typedef :声明类型别名 $ J1 u% v9 F# q
4 X/ z/ {. R: l, m3 u1 R sizeof :得到特定类型或特定类型变量的大小 # G- H* L5 g, z0 V8 D! o
, `( c/ V7 Y( m
D 存储级别关键字(6个) " |2 C( a& @3 Y d0 C! X
8 S2 Q3 ^/ {! H6 t" c$ r0 h8 I auto :指定为自动变量,由编译器自动分配及释放。通常在栈上分配 1 m* E: T9 Q; b4 n
7 b( d, Y! Q% b static :指定为静态变量,分配在静态变量区,修饰函数时,指定函数作用域为文件内部 8 V, ?/ g" _ I% w _) V' C4 N
) i5 M6 i. h% X register :指定为寄存器变量,建议编译器将变量存储到寄存器中使用,也可以修饰函数形参,建议编译器通过寄存器而不是堆栈传递参数
. o2 A8 I6 c; H i; O1 Q
8 }: m2 s/ F/ j7 |* }/ p' [$ e extern :指定对应变量为外部变量,即标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义。 ! u! v4 h* F: F- B) m$ I2 }
: O+ P9 P: b5 y: { const :与volatile合称“cv特性”,指定变量不可被当前线程/进程改变(但有可能被系统或其他线程/进程改变) 4 i1 O5 M& n U: i3 I
: L, j7 N6 P( H6 V, r. k volatile :与const合称“cv特性”,指定变量的值有可能会被系统或其他进程/线程改变,强制编译器每次从内存中取得该变量的值 4 G5 z5 @9 b$ u# M. Z s2 B& F6 L
4 f* X3 i. q& G5 Q1 V1 q) _ 2 流程控制关键字
, }" o8 a; x# t/ m8 b
3 b) E3 x1 h8 m! D8 a2 S) ~7 Q A 跳转结构(4个) 3 e4 k" W( q7 ]/ V4 |" ]1 ~
- \' ^* x4 [7 t1 [$ H& V- _5 K; {
return :用在函数体中,返回特定值(或者是void值,即不返回值) 0 N* Z, }2 D9 t, }7 w. M! m
6 ]6 s1 d8 T: }
continue :结束当前循环,开始下一轮循环 ( v" G9 s; r. E4 g# ^
7 Q2 n1 b+ r1 d/ t
break :跳出当前循环或switch结构 9 z. ]% o2 U9 {" r' q' b+ j% Z
$ ^* U) M' ^- i9 V0 ^2 O5 p
goto :无条件跳转语句
2 X4 l1 p7 P1 s) d8 z" S W3 s! F
B 分支结构(5个) - }" n; ^4 ^0 e8 _ X1 E; d; Z
4 d& ?! o( X- h. q1 d. y$ L
if :条件语句
7 z9 x9 b. U' F0 K" x% ?# B; u/ v% {: j; ^
else :条件语句否定分支(与if连用) 2 q: W0 _& v/ _1 Z# ~( W- D8 s* s
4 F! U8 B1 i% V8 T
switch :开关语句(多重分支语句)
+ I3 W5 t" B6 W% J2 o
5 `6 F5 o4 r" J" h case :开关语句中的分支标记
: `: L6 W/ S6 A9 a7 V$ B
& _$ v2 u# M. o, B8 E/ H, o+ `. f default :开关语句中的“其他”分治,可选。 4 W6 L# V; n* o3 J' {0 m% c+ _
2 y6 J% N- i# p5 d- x* N4 ` C 循环结构(3个)
`1 a S9 S- v1 _; B7 Z7 F2 r! s9 Z* y' R
for :for循环结构,for(1;2;3)4;的执行顺序为1->2->4->3->2...循环,其中2为循环条件
6 D4 ?# |- b( a$ S. a
4 _8 C; N1 f6 c7 Y6 Q' t do :do循环结构,do 1 while(2); 的执行顺序是 1->2->1...循环,2为循环条件
6 I- ^/ L( w- l5 f) _2 c
2 Y9 u8 H6 D4 W# z$ A) Z' O+ G while :while循环结构,while(1) 2; 的执行顺序是1->2->1...循环,1为循环条件 1 Z+ A! m$ u4 c$ M1 m* r
) T# } @: N9 Q# A
以上循环语句,当循环条件表达式为真则继续循环,为假则跳出循环。 |
评分
-
查看全部评分
|