? 第一章 C语言概述
? 第二章 数据类型、运算符与表达式
? 第三章 最简单的 C程序设计
? 第四章 逻辑运算和判断选取控制
? 第五章 循环控制
? 第六章 数组
? 第八章 编译预处理
? 第九章 指针
? 第十章 结构体与共用体
? 第十二章 文件的基本操作
? 第十三章 位运算
§ 6.3 字符数组
6.3.1字符数组的定义
类型名 数组名 大小
1,初始化,
? 直接给出字符串中的各字符
static char a[4]={' G ',' o ',' o ',' d '};
存放字符数据。字符串 –––用字符数组存放。
char c[10];
若字符多于元素个数,则语法错,反之,后而补 "\0"
?可以缺省数组的大小,通过自动赋值决定长度 (大小 )
static char x[ ]={'c ','_ ','L ','a ','n','q ','u ','a ','g ','e '};
数组长度为 10,相当于,
char x[0]= ' c '; char x[5]= ' q ';
char x[1]= ' _ '; char x[6]= ' u ';
char x[2]= ' L '; char x[7]= ' a ';
char x[3]= ' a '; char x[8]= ' g ';
char x[4]= ' n '; char x[9]= ' e ';
? 字符串常量用双引号,” 括起来,且由‘ \0’结尾。
static char x[ ]={"C_language"};
或, static char x[ ]="C_language";
2,字符数组的引用
每一个字符数组元素相当于一个字符变量。
数组长度为 11,相当于,
char x[0]= ' c '; char x[5]= ' q ';
char x[1]= ' _ '; char x[6]= ' u ';
char x[2]= ' L '; char x[7]= ' a ';
char x[3]= ' a '; char x[8]= ' g ';
char x[4]= ' n '; char x[9]= ' e ';
char x[10]= '\0';
格式符, %c –––逐个输入 /输出字符。
%s ––– 整个串一次输入 /输出。
1,输出 (用 %s)
?用 %s输出时,不输出‘ \0’,
? 在 printf中须直接写数组名,
static char c[ ]={"I am a student"};
printf("%s",c);
6.3.2 字符数组的输入输出
? 若数组长度大于字符串长度,则遇到‘ \0’
即停止输出
static char c[10]=" china";
printf(" %s",c);
? 输出时遇到第一个‘ \0’即结束。
2,输入 (用 %s)
? 输入多个字符串,可用空格隔开。
Static char str1[5],str2[5],str3[5];
scanf(" %s%s%s",str1,str2,str3);
? 输入字符串时,系统自动加上‘ \0’
则,输入 How are you?
str1,H o w
str2,a r e
str3,y o u
输入, How are you ? 则只会将 How输入,且存为
? scanf中须用地址量,数组名表示地址量。
str,H o w \0 ……
但若, static char str[13]
scanf("%s",str);
#include <stdio.h>
main( )
{ char name[13];
int i;
for (i =0; i <=12; i ++)
scanf(,%c”,&name[i]);
for (i =0; i <=12; i ++)
printf(,%c”,name[i]);
scanf(,%s”,name);
printf(,%s”,name);
}
例 1,采用不同的方式输入输出字符串
运行结果,
Pear & Apple ?
Pear & Apple
Pear & Apple ?
Pear
? scanf中须用地址量,数组名表示地址量。
/*pro10_12.c*/
#include <stdio.h>
#include <conio.h>
main( )
{int i;
char name[7][4]=
{"sun","mon","tue","wed","thu","wen","sat"};
printf("Result is:\n");
name[0][3]='&'; name[2][3]='&'; name[5][3]='&';
for (i=0;i<7;i++)
printf("%s\n",name[i]);
getch();
}
例 2,字符串数组值的改变。
程序运行结果,
sun&mon
mon
tue&wed
wed
thu
wen&sat
sat
N A M E[0] S U N
\0
N A M E[1] M O N
\0
N A M E[2] T U E
\0
N A M E[3] W E D
\0
N A M E[4] T H U
\0
N A M E[5] F R I
\0
N A M E[6] S A T
\0
N A ME [0 ] S U N
&
N A ME [1 ] M O N
\0
N A ME [2 ] T U E
&
N A ME [3 ] W E D
\0
N A ME [4 ] T H U
\0
N A ME [5 ] F R I
&
N A ME [6 ] S A T
\0
赋初值,
改变后,
6.3.3 字符串处理函数
用于处理字符串运算的函数,放在头文件 string.h中
如, strcpy-------字符串拷贝
strcat-------字符串连接
strcmp------字符串比较
等等。
6.3.4 字符串数组举例
例 1,字符串复制。
/*pro10_13.c*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
main()
{ int i;
char name1[6]={"pear"};
char name2[13]={"Apple&Banana"};
printf("Result is:\n");
printf("1---%s\n",name2);
strcpy(name2,name1); /*将 name1中的字符串连同 \0一
起复制到 name2*/
printf("2---%s\n",name2);
for (i=0;i<11;i++)
printf("%c",name2[i]);
getch( );
}
连接后,
连接前,Name1= p e a r \0
Name2= A p p l & B a n a n a \0 e
Name1= p e a r \0
Name2= p e a r & B a n a n a \0 \0
程序运行结果,
Result is,
1---name1---pear
1---name2---Apple&Banana
2---name1---pear
2---name2---pear
pear &Banana
例 2,字符串连接。
/*pro10_14.c*/
#include <stdio.h>
#include <conio.h>
#include <string.h>
main()
{ int i;
char name1[13]={"pear"};
char name2[6]={"apple"};
printf("Result is:\n");
printf("1---%s\n",name1);
strcat(name1,name2); /*将 name2中的字符串连接到 name1*/
printf("2---%s\n",name1);
for (i=0;i<13;i++)
printf("##%c",name1[i]);
printf("\n---------------\n");
for (i=0;i<13;i++)
printf("#%d",name1[i]);
getch();
}
程序运行结果,
Result is,
1---pear
2---pearapple
##p##e##a##r##a##p##p##l##e## ## ## ##
---------------
#112#101#97#114#97#112#112#108#101#0#0#0#0
例 3,输入一行字符,统计其中有多少个单词,单
词之间用空格分隔开。
# include "stdio.h”
main ( )
{ char c,string[81];
int i,num=0,word=0;
gets (string);
for (i=0; (c=string[i]!= '\0 '; i++)
if ( c= = ' ')word=0;
else if (word = =0)
{ word=1;
num++; }
printf("There are %d words in the line \n ",num);
}
运行情况如下,
I am a boy?
There are 4 words in the line
目的, 为了简化程序的编写, 提高程序的可
移植性, 可读性, 模块化 。 C语言设
计了若干命令 –––编译预处理命令,
并可出现于程序当中 。
处理流程, 第一次编译扫描时,将预编译命令处理完,
然后再进行正式编译,生成目标代码。
1,宏定义命令 ;
有三种类型的预处理命令,
为了与 C语句区别,这些命令均以,#”开头。
2,文件包含命令 ;
3,条件编译命令。
§ 8.1 宏定义
简化程序的书写,提高可读性、可移植性。
一、无参数形式
# define 标识符 字符串表达式
宏定义分为, 无参数 和 有参数 二种形式。
例, #define PAI 3.14159
#define Array_size 500
?
int m[Array_size];
实际处理时,
用,字符串表达式”替换程序中的标识符 (宏名 )
相当于,int m[500];
从开始定义的位置至文件结尾,但允许提前终
止。用命令 (#undef标识符 )
#define M 10.5
?
main ( )
{ ?
# undef M
?
}
1,宏定义的作用域,
作用域范围
/*----exp11_3.c---*/
# include <stdio.h>;
# define PAI 3.14159
main( )
{ float r,s;
r=2.0;
s=PAI?r?r;
printf("s=%5.3f\n",s);
#undef PAI
r=3.0;
s=PAI?r?r;
prinft("s=%5.3f\n",s);
}
运行结果, s=12.566
s=28.274
如果在程序中提前终止宏定义,则编译时会提示,
undefined symbol 'PAI' in function main
#define PI 3.14159
#define R 3.0
#define L 2?R ?PI
#define S PI ?R ?R
main
{
?
prinf("L=%f\n s=%f\n ",L,S);
?
}
2,可以嵌套定义,即可引用已定义的宏名。
注意, 双引号,”中的 L不被替
换。
结论, ? 凡程序中常用到的字符序列,如,常数,公式,
均可用宏定义。
? 经常会改变的数据可用宏定义。
结果,
L=18.84954 /*L=2?3.0 ? 3.14159*/
S=28.27131 /*S=3.14159?3.0 ? 3.0*/
二、有参形式
形式, #define 宏名 (参数表 ) 字符串
#define S(r ) 3.14159 ?r ?r
?
S(3.0) /*相当于, 3.14159 ?3.0 ?3.0*/
S(4.0) /*相当于, 3.14159 ?4.0 ?4.0*/
?
合适于字符串表达式序列中有变化的字符,
将这部分字符可定义为参数。
例 1,?r2?3.1415?r ?r
为字符序列,但 r是可变的。
main()
{int x,y,b,z;
x=3;y=4;
b=x+y;
z=f(x+y);
}
编译后, z=f(x+y) 变成,
x+y*b
结果为, z=31
(这个结果有可能与初始设想不一致 )
初始想法有可能是,
若有,f(x+y) 则应有,(x+y)?b
若有,f(x+y+z) 则应有,(x+y+z)?b
例 2,#define f(a) a*b
1,宏展开实质为严格的字符替换,把参数看一种
,字符串”,所以定义宏时要考虑实参 (替换 )
的各种可能,防止出现二义性。
如程序例 1中,若有 #define s( r) 3.14159?r?r
?
则 S(a+b)的结果为, 3.14159?a+b?a+b
为避免出现错误的结果,可将 宏定义修改为,
#define S( r) 3.1415926?( r)?( r)
宏定义时必须注意以下几个方面,
2,宏定义与函数是完全不同的概念。
例, printf中经常有 " \n "," %d "或程序中经常有
printf(" please input a number ")等。则可用宏
定义代替,如,
3,灵活运用宏定义,可使程序书写简化,
# inclnde<stdio.h>
# define EN printf("please input number:\n")
#define NL printf(" \n")
#define PRINT(F,V) printf ("V=%d\t",V)
#define INPUT_ PROMPT printf("…")
/*---exp11_4.c---*/
#define PRINT1(F,X1) PRINT(F,X1); NL
#define PRINT2(F,X1,X2) PRINT(F,X2); NL
main ( )
{int a,b,c,d;
float e,f,g,h;
long i,j;
char n,m;
a=1; b=2; c=3; d=4;
e=1.5; f=2.5; g=3.5; h=4.5;
i=10; j=100;
n='x'; m='y'
PRINT(d,a);
PRINT1(d,a,);
PRINT2(d,a,b);
PRINT2(d,c,d);
PRINT2(f,e,h);
PRINT2(f,g,h);
PRINT2(ld,i,j);
PRINT2(c,n,m); }
printf("h=%f\n",h);
EN;
程序运行结果如下,
h=4.500000
Please input number,
V=1 V=1
V=2
V=4
V=0
V=0
V=100
V=121
程序使用了宏定义,各宏语句的对应关系为,
EN; //printf("pleas input number:\n")
PRINT(d,a); //printf("V=%d\t",a)
PRINT1(d,a); //printf("V=%d\t",a)
PRINT2(d,a,b); //printf("V=%d\t",b); printf("\n")
PRINT2(d,c,b); //printf("V=%d\t",d); printf("\n")
PRINT2(f,e,h); //printf("V=%d\t",h); printf("\n")
PRINT2(f,g,h); //printf("V=%d\t",h); printf("\n")
PRINT2(ld,i,j); //printf("V=%d\t",j); printf("\n")
PRINT2(c,n,m); //printf("V=%d\t",m); printf("\n")
程序中变量 c,e,f,g,h,i并没有被用到。
§ 8.2 文件包含
C语言允许在一个文件预编译时,将另一个文件
原封不动地包含进来。
? 当一组符号常量的定义为公用时,可作为一个
独立的文件被其它文件包含。
目的,
? 当函数不在一个文件中,既可用 link连接编译
后的 obj文件,也可用,文件包含”方式。
格式, # include "文件名 "
# include "f2.c "
?
main ( )
{ ?
}
例,
f1.c
f2.c
,
,
,
,
预编译后,
,
,
main ( )
{
?
}
f1.c
为 f2.c中的内容
?
再进行正式编译
1,一个 include只能写一个文件,包含多个文件需多
个 include
? 只在 f1.c中用 #include,
#include "f2.c"
#include "f3.c"
? 分别在 f1.c,f2.c中用 #include
在 f1.c中, #include "f2.c"
在 f2.c中, #include "f3.c"
2,当 f1.c包含 f2.c,而 f2.c又包含 f3.c时,有两种包含形式,
3,一般用,h扩展名命名被包含文件。 h为 head之意
以与一般,c文件区别。如系统 stdio.h.系统,h文件
在子目录 INCLUDE下。
4,#include后的文件名既可用 " ",也可用 < >,两者
区别,
,,首先在当前目录中找,然后再去标准目录中找。
< > 只在标准目录 (include目录 )中找。
5,被包含文件和包含文件最后形成一个文件。因此,
全局变量作用域为整个文件。不必用 extern说明。
§ 8.3 条件编译
有时,C程序的一部分语句是否起作用要根据一
定的条件,即由条件而决定是否起作用。
例如,
? 调试程序时,需加多条 printf,但调试完则要一
一删除。
? 有的语句也视条件而决定其具体形式。
形式 1 # ifdef 标识符
程序段 1
# else
程序段 2
# endif
功能 当标识符在此之前被定义过 (即用 #define定
义过 ),则编译程序段 1,否则编译程序段 2。
其中, 程序段即可为语句组,也可为命令行。
条件编译命令的三种形式,
例, 为了调试程序,加上以下条件编译
#ifdef DEBUG
printf("x=%d,y=%d,z=%d",x,y,z );
#endif
另, #else 后面部分可没有,但 #endif保留。
只要在此之前有,
# define DEBUG <任意字符 >
则编译 printf( x=%d,y=%d,z=%d",x,y,z);
例,/*---exp11_5.c---*/
# include<stdio.h>
# define EN printf("Please input number:\n")
main( )
{ int a=123,b=456;
#ifdef EN
prinft("This is test,a=%d\n",a);
#else
prinft("This is test,b=%d\n",b);
#endif
编译时会有警告,
'b' is assigned a value that is never used
运行结果, This is test,a=123
}
形式 2 #ifndef 标识符
程序段 1
#else
程序段 2
#endif
功能, 与形式 1的条件正好相反,即, 当标识符未
被定义,则编译程序段 1,否则编译程序
段 2。
例,/*---exp11_5.c---*/
# include<stdio.h>
# define EN printf("Please input number:\n")
main( )
{ int a=123,b=456;
#ifndef EN
prinft("This is test,a=%d\n",a);
#else
prinft("This is test,b=%d\n",b);
#endif
编译时会有警告,
'a' is assigned a value that is never used
运行结果, This is test,b=456
}
形式 3 #if 表达式
程序段 1
#else
程序段 2
#endif
功能, 当表达式 ?0,则编译程序段 1,否则编译程
序段 2。
例, 输入一任意字符串,需将其全部转化为大
写字母,或者将其转化为小写字母。
只编一个程序,程序中用条件编译,
决定是全部转为大写字母还是小写字母。
i=0;
while ( (c=str [i])!=' \o')
{
# if LETTER
if (c>= 'a' && c<=' z')
c=c–32; /*把所有的小写字符转成大写字符 */
#else
if (c>='A' && c<=' Z')
c=c+32;
#endif
printf(" str[%d]=%c",i,c);
i++;
}
}
#define LETTER 1/0
main( )
{ char str[5]; char c;
int i=0;
for(i=0; i<=5; i++)
scanf("%c",&str[i]);
程序运行后,若输入,aBcDE
则运行结果为,
str[0]=A
str[1]=B
str[2]=C
str[3]=D
str[4]=E