转义字符
常量和变量
变量
#defined sum 100
符号常量与变量不同,它的值在其作用域内不能改变,也不能再被赋值。 使用符号常量的好处是:
- 含义清楚
- 能做到“一改全改”
- 符号常量:由#define 编译预处理(下例展示符号常量的使用)
常量
- 变量代表内存中具有特定属性(类型)的一个存储单元
- 它用来存放数据,这就是变量的值
- 在程序运行期间,这些值是可以改变的
- 变量名实际上是对应一个地址,是高级语言访问地址内容的一种普遍机制
原理
- 在对程序编译连接时由编译系统给每一个变量名分配对应的内存地址
- 从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据
- 变量:在程序运行期间,变量的值是可以改变的
- 变量必须先定义,后使用
- 定义变量时指定该变量的名字和类型
- 变量名和变量值是两个不同的概念
- 变量名实际上是以一个名字代表的一个存储地址
- 从变量中取值,实际上是通过变量名找到相应的内存地址,从该存储单元中读取数据
变量的作用域
- (1) 主函数中定义的变量只在主函数中有效,而不因为在主函数中定义而在整个文件或程序中有效。主函数也不能使用其他函数中定义的变量。
- (2) 不同函数中可以使用相同名字的变量,它们代表不同的对象,互不干扰。
- (3) 形式参数也是局部变量。
- (4) 在一个函数内部,可以在复合语句中定义变量,这些变量只在本复合语句中有效,这种复合语句也称为“分程序”或“程序块”。
外部变量
变量的存储类型
- 从变量的作用域的角度来观察,变量可以分为全局变量和局部变量
从变量的生存期 (即存在的时间,也是存放在内存中的区域)观察,变量的存储有两种不同的方式:静态存储方式和动态存储方式:
- 静态存储方式是指在程序运行期间由系统分配固定的存储空间的方式。
- 动态存储方式是在程序运行期间根据需要进行动态的分配存储空间的方式。
- 整个存储空间可以分为三部分:1.程序区 2.静态存储区 3.动态存储区
auto类型的变量
- auto类别的变量:不专门声明为static存储类别的局部变量都是动态分配存储空间,在调用该函数时系统会给它们分配存储空间,在函数调用结束时就自动释放这些存储空间。因此这类局部变量称为自动变量。
static类型的变量
- 当函数中的局部变量的值想要在函数调用结束后不消失而保留原值时,该变量称为静态局部变量。用关键字static进行声明。
- (1) 静态局部变量属于静态存储类别,在静态存储区内分配存储单元。在程序整个运行期间都不释放。而自动变量(即动态局部变量)属于动态存储类别,占动态存储区空间而不占静态存储区空间,函数调用结束后即释放。
- (2)对静态局部变量是在编译时赋初值的,即只赋初值一次,在程序运行时它已有初值。以后每次调用函数时不再重新赋初值而只是保留上次函数调用结束时的值。
- (3)如在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0(对数值型变量)或空字符(对字符变量)。而对自动变量来说,如果不赋初值则它的值是一个不确定的值。
- (4)虽然静态局部变量在函数调用结束后仍然存在,但其他函数不能引用它。
register类别的变量
- 一般情况下变量的值是存放在内存中的。当程序中用到哪一个变量的值时,由控制器发出指令将内存中该变量的值送到运算器中。 经过运算器进行运算,如果需要存数,再从运算器将数据送到内存存放。
- 如果有一些变量使用频繁,则存取这些变量的值要花费不少时间。为提高执行效率,C语言允许将局部变量的值放在CPU中的寄存器中,需要使用时可以直接从寄存器取出参加运算,不必再到内存中去存取。
- 由于对寄存器的存取速度远高于对内存的存取速度,因此这样做可以提高执行效率。这种变量叫做寄存器变量,用关键字register作声明。
register类型的变量不能对它用&进行取值操作!
register类别的变量求变量
#include<iostream>
using namespace std;
long fac(long n)
{
register long i, f = 1;
if (n == 0)
return 1;
for (i = 1; i <= n; i++)
f = f * i;
return (f);
}
int main()
{
long i, n;
cin >> n;
for (i = 0; i <= n; i++)
cout << i << "!=" << fac(i) << endl;
}
extern类别的变量
- 外部变量是在函数的外部定义的全局变量,它的作用域是从变量的定义处开始,到本程序文件的末尾。在此作用域内,全局变量可以为程序中各个函数所引用。编译时将外部变量分配在静态存储区。用extern来声明外部变量,以扩展外部变量的作用城。
用extern仅是进行变量声明,而不是变量定义!
运算
- 混合运算:整型(包括int,short,long)、浮点型(包括float,double)可以混合运算。在进行运算时,不同类型的数据要先转换成同一类型,然后进行运算.
数据类型转换
- 在使用强制转换时应注意以下问题:
- 类型和表达式都必须加括号(单个变量可以不加括号),如把(int)(x+y)写成(int)x+y则成了把x转换成int型之后再与y相加了。
- 无论是强制转换或是自动转换,都只是为了本次运算的需要而对变量的数据长度进行的临时性转换,而不改变数据说明时对该变量定义的类型。
输入格式
scanf
下例通过键盘输入三角形的三边长,输出三角形面积展示: 格式化输入scanf()从键盘接收数据 对于scanf()要严格记住,输入要和双引号内的格式控制符包括标点等其他符号完全严格吻合,这是最易出错的地方 而且此类错误后果严重
putchar()函数
作用:从计算机向显示器输出一个字符 putchar函数的一般形式为: putchar?
printf
关系运算与逻辑运算
逻辑短路
逻辑表达式的短路运算特性:在逻辑表达式的求解中,因为逻辑运算的特性,知道一个操作数的逻辑值就有可能得到整个逻辑表达式的值,所以某些情况下并不是所有的逻辑运算符都要被执行
- 比如:
a && b && c 只要a为假,就不必判断b和c的值,只有a为真,才判断b,a和b都为真才判断c a || b || c 只要a为真,就不必判断b和c的值,只有a为假,才判断b,a和b都为假才判断c - 本例说明逻辑表达式的短路运算
例:(m=a>b)&&(n=c>d),当a=1,b=2,c=3,d=4,m和n的原值为1时,表达式执行完后m和n各为几? 由于“a>b”的值为0,因此m=0,而“n=c>d”不被执行,因此n的值不是0而仍保持原值1。
if
方式一
#include <iostream>
using namespace std;
int main()
{int year,leap;
cout << ("enter year:");
cin >> year;
if (year%4==0)
if(year%100==0)
if(year%400==0)
leap=1;
else
leap=0;
else
leap=1;
else
leap=0;
if (leap)
cout << year << " is ";
else
cout << year << " is not ";
cout << "a leap year" << endl;
return 0;}
方式二:
#include <iostream>
using namespace std;
int main()
{ int year,leap;
cout << ("enter year:");
cin >> year;
if((year%4==0 && year%100!=0) || (year%400==0))
leap=1;
else
leap=0;
if (leap)
cout << year << " is ";
else
cout << year << " is not ";
cout << "a leap year" << endl;
return 0; }
函数
- 函数值的类型:函数的返回值应当属于某一个确定的类型,在定义函数时指定函数返回值的类型
- 在定义函数时指定的函数返回类型一般应该和return语句中的表达式类型一致
- 如果函数值的类型和return语句中表达式的值不一致,则以函数返回类型为准
- 对数值型数据,可以自动进行类型转换。即函数类型决定返回值的类型
- 对于不带回值的函数,应当用“void”定义函数为“无类型”(或称“空类型”)。此时在函数体中不得出现
函数原型(告诉编译器函数的所有信息)的一般形式有两种:
- 不带参数名:
函数类型 函数名(参数类型1,参数类型2……); float add(float, float); - 带参数名:
函数类型 函数名(参数类型1 参数名1,参数类型2 参数名2……); float add(float x, float y); 注意:是一条独立的C语句,别忘了最后的分号!
练习题
- 编写一个函数,判断输入的任何一个正整数n是否等于某个连续正整数序列之和,若是,输出所有可能的序列,否则输出“不能分解”。比如,当输入100时,输出:
- 100=9+10+11+12+13+14+15+16
- 100=18+19+20+21+22
解题思路: **找到数学规律。n以i为开头的j个整数的和为ij+j(j-1)/2;判断输入的整数是否和计算结果相同。 如果相同则循环输出以i为开头的j个整数。
高级版
#include<iostream>
using namespace std;
int main()
{
int num=0,sum=0;
cout << "请输入一个整数:" << endl;
cin >> num;
for (int i = 0; i < (num + 1) / 2; i++)
{
for (int j = 0; j < (num + 1) / 2; j++)
{
if (num == i * j + j * (j - 1) / 2)
{
cout << num << "=";
for (int k = 0; k < j; k++)
{
cout<< " + "<< i ;
i++;
}
cout << endl;
sum++;
}
}
}
if (sum == 0)
{
cout << "不存在连续的数字使得它们的和为" << num << endl;
}
}
基础版
#include<iostream>
using namespace std;
int main()
{
int n;
cout << "请输入一个整数:" << endl;
cin >> n;
int max = (n + 1) / 2,num=0;
for (int i = 0; i <= max; i++)
{
int sum = 0;
for (int j = i; j <= max; j++)
{
sum += j;
if (sum == n)
{
cout << "从" << i << "开始到" << j << "有连续的数" << endl;
num++;
}
}
}
if (num != 0)
{
cout << "连续的数有"<<num<<"种" << endl;
}
else
{
cout << "没有连续的数" << endl;
}
}
地址传递
- 函数的形参不仅可以传值还可以传地址,在传地址的情况下,实参和形参指向同一个存储单元,通过间接运算,形参和实参可同步变化!
*运算符:出现在变量定义语句时,其作用为定义指针型变量 类型 * 指针变量名 表示定义一个指向给定类型的指针变量,存储的是该类型变量的地址 " int * p"; \可以存放整型变量地址的指针变量 int num; p=# \p里面存放的是整形变量num的地址 " * "运算符:出现在表达式中时,其作用为取指针变量地址内的具体内容,即它所指向的变量本身
函数的分类
根据函数能否被其他源文件调用,将函数区分为: 内部函数和外部函数。
内部函数
如果一个函数只能被所在文件中其他函数所调用,它称为内部函数。在定义内部函数时,在函数名和函数类型的前面加static。即
static 类型标识符 函数名(形参表)
例如: static int fun ( int a , int b )
外部变量
(1) 定义函数时,如果在函数首部的最左端加关键字extern,则表示此函数是外部函数,可供其他文件调用。例如,函数首部可以写为extern int fun (int a, int b),这样,函数fun就可以为其他文件调用。如果在定义函数时省略extern,则隐含为外部函数。 (2) 在需要调用此函数的文件中,用extern对函数作声明(extern同样可省略),表示该函数是在其他文件中定义的外部函数 。
函数递归
- 在调用一个函数的过程中又出现直接或间接地调用该函数本身,称为函数的递归调用。
- 递归用来解决此类问题:从数学上大致描述,只有有限项需要具体描述,而无限项可以用一个通式描述,这个通式包含前面的有限项信息来描述当前项
调用形式
案例
- 编写递归函数的一个关键点:
在程序中必须有一个原子操作,使得程序能够停止下来不再递归,一般都会利用判断语句在函数参数等于某个值时,直接进行一个简单操作。否则,这个递归函数一旦调用,会出现死循环!
数组
数组概述
- 数组的本质:同种类型的数据存放在连续的内存空间中,地址变化规律明确清晰。
- 数组就是一组具有相同数据类型的数据的有序集合。
- 用一个数组名和下标唯一确定数组中的元素。下标代表数据在数组中的序号。
- 数组中的每一个元素都属于同一个数据类型
注意
- 要使用数组,必须在程序中先定义数组; “先定义、后使用”
- C语言不允许对数组的大小作动态定义,即数组的大小不依赖于程序运行过程中变量的值。也就是说数组的长度一定要在程序运行前就要确定下来。
二维数组
|