c语言.docx

上传人:b****5 文档编号:7254228 上传时间:2023-01-22 格式:DOCX 页数:13 大小:170.24KB
下载 相关 举报
c语言.docx_第1页
第1页 / 共13页
c语言.docx_第2页
第2页 / 共13页
c语言.docx_第3页
第3页 / 共13页
c语言.docx_第4页
第4页 / 共13页
c语言.docx_第5页
第5页 / 共13页
点击查看更多>>
下载资源
资源描述

c语言.docx

《c语言.docx》由会员分享,可在线阅读,更多相关《c语言.docx(13页珍藏版)》请在冰豆网上搜索。

c语言.docx

c语言

第四章 变量运算 表达式

  1.运算

C语言运算分为五大类:

取目标运算、算术运算、逻辑运算、关系运算和其它运算.

表达式:

C语言中的所谓表达式是一个含义较广的名称,通常称以运算符连接变量、常量、函数所成的式子为表达式;表达式必定有一个返回值;最简单的表达式就是一个量,如5,a可以认为是两个表达式.

为了简便,我们在下面运算中的对象都是量a,b...,其实这些量除了少数外,也可以是表达式.

①取目标运算:

  运算对象:

结构体或共同体型数据类型变量;

  运算符:

‘.’;含义:

访问结构体或共同体型数据类型变量的成员;

      ‘[]’;含义:

数组下标运算,即访问数组元素;

  运算结果:

返回被访变量的值.

②算术运算、关系运算、逻辑运算及其它运算:

数值型或字符型变量在此等同看待,字符型变量以其ASCII参加运算,此时可认为它是单字节整型量,因此以下的“整型”也包含字符型

                    a,b隐性转化为较长数据类型后运算,返

                   回值的数据类型也是较长数据类型

减法算 双目 同上 a-ba-b的值 同上

  取负 单目 同上-a-a的值a本身并未改变

 *乘法术 双目 同上 a*ba*b的值同上

  同上,如5/2返回2;5/2.0返回2.5;

/除法   双目 同上 a/ba/b的值 inta=5;floatb=2;a/b返回2.5;

                      floata=5/2;a的值仍然是2而不是2.5

a除以b返回必定是整数.17%5返回2;-17%5返

 的余数回-2;17%(-5)返回2;-17%(-5)返回-2(exa4_1)

                  称++a为前置自增,a++为后置自增,对a

算++aa的原来而言两者都等价于a=a+1(a增加了1);但

             a++ 值加1出现在一个表达式中,前者先自增后再参

                于后继运算,后者则以增前值参与运算

                如a=3,b=5;c=++a*ba=4,c=20,b=5;

 术  c=a++*ba=4,c=15,b=5;

    称--a为前置自减,a--为后置自减,对a

                      而言两者都等价于a=a-1(a减小了1);

  区别类似于自增

                    a隐性转换为b的数据类型,再赋予b;

     赋              C语言允许连续赋值,如c=b=b*(a+2);

                     j=i=(k=l+1)+(j=5).除()优先外,依次自

右至左赋值

                  符号‘#’是算术运算符+,1,*,/,%之一,表

#= 达式a#=b等价于a=a#b,例如a%=b即

a=a%b,a*=b即a=a*b.

>大于   双目数值 a>b特别强调,式中的a,b可以是表达式.

 <小于 关双目同上a

>=不小于  双目同上a>=b      如:

a=2,b=-2;

=<不大于  双目同上a<=bc=(a!

=0);c=1;c=a

== 等于 系 双目同上a==b        c=(a+b)>=(a-b)c=0;

                       a+=a>=ba=3;

                       a-=a==-b+1a=2(见exa4_2)

  若在一个表达式中含有赋值号,常称为赋值表达式;含有逻辑运算符,常称为逻辑表达式;含有关系运算符,常称为关系表达式.

式中的a,b很多情况是表达式;

逻                  逻辑运算的返回值如同普通值一样

                        可以参与后继操作.如:

a=2,b=-2;

                        c=!

bc=0;c=(a>0)&&(b>0)c=0;

      辑                  c=a>=0||b>0c=1;c=(a>=0)&&b

c=1;c=(a<=0)||!

bc=0(见exa4_2)

&取址   单目 无  &aa的存储地址 地址是一个特殊类型的数据类型

      

 

  此外,教材上把强制类型转换、取数据类型存储长度函数sizeof()也列入单目运算类型.

  2.运算优先级

①运算的优先级:

多种运算符同时出现于一个表达式时,准确判断其有限序是获得准确结果的前提.

运算优先级见教材P.369P.369.记忆规律可循一般的主导思路:

  找寻目标对目标作处理(单目运算)目标参与(算术)运算(先乘除余,后加

  减)对结果进行比较(关系运算)对多个关系做逻辑判定(逻辑运算)输

出最终结果(赋值).

  ②同优先级处理:

在一个表达式中,若出现同一优先级运算符,则按结合方向决定运算的先后次序.所谓结合方向是指表达式向哪个方向去结合运算符,自左向右结合是从右边起,表达式去与其右边最近的运算符结合.结合方向可按下述方法记忆:

除单目运算、赋值运算和三项结合运算外,都是自左向右结合,而单目和赋值自右向左结合是我们的自然习惯.如

 c=a+b+c(左向右结合)  c=(a+b)+c);

   x=5>2>7>8(左向右结合) x=((5>2)>7)>8x=(1>7)>8x=0>8,最后x为0;

③对前置、后置自增自减运算,其固定法则部分,不受运算优先级的干扰.如

(1)a=4,b=2;c=++a%b--;

按运算优先级,自减运算‘--’应在取余运算‘%’之前,但按后置运算法则,实际上运算次序仍然是:

a自增a=a+1成为5a%b得1b自减成为1把a%b的结果1赋予c.

  

(2)a=13,b=7;c=(a--)%(b--);

按运算优先级,先对()内运算,结果似乎应该是c=(12)%(6),即以0赋予c,但实际上因为()内是a--和b--,运算()时按后置自减的法则,应该先运算(),结果分别返回13和7,然后a,b再分别‘--’成为12和6,而运算‘%’对两个()内返回值进行,即13%7得6,因此赋值予c的是6.

(3)a=13,b=5;c=++(a%b--);c1=(++a%b)--;

与例1)相比,c把‘++’放到了()外,c1把‘--’放到了()外,但表达式含义及结果与1)大相径庭.因为这一来,运算‘++’和‘--’的对象不再是a,b而是()内的返回值,因此

第一个表达式结果是:

a%b返回3b--,b成为4++3得4赋予c,所以最终:

a=13,b=4,c=4;

第二个表达式结果是:

++a,a成为1414%4返出22--成为11赋予c1,所以最终:

a=14,b=4,c1=1.

可惜上述分析仅是理论上的,C语言的编译系统还不足以分析这种略微复杂一点的表达式,干脆给出一个出错信息,认为语法有错误!

也就是说,如果您想得到上述结果,只能分为两个表达式,不能一步得到.(见exa4_4)

④运算与输出序的关系.在以前讲输出项即输出目标,总认为它是变量、常量、函数,其实输出目标可以是一个表达式的返回值,此时输出项就成为一个表达式了.如:

  putchar(‘c’-32);(输出‘C’);printf(“%d”,x>=0?

x:

-x); (输出x).

用格式化输出函数printf(),一次可以输出多项,当输出项是一些表达式时,就会发生问题:

这些表达式先计算哪一个?

例如:

   inti=0;printf(“%d,%d,%d”,i,i++,i++);

两个‘i++’先计算哪一个?

C语言规定:

逆序计算,顺序输出.也就是说,表达式从最后一个开始依次向前计算;到第一个计算结束,再顺序依次从第一个输出,因此上面语句输出结果是:

 2,1,0_.注意这里仍然遵守后置运算的规则,先把末个i=0送到输出栈,再在i的存储元中自增,改变i成为1;然后把中间i=1送到输出栈,再在i的存储元中自增,改变i成为2;最后把第一个i=2送到输出栈,再在i的存储元中自增,改变i成为3.所有输出项计算完毕,依次从输出栈取出2,1,0予以输出.(见exa4_5)

⑤几点注意:

(1)若运算属于优先的,理论上不必再加(),但为了增强程序的可读性,最好还是加这些“不必要”的圆括弧,或者分列成几个运算式.如

 x=2,y=3;z=3-1>=x+1<=y+2;                    (*)

按优先级:

  z=(3-1)>=(x+1)<=(y+2),

按结合方向:

 z=((3-1)>=(x+1))<=(y+2)z=(2>=3)<=5z=1

因此.(*)式是合法的,且按算法优先级有一个唯一的计算顺序,但这种写法显然增加了阅读的困难.

  

(2)不要滥用优先级或连续赋值,尽量加一些不必要的括号(),以免引起误解.例如

  1)x=i+++j;

可解释为x=i+(++j),也可解释为x=(i++)+j;实际上C语言在编译时,自左向右结合尽量多的运算符成为一个运算符,因此后一种解释是正确的.

  2)x=i+++++j;

解释就更多了,按上面编译处理原则,似乎应解释为x=((i++)++)+j,实际上不能通过编译,认为它是一个错误的表达式.

3)i=(k=j+1)+(j=5);

按运算优先级和结合方向规定,能得到一个唯一的结果:

k=j+1得到第一个返回值j=5得到第二个返回值相加两个返回值后赋予i.但由于编译系统差异,实际可能会先执行j=5,再执行k=j+1而使结果与预期的不同.因此在“结合方向”问题上不能绝对化.

类似的例子还有运算‘&&’与‘||’,它们优先级相同,结合方向自左向右,但有时是‘&&’优先于‘||’.因此在同优先级情况,比较可靠的还是分列或加括号.

(3)C语言对表达式处理有一个优化原则:

当一个表达式已经能得到确定的值,就终止计算.如:

  x=y=0;经表达式 ++x||++y&&++z;计算后的x,y,z的值应该是1,1,1,但实际上是1,0,0.原因是当++x返回1时,根据逻辑运算‘||’的运算法则,此表达式已经能得到确定的值,因此计算终止,下面的++y,++z不再执行而保留了原来的值.(见exa4_6)

  3.字符串运算

字符串运算常称串操作,其运算对象不是字符串中的个别字符,而是整个串.

对字符串运算主要调用系统提供的一批函数,这些函数的原型说明都在string.h中,因此程序中应包含头文件#include

  ①字符串求长函数strlen():

使用格式:

strlen(字符串地址);

功能:

返回从指定地址起到‘\0’止所含的字符个数(不包括‘\0’本身).若地址是存储字符串的首地址,则返回整个字符串所含的字符个数,即字符串的长度.

例如charch[20]=“Goodmorning”;

strlen(ch) 返回12; strlen(&ch[4]) 返回8.

  ②字符串连接函数:

strcat()

使用格式:

strcat(字符串1的地址1,字符串2的地址2);

功能:

把地址2起直到‘\0’为止的字符串2,连接到字符串1的后面去,成为一个字符串,并返回地址1(直观图象见下).

例:

    charstr1[50]=“Good”,str2[50]=“morning”;

strcat(str1,str2);str1[]中存储了字符串“Goodmorning”,返回地址str1;

若改为strcat(&str1[2],&str2[2]);str1[]中存储了字符串“Goodrning”,返回地址&str1[2].

注意:

  1)字符串2可以是一个字符串常量,例如:

  strcat(str1,“Goodmorning”);

字符串1在理论上也可以是字符串常量,如strcat(“Ilove”,“you”);但在实际上若强行如此,可能会破坏第二个字符串,因为字符串常量存储地址与存放于一维char型数组中的字符串的地址的段不同,字符串常量之间没有空余字节.

2)被连接的字符串后应该有富裕字节,使能容下连接后所成较长的字符串,否则与1)同样的问题也会发生,例如charstr1[7]=“Ilove”,其后无富裕字节,在其后连接另一个字符串“you”时,也可能破坏后继数据.

③字符串比较函数strcmp():

使用格式:

strcmp(字符串1地址,字符串2地址);

功能:

从指定的两个地址起,逐字节比较,直至

     两个字符串都读到了‘\0’,返回0 两个字符串相同;

     串1的字符>串2的字符,返回正数            串1>串2;

     串1的字符<串2的字符,返回负数             串1<串2.

简言之,比较结果返回0表示两个字符串相同;返回正数表示字符串1>字符串2;返回负数表示字符串1<字符串2.

例如,charch1[10]=“abcd”,ch2[10]=“abcd”,ch3[10]=“abcd”,ch4[10]=“abcD”,

ch5[10]=“Abcd”,

strcmp(ch1,ch2)返回0;strcmp(ch1,ch3)返回负数;strcmp(ch3,ch4)返回正数;

     strcmp(ch1,ch5)返回正数;strcmp((ch1[1],&ch5[1])返回0.

④字符串复制函数strcpy():

使用格式:

strcpy(地址1,地址2);

功能:

把地址2开始的字符串(从地址2起到‘\0’止的字符串),赋值到地址1去,成为一个相同的新字符串,并返回地址1.如

     charch1[20],ch2[20]=“Googmorning”;

strcpy(ch1,ch2);ch1[]中存放了字符串“Goodmorning”;

     strcpy(ch1,&ch2[2]); ch1[]中存放了字符串“odmorning”.

注意:

  1)地址2开始的字符串可以是一个字符串常量,如

   strcpy(ch1,“Goodmorning”);ch1[]中也存放了字符串“Goodmorning”.

2)以前曾强调字符串不能整体赋值,例如ch1[]=“Goodmorning”是错误语法.strcpy()函数的功能,相当于赋字符串予一个一维char型数组,只要strcpy(数组名,字符串常量).

⑤字符匹配函数strchr():

使用格式:

strchr(地址,字符变量或字符常量);

功能:

从指定的地址起,逐个字符与变量中的字符或字符常量对照,直到发现字符相同,返回自该字符在字符串中的地址;或已经扫描到‘\0’还没有发现相同字符,则返回“空”(即NULL).

例如charstr[20]=“Googmorning”,ch=‘n’;

strchr(str,ch)返回&str[8]; strchr(str,‘n’);结果相同;

strchr(&str[6],ch);结果也相同;若strchr(&str[1],‘G’);则返回NULL.

⑥子串匹配函数 strstr():

所谓子串匹配是指在一个字符串1中,是否含有另一个字符串2,若含有,则称字符串1能匹配字符串2,否则成为不能匹配.

使用格式:

strstr(地址1,地址2);

功能:

在以地址1起到‘\0’止的字符串1中,匹配地址2起的字符串2,若能够匹配,则返回字符串1中的匹配起始地址,否则返回NULL(‘空’).

例如:

charstr1[20]=“GoodBye”;str2[10]=“Good”;str3[10]=“Bye”;

strstr(str1,str2);返回str1(即&str1[0]);

strstr(str1,str3);返回&str1[5];

   strstr(str1,“good”);返回NULL;

   strstr(&str1[1],“Good”);也返回NULL.(见exa4_7)

⑦数字字符串转化为数的转换函数:

以下三个函数可以把一个数字字符串转化为相应的数,如“123”转化为123.这三个函数的原型说明在stdlib.h,因此要使用它们,必须包含头文件#include

1)短整型转化函数atoi():

使用格式:

atoi(地址);

功能:

把指定地址起直到‘\0’止的、不含小数点的数字字符串,转化为相应的数,并予以返回.“地址”也可以是一个整数数字字符串常量.如

    atoi(“123”); 返回整数123;

    charstr[5]=“0124”;

       atoi(str);返回124;    atoi(&str[1]);也返回124;

       atoi(&str[2]);则返回24; stoi(&str[3]);返回4.

注意若字符串中含有除+、-号外非数码字符,或转化结果超出短整型数的范围(-3276832767)则返回不正确的结果.

  2)长整型转化函数atol():

使用格式及功能与atoi()相同,区别仅在于返回的是长整型数,且转化成数的范围扩大为长整型数的范围.

3)实型转换函数atof():

使用格式及功能与atoi()相同,区别仅在于数字字符串中可以含有数码、+,-号及小数点,返回的是单精度实型数(float型).

  ⑧数转化为数字字符串的转换函数:

有若干个函数能实现转换功能,仅介绍一个gcvt().

使用格式:

gcvt(doublevalue,intndigit,地址);

功能:

把数value转化为长度是ndigit个字节的相应字符串,存放在指定的地址中,并返回此地址.

如:

doublea=10.12;charbuff[20];

gcvt(a,5,buff);则在buff[]中即存放了字符串“10.12”.

value也可以是直接常量,如gcvt(10.12,5,buff);

结构体型变量可以含有不同数据类型的成员,在输入数据中,当由数值型成员输入转为字符型或字符串成员输入时,常常因为键盘缓冲区残留的回车符而造成误输入.为避免这种失误,常用的技巧之一是,在输入数值型成员时也输入为字符串,再应用上述转换函数转换为需要的数据类型赋予数值型成员.因为输入字符串能吸收回车符转化为‘\0’,这样就可不必顾虑残留回车符问题.例如:

(见exa4_8)

  #include

  #include

#defineMAX50/*定义宏MAX*/

structstudent/*定义结构体数据类型structsutdent,表示一个学生记录*/

  {

  unsignedlongnum;/*学号*/

   charname[10],sex,;/*姓名、性别*/

   floatscore;    /*课程的成绩*/

  };

/*-----------------------------*/

  main()

  {

  structstudentst[MAX];    /*数组st[]存放一个班级学生的记录*/

    intn=0,i,k=0;

/*n为实际输入记录的人数,i,k为计数器*/

charch,temp[20];/*ch用来接受用户的应答输入字符,temp[]临时存放字符串*/

   

do/*do...while(条件);是循环语句,在条件满足时,重复执行其间的所有语句*/

   {

   clrscr();/*每一个记录输入之前清屏*/

   printf("\n\n"); /*空二行*/

   printf("输入第%d个记录的全部数据:

\n",n+1);/*提示输入第几个记录*/

   printf("学号:

");/*下一行行首空二个字符后,提示输入学号*/

    gets(temp);    /*自动换行*/

      st[n].num=atol(temp);

      printf("姓名:

");

      gets(st[n].name); /*自动换行,键盘缓冲区是空的*/

   printf("性别(男:

m;女:

w):

");

      gets(temp);

st[n].sex=temp[0];

   printf("输入课程的成绩:

");

      gets(temp);

st[n].score=atof(temp);

n=n+1;        /*一个记录输入完毕,输入记录个数增加1*/

   printf(“\n还要继续输入吗(y/n)?

");

/*隔开一行后提示选择后继操作及应答格式*/

   gets(temp);ch=temp[0];

   }while(ch=='Y'||ch=='y');

......

}

本章作业:

一、P.663.9,3.10,3.12

二、补充:

    输入三个字符串,按有“小”到“大”的顺序输出;然后把这三个字符串连接起

  来予以输出;再把第三个字符串的后半部分复制到连接后字符串的一半的地方,输

  出结果;最后,找出第三步复制后与第三个字符串的后半部分的匹配起始点.

三、职工工资表的结构为

  structwork

{

charname[10],salory[10],depart[3];

}

其中name[]为姓名,salory[]为工资(含有二位小数),depart[]为部门号.部门号

  从“01”到“99”.所有职工的工资记录存放在数组structworks[200]中,实际职

  工人数不足200人,以姓名是空字符串为结束标记.试编一个函数

voidaverage_salory(structworks[])

输出各部门职工的平均工资和全体职工的总平均工资.显示形式为:

    部门号..,职工平均工资=.....(换行);

  最后输出所有姓王和姓张的职工的混合平均工资.

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 金融投资

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1