- 博客(40)
- 收藏
- 关注
原创 39.地址算术运算
如果p是一个指向数组中某个元素的指针,那么p++将会对p进行自增运算并指向下一个元素,而p+=i将对p进行加i的增量运算,使其指向指针p当前所指向的元素之后的第i个元素。通常,对指针有意义的初始化值只能是0或者是表达地址的表达式,对后者来说,表达式所代表的地址必须是在此前已定义的具有适当类型的数据的地址。指针的减法运算也是有意义的:如果p和q指向相同数组中的元素,且p<q,那么q-p+1就是位于p和q指向的元素之间的元素的数目。在上述程序的的声明中,指针p被初始化为指向s,即指向该字符串的第一个字符。
2023-09-19 19:00:59 106
原创 38.指针与数组
如果将数组名传递给函数,函数可以根据情况判定是按照数组处理还是按照指针处理,随后根据相应的方式操作该参数。在被调用函数中,该参数是一个局部变量,因此,数组名参数必须是一个指针,也就是一个存储地址值的变量。因为s是一个指针,所以对其执行自增运算是合法的。执行s++运算不会影响到strlen函数的调用者中的字符串,它仅对该指针在strlen函数中的私有副本进行自增运算。指针式一个变量,因此,在C语言中,语句pa=a和paa++都是合法的。但数组名不是变量,因此,类似于a=pa和a++形式的语句式非法的。
2023-08-26 20:17:06 48
原创 37.指针与函数参数
我们来看这样一个例子,函数getint接受自由格式的输入,并执行转换,将输入的字符流分解成整数,且每次调用得到一个整数。由于C语言是以传值的方式将参数值传递给被调用函数,因此,被调用函数不能直接修改主调函数中变量的值。在getint函数中,*pn始终作为一个普通的整型变量使用。这是因为,由于参数传递采用传值的方式,因此上述的swap函数不会影响到调用它的例程中的参数a和b的值。该版本的getline函数在到达文件结尾时返回EOF,当下一个输入不是数字时返回0,当输入中包含一个有意义的数字时返回一个正值。
2023-08-21 20:17:46 68
原创 36.指针与地址
一元运算符*是间接寻址或间接引用运算符,当它作用于指针时,将访问指针所指向的对象。我们在这里假定x与y是整数,而ip是指向int类型的指针。这样声明式为了便于记忆。该声明语句表明表达式*ip的结果是int类型。这种声明变量的语法与声明该变量所在的表达式的语法类似。变量x、y与z的声明方式我们已经在前面的章节中见到过。指针是能够存放一个地址的一组存储单元(通常是两个或四个字节)。
2023-08-19 19:55:22 44
原创 35.条件包含
if语句对其中的常量整型表达式(其中不能包含sizeof、类型转换运算符或enum常量)进行求值,若该表达式的值不等于0,则包含其后的各行,直到遇到#endif、#elif或#else语句为止(预处理器语句#elif类似于else if)。在#if语句中可以使用表达式defined(名字),该表达式的值遵循下列规则:当名字已经定义时,其值为1;还可以使用条件语句对预处理本身进行控制,这种条件语句的值是在预处理执行的过程中进行,这种方式为在编译过程中根据计算所得的条件值选择性地包含不同代码提供了一种手段。
2023-08-17 20:17:00 72
原创 34.C预处理器
通常情况下,#define指令占一行,替换文本是#define指令行尾部的所有剩余部分内容,但也可以把一个较长的宏定义分成若干行,这时需要在持续的行末尾加上一个反斜杆符\。的行都将被替换为由文件名指定的文件的内容。如果在该位置没有找到文件,或者如果文件名时用尖括号<与>括起来的,则将根据相应的规则查找该文件,这个规则同具体的实现有关。源文件的开始处通常都会有多个#include指令,它们用以包含常见的#define语句和extern声明,或从头文件中访问库函数的函数原型声明,比如<studio.h>。
2023-08-14 19:46:22 37
原创 33.递归
解决该问题有两种方法。一种方法是将生成的各个数字依次存储到一个数组中,然后再以相反的次序打印它们,这种方法与3.6节中itoa函数的处理方式相似。另一种方法则是使用递归,函数printd首先调用它自身打印前面的(高位)数字,然后再打印后面的数字。这里编写的函数不能处理最大的负数。下列版本的快速排序函数可能不是最快的,但它是最简单的算法之一。在每次划分子集时,该算法总是选取各个子数组的中间元素。C语言中的函数可以递归调用,即函数可以直接或间接调用自身。
2023-08-13 19:41:58 58
原创 32.程序块结构与初始化
变量的声明(包括初始化)除了可以紧随在函数开始的花括号之后,还可以紧跟在任何其他标识复合语句开始的左花括号之后。以这种方式声明的变量可以隐藏程序块外与之同名的变量,它们之间没有任何关系,并在与左花括号匹配的右花括号出现之前一直存在。对于自动变量与寄存器变量来说,初始化表达式可以不是常量表达式:表达式中可以包含任意在此表达式之前已经定义的值,包含函数调用。在不进行显式初始化的情况下,外部变量和静态变量都将被初始化为0,而自动变量和寄存器变量的初值则没有定义(即初值为无用的信息)。这段代码中的变量y也是如此。
2023-08-12 09:48:05 77
原创 31.静态变量与寄存器变量
某些变量,比如文件stack.c中定义的变量sp与val以及文件getch.c中定义的变量buf与bufp,它们仅供其所在的源文件中的函数使用,其他函数不能访问。用static声明限定外部变量与函数,可以将其后声明的对象的作用域限定为被编译源文件的剩余部分。通过static限定外部对象,可以达到隐藏外部对象的目的,比如,getch-ungetch复合结构需要共享buf与bufp两个变量,这样buf与bufp必须是外部变量,但这两个对象不应该被getch与ungetch函数的调用者所访问。
2023-08-11 10:22:37 72
原创 30.作用域规则与头文件
名字的作用域指的是程序中可以使用该名字的部分。对于在函数开头声明的自动变量来说,其作用域是声明该变量名的函数。不同函数中声明的具有相同名字的各个局部变量之间没有任何关系,函数的参数也是这样的,实际上可以将它看作是局部变量。外部变量或函数的作用域从声明它的地方开始,到其所在的(待编译的)文件的末尾结束。为源文件的其余部分声明了一个int类型的外部变量sp以及一个double数组类型的外部变量val(该数组的长度在其他地方确定),但这两个声明并没有建立变量或为它们分配存储单元。
2023-08-10 09:53:32 48
原创 29.外部变量
main函数包含一个很大的switch循环,该循环根据运算符或操作数的类型控制程序的转移。这里的switch语句的用法比3.4节中的例子更为典型。为了保证正确的次序,必须像main函数中一样把第一值弹出到一个临时变量中。
2023-08-09 10:44:06 79
原创 28.返回非整数型值的函数
调用函数必须知道atof函数返回的是非整数型值,这一点也是很重要的。为了达到该目的,一种方法是在调用函数中显式声明atof函数。下面所示的基本计算程序有类似的声明。atof函数需要处理可选的符号和小数点,并要考虑可能缺少整数部分或小数部分的情况。
2023-08-07 19:41:30 106
原创 26.break语句与continue语句、goto语句与标号
所有使用了goto语句的程序代码都能改写成不带goto语句的程序,但可能会增加一些额外的重复测试或变量。当发现最右边的字符未非空格符、非制表符、非换行符,就使用break语句从循环中退出。continue语句只用于循环语句,不用于switch语句。某个循环包含的switch语句中的continue语句,将导致进入下一次循环。在该例子里,如果错误处理代码很重要,并且错误可能出现在多个地方,使用goto语句将会比较方便。大多数情况下,使用goto语句的程序段比不使用goto语句的程序段要难以理解和维护。
2023-08-05 10:37:54 59
原创 25.do-while循环
do-while循环是比较有用的,下面我们通过函数itoa来说明这一点。itoa函数是atoi函数的逆函数,它把数字转换为字符串。这个工作比最初想象的要复杂一点。如果按照atoi函数中生成数字的方法将数字转换为字符串,则生成的字符串的次序正好是颠倒的,因此,我们首先要生成反序的字符串,然后再把该字符串倒置。下面是itoa函数。无法通过n = -n;转换成一个正数,这是因为对2的补码所能表示的最大整数只能是。因此无法完成将n成为正数的操作。2^(字长-1) - 1.-(2^(字长-1))
2023-08-04 20:11:37 37
原创 24.while循环与for循环
while循环中,首先求表达式的值。如果其值为真非0,则执行语句,并再次求该表达式的值。这一循环过程一直进行下去直到该表达式的值为假(0)为止,随后继续执行语句后面的部分。
2023-08-03 10:33:23 44
原创 24.switch
break语句将导致程序的执行立即从swtich语句中退出。在switch语句中,case的作用只是一个标号,因此,某个分支中的代码执行完后,程序将进入下一分支继续执行,除非在程序中显式地跳转,跳出switch语句最常用的方法是使用break语句与return语句,break语句还可强制控制从while、for与do循环语句中立即退出。switch语句是一种多路判定语句,它测试表达式是否与一些常量数值中的某一值匹配,并执行相应的分支动作。case常量表达式:语句序列。case常量表达式:语句序列。
2023-08-02 10:07:05 53
原创 23.else-if语句
在折半查找时,首先将输入值x与数组v的中间元素进行比较。如果x小于中间元素的值,则在该数组的前半部分查找;否则,在该数组的后半部分查找。在这两种情况下,下一步都是将x与所选部分的中间元素进行比较,这个过程一直进行下去,直到找到指定的值或查找范围为空。else-if语句的最后一个else部分用于处理“上述条件均不成立”的情况或默认情况,也就是当上面各条件都不满足时的情形。该函数的基本判定是:在每一步判断x小于、大于还是等于中间元素v[mid]。使用else-if结构执行这种判定很自然。
2023-08-01 13:56:36 109
原创 22.语句与程序库和if-else语句
因为if-else语句的else部分是可选的,所以在嵌套的if语句中省略它的else部分将导致歧义。解决的方法是将每个else与最近的前一个没有else配对的if进行匹配。用一对花括号“{”与“}”把一组声明和语句括在一起就构成了一个复合语句(也叫做程序块),复合语句在语法上等价于单条语句。函数体中被花括号括起来的语句便是明显一例。else部分与内层的if匹配,我们通过程序的缩进结构也可以看出来。if-else语句用于条件判定。
2023-07-31 09:47:48 63
原创 21.条件表达式、运算符优先级与求值次序
的语句中,f()可以在g()之前计算,也可以在g()之后计算。因此,如果函数f或g改变了另一个函数所使用的变量,那么x的结果可能会依赖于这两个函数的计算顺序。b :c中,首先计算a,如果其值不等于0(为真),则计算b的值,并以该值作为条件表达式的值,否则计算c的值并以该值作为条件表达式的值。如果&&运算左边是假,那么右边的运算就不用做了。同大多数语言一样,C语言没有指定同一种运算符中多个操作数的计算顺序(&&、||、?:”是三目运算符,该运算符连接3个对象,是C语言中唯一一个三目运算符,又称条件运算符。
2023-07-30 10:00:32 59
原创 20.赋值运算符与表达式
这里将x声明为无符号类型是为了保证将x右移时,无论该程序在什么机器上运行,左边空出的位都用0填补。下面的函数bitcount统计其整型。其中的运算符+=称为赋值运算符。
2023-07-29 10:07:24 179
原创 19.赋值运算符和表达式
这里将x声明为无符号类型是为了保证将x右移时,无论该程序在什么机器上运行,左边空出的位都用0(而不是符号位)填补。用函数举例说明:下面的函数bitcount统计其整数型参数的值为1的二进制的个数。
2023-07-28 11:04:40 52 1
原创 18.按位运算符
为了进一步说明某些位运算符,我们来看函数getbits(x,p,n),它返回x中从右边数第p位开始向右数n位的字段。这里假定最右边的一位是第0位,n与p都是合理的正值。例如,getbits(x,4,3)返回x中第4、3、2三位的值。按位异或运算符^当两个操作数的对应位不同时将该位设置为1,否则,将该位设置为0。移位运算符分别用于将运算的左操作数左移与右移,移动的位数则由右操作数指定。
2023-07-27 15:19:55 90 1
原创 17.自增运算符与自减运算符
考虑标准函数strcat(s, t),它将字符串t连接到字符串s的尾部。C语言提供了两个用于变量递增与递减的特殊运算符。自增运算符++使其操作数递增1,自减运算符--使其操作数递减1.我们经常使用运算符递增变量的值。每当出现一个不是c的字符时,该函数把它拷贝到数组中下标为j的位置,随后才将j的值增加1,以准备处理下一个字符。在将t中的字符逐个拷贝到s的尾部时,变量i和j使用的都是后缀运行符++,从而保证在循环过程中i与j均指向下一个位置。
2023-07-26 10:39:12 50 1
原创 15.算术运算符与关系运算符和逻辑运算符
取模运算符%不能应用于float或double类型。在有负操作数的情况下,整数除法截取的方向以及取模运算结果的符号取决于具体机器的实现,这和处理上溢和下溢的情况是一样的。逻辑运算符&&与||有一些较为特殊的属性。由&&与||连接的表达式从左到右的顺序进行求值,并且在知道结果值为真假后立即停止计算。练习2-2:在不使用运算符&&或||的条件下编写一个与上面的for循环语句等价的循环语句。二元运算符包括:+、-、*、/、%(取模运算符)。整数除法会截断结果中的小数部分。我们可以用一下语句判断闰年。
2023-07-24 10:32:29 49
原创 14.常量与声明的用法
所有变量都必须先声明后使用,尽管某些变量可以通过上下文隐式地声明。一个声明指定一种变量类型,后面所带的变量表可以包含一个或多个该类型的变量。整型数除了用十进制表示外,还可以用八进制或十六进制表示。带前缀0的整型数常量表示它为八进制形式,前缀为ox或OX,则表示它为十六进制。我们可以用'\000'表示任意的字节大小的位模式,这种模式也可以用'\xhh'来表示。标准头文件中声明了strlen和其他字符串函数。枚举为建立常量值与名字之间的关联提供了一种便利方式。设计一个strlen函数。
2023-07-23 10:29:43 43
原创 13.变量名、数据类型及长度
练习2-1:编写一个程序以确定分别由signed及unsigned限定的char、short、int与long类型变量的取值范围。采用打印标准头文件中的相应值以及直接计算两种方式实现。函数名与外部变量名包含的字符数目可能小于31,这是因为汇编程序和加载程序可能会使用这些外部名,而语言本身是无法控制加载和汇编程序的。名字是由字母和数字组成的序列,但其第一个字符必须为字母。由于库例程的名字通常以下划线开头,因此变量名不要以下划线开头。char 字符型,占用一个字节,可以存放本地字符集中的一个字符。
2023-07-22 09:53:39 131
原创 12.外部变量与作用域
由于自动变量只在函数调用执行期间存在,因此,在函数的两次调用之间,自动变量不保留前次调用时的赋值,且在每次进入函数时都要显式为其赋值。如果自动变量没有赋值,则其中存放的时无效值。函数中的每个变量只在函数被调用时存在,在函数执行完毕退出时消失。这也是其他语言通常把这类变量称为自动变量的原因。
2023-07-21 13:39:09 38
原创 10.参数——传值调用
该代码用于求底数的n次幂,其中,参数n用作临时变量,并通过随后执行的for循环语句递减,直到其值为0,这样就不需要额外引入变量i。必要时,也可以让函数能够修改主调参数中的变量。这种情况下,调用者需要向被调用函数提供待设置值的变量的地址,而被调用函数则需要将对应的参数声明为指针类型,并通过它间接访问变量。也就是说,传递给被调用函数的参数值存放在临时变量中,而不是存放在原来的变量中。在C语言中,被调用函数中,参数可以看作是便于初始化的局部变量,因此额外使用的变量更少,这样程序可以更紧凑简洁。
2023-07-19 14:54:11 29
原创 9.函数的学习
课后练习1-15:重新编写1.2节中的温度转换程序,使用函数实现温度转换计算。函数为计算的封装提供了一种简便的方法,使用的函数时不需要考虑它是如何实现的。然后是程序成功运行后的结果。下面是课内的程序代码。
2023-07-18 15:26:16 36
原创 8.数组与直方图学习
我们通过编写一个程序,以统计各个数字、空白符(包括空格符、制表符及换行符)以及所有其他字符出现的次数。课后练习:编写一个程序打印输入中单词长度的直方图。下面是该程序的代码部分。
2023-07-17 18:25:12 52
原创 7.单词计数
其中运算符 ||代表OR(逻辑或)。运算符&&代表AND(逻辑与),它仅比||高一个优先级,由%%或||连接的表达式由左至右求值,并保证在求值过程中只要能够判断最终的结果为真或假,求值就停止。上面是单词计数的代码。
2023-07-15 22:01:41 71
原创 6.行计数
在该代码中出现了单引号,需要注意的是单引号中的字符表示一个整型值,该值等于此字符在机器字符集中对应的数值,称之为字符常量。然后是课后练习:编写一个将输入复制到输出的程序,并将其中连续的多个空格用一个空格代替。接下来是课后练习:编写一个统计空格、制表符与换行符个数的程序。下面是程序的运行结果。
2023-07-14 15:34:10 63
原创 5.字符计数
在该课的学习中引入了++nc的概念,其功能是执行加1操作,可以用语句nc=nc+1来代替它,但语句++nc更精炼一些,且通常效率也更高。下面是字符计数的版本1的代码。这是程序运行后的结果。这是程序运行后的结果。
2023-07-14 14:33:45 54
原创 4.字符输入/输出与文件复制的学习
标准库提供了一次读/写一个字符的函数,其中最简单的是getchar和putchar两个函数。每次调用时,getchar函数从文本流中读入下一个输入字符,并将其作为结果值返回。无论文本从何处输入,输出到何处,其输入/输出都是按照字符流的方式处理。=EOF的值是0还是1。这是程序正确运行的结果,输入内容按下回车后将会在下一行生成相同内容。这个字符复制程序编写可以变得更加精炼一些,代码如下。程序成功运行后,结果如下,程序能够复制字符到下一行。然后是第二个课后练习编写一个打印EOF值的程序。下面是文件复制的代码。
2023-07-12 16:00:26 84
原创 3.for语句和符号常量的学习
for在C语言中的定义:For是c语言的关键词,它是C语言中的一个关键字。它的作用是:循环地执行一个或多个操作(可以是代码段或语句)。例如:for >>> do while >>> end.这样我们就可以通过for来控制程序流程的进行。其特点是编译后写在代码区,不可寻址,不可更改,属于指令的一部分。下面是课后练习部分:修改温度转换程序,要求以逆序(即按照从300度到0度的顺序)打印温度转换表。这就是逆序打印温度转换表的代码,然后是程序运行的结果。上面是今天学习的for语句的代码。这是程序成功运行后的结果。
2023-07-11 15:23:03 75
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人