本专栏主要基于北大郭炜老师的程序设计与算法系列课程进行整理,包括课程笔记和OJ作业。该系列课程有三部分: (一) C语言程序设计;(二) 算法基础;(三) C++面向对象程序设计
1. 信息在计算机中的表示
计算机用0和1表示各种信息:
- 计算机的电路由逻辑门电路组成。一个逻辑门电路可以看成一个开关,每 个开关的状态是“开"(高电位)或“关”(低电位),即对应于1或0
- 二进制数的一位,取值只能是0或1,称为一个“比特”(bit),简写:b
- 八个二进制位称为一个“字节”(byte),简写: B
- 1024( 2 10 2^{10} 210)字节称为1KB ,1024KB称作1MB(1兆),1024MB称作1GB,1024GB称作1TB。
- 0和1足以表示和传播各种信息。
比如, 用8个连续的0或1(即1个字节)来表示一个字母、数字或标点符号 ,比如用“00100000”表示空格,用“01100001”表示字母“a”,用 “01100010”表示字母“b”,用“01100011”表示字母“c”…。由8个 0或者1的组成的串,一共有28即256种不同的组合,这就足以表示10个阿拉伯数字以及英语中用到的所有(大小写)字母和标点符号了。此即为ASCII编码方案。 - 图片、视频和可执行程序,也可以用0和1表示
十进制和K进制的互相转换
-
K进制转换为10进制
假设有一个n+1位的K进制数,它的形式如下: A n A n − 1 A n − 2 . . . A 2 A 1 A 0 A_nA_{n-1}A_{n-2}...A_2A_1A_0 AnAn−1An−2...A2A1A0,则其大小为:
-
10进制转换为K进制(短除法)
K进制数
A
n
A
n
−
1
A
n
−
2
.
.
.
A
2
A
1
A
0
A_nA_{n-1}A_{n-2}...A_2A_1A_0
AnAn−1An−2...A2A1A0可以通过下式转换为十进制数N:
那么十进制数N准换为K进制数,可以不断的除以K,N除以K所得余数为
A
0
A_0
A0,商是
(
A
1
+
A
2
×
K
1
+
.
.
.
+
A
n
×
K
n
−
1
)
(A_1+A_2\times K^1+...+A_n\times K^{n-1})
(A1+A2×K1+...+An×Kn−1). 将这个商再除 以K,就得到余数
A
1
A_1
A1,新的商
(
A
2
+
.
.
.
+
A
n
×
K
n
−
2
)
(A_2+...+A_n\times K^{n-2})
(A2+...+An×Kn−2),不停地将新得到的商除以K,直到商变成0,就能依次求得
A
0
,
A
1
,
.
.
.
,
A
n
−
1
,
A
n
A_0,A_1,...,A_{n-1},A_n
A0,A1,...,An−1,An。显然
A
i
<
K
(
i
=
0
,
.
.
.
,
n
)
A_i < K (i=0,...,n)
Ai<K(i=0,...,n),且最终得到的K进制数就是
A
n
A
n
−
1
A
n
−
2
.
.
.
A
2
A
1
A
0
A_nA_{n-1}A_{n-2}...A_2A_1A_0
AnAn−1An−2...A2A1A0.
-
十六进制数应该有16个数字,除0到9外:
小写也可以. -
十六进制转换10进制
-
十六进制和2进制互相转换
注意:4个2进制位对应一个16进制位
2. C++快速入门
为什么是C++而不是C语言
- C语言是好东西,但是有点弱
- C++ 更是好东西,但是有点烦
- 我们要学的,是C++的一部分,基本上就是:C语言+ STL (STL(标准模版库)是C++中能让你节省大量编程时间的神兵!) 。C++是面向对象的语言,因为暂时不写大程序,只实现一些算法,因此不用关心“面向对象”的事情!
C++程序示例
- 第一个C++程序
//头文件
#include <iostream>
#include <cstdio> //可以不加这一行 但可能会在oj上报错
using namespace std;
int main()
{
printf("Hello,world!"); //printf执行输出,字符串需要放在""内
return 0;
}
- 第二个C++程序:输出更多
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
int a = 3; //a是变量 用于存放数据,int表示类型 用于存放整数
printf("I have %d dollars.\n",a); //%d表示此处输出一个整数 整数的值是变量a的值
printf("I want to buy:\na book."); // \n表示换行 其后输出会从下一行开始;每条语句后要有;
return 0;
}
- 第三个C++程序:如何输入
输入两个整数,输出它们的和 (NOI.POJ 7883)
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
int a,b;
scanf("%d%d",&a,&b); //scanf执行输入功能 %d表示要等待输入一个整数 &a表示把输入整数放入变量a
printf("%d", a+b);
return 0;
}
输入字符
#include <iostream>
#include <cstdio>
using namespace std;
int main()
{
char a,b,c;
scanf("%c%c%c",&a,&b,&c); //%c表示读入一个字符 不会跳过空格
printf("%c%c%c",a,b,c);
return 0;
}
程序的注释
-
经常需要在程序中写点说明性的文字,帮助程序阅读者理解程序。这就需要用注释
-
程序的注释不是程序的一部分,不会对程序运行产生影响
-
一个函数的注释:一般包括功能说明,参数说明,返回说明以及内部关键语句的注释
-
多行注释: /* */
/* mp3 解码程序
author : Guo Wei programmed on 2011.5.18
*/
int main()
{
int bitrate; /* 比特率,以 Kbps为单位 */
int size; /* 以字节为单位 */
......
}
- 单行注释: //
int main()
{
int bitrate; // 比特率,以 Kbps为单位
int size; // 以字节为单位
......
}
程序文件的保存
- 本课程中的所有程序,都应该存为后缀名为 “.cpp”的文件然后编译,不能存成 “.c”文件!
3. 变量和数据类型
什么是变量
- 变量就是一个代号,程序运行时系统会自动为变量分配内存空间,于是变量就代表了系统分配的那片内存空间,对变量的访问,就是对其代表的内存 空间的访问。
- 变量有名字和类型两种属性,不同变量的名字就对应了内存中的不同地址 (即不同位置),而变量的类型,决定了一个变量占用多少个字节。变量名相当于房间号,类型相当于户型。
- 在C++语言中,变量要先定义,然后才能使用。“使用”有时也称为“引用”。读取或修改一个变量的值,都叫使用这个变量。定义变量的语句,要出现所有使用该变量的所有语句之前。
变量的定义
类型名 变量名1,变量名2,…,变量名n;
int number, price; //定义整型变量 number和price
一个变量不能定义两次:
int number;
double number; //错,前面已经有定义了
变量命名规则
- 变量由大小写字母、数字和下划线构成,中间不能有空格,长度不限,不能以数字开头。
- 变量名尽量做到见名知意
- 变量名是大小写敏感的,name 和 Name 是不同的两个变量。
- 变量名不能和C++系统预留的一些名字(保留字)重复。C++预留的保留字为:
此外还要注意不要取名为 begin 、 end 、 next 、 index、list、link 等
C++的数据类型
“数据类型”能够说明一个变量表示什么样的数据(整数,实数, 还是字符等)。不同数据类型的变量,占用的存储空间大小不同。
除了基本数据类型外,C++还允许程序员自定义数据类型。
C++的基本数据类型
- int,long,short,char的最高位(最左边)是符号位,为1则表示负数,为0表示非负数。
- 一个字节等于8个比特,即8个二进制位
注意这里double和float的表示范围是绝对值表示范围,左端表示接近0的程度,右端表示最大能到什么程度。一般使用double,范围更大,精度更高。
sizeof运算符
sizeof(变量名)
sizeof(类型名)
能够得到某个变量或某一类型变量占用的字节数。
int n1 = 10;
double f;
char c;
printf("%d,%d,%d,%d",sizeof(n1),sizeof(short),sizeof(double),sizeof(c)); //4,2,8,1
变量的初始化
- 变量在定义的时候,可以给它指定一个初始值,这叫变量的初始化。
int a = 4, b=3, c;
char ch ='a';
- 没有初始化的变量,其值一般是不确定的。
有符号整数和无符号整数
- short、int、long、long long 类型的变量,可以表示正数,也可以表示 负数,称为有符号的整数类型。
- unsigned short, unsigned int, unsigned long,unsigned long long类型的变量,只会被看作非负数,称为无符号的整数类型。
有符号整数的表示方式
- 将最左边的位(最高位)看作“符号位”。 符号位为0,则表示是非负数,其绝对值就是除符号位以外的部分;符号位为1,则表示是负数, 其绝对值是除符号位以外所有位取反(0变1,1变0)后再加1。
- 将一个负整数表示为二进制的方法:
- 设置符号位为1
- 其余位等于该负整数绝对值的2进制表示取反再加1
数据类型的自动转换
- 有些不同的数据类型之间是相容的,可以互相赋值, 这叫数据类型的自动转换
int a = 11.34; // 11.34被自动转换为11后赋值给a. 直接去掉小数部分
int b = 30;
double d = b; //d的值是30.0
- 字符类型到整型的互相转换
字符型数据(1 Byte)可以转换成整型数据:
int k = 'a'; //k内容变为'a'的ASCII码,即97
printf("%d",a);
整型数据也可以转换为字符型数据,但只会留下最右边的一个字节(第0位
到第7位),其他字节丢弃:
int n = 98; //98没有超过一个字节的表示范围
char k = n; //k内容变98,98是字符'b'的ASCII码
printf("%c",k); //输出:b
- 类型自动转换示例
#include <cstdio>
#include <iostream>
using namespace std;
int main()
{
int n1 = 1378; //1378的十六进制形式是 0x562(超过一个字节的表示范围) 0x开头代表十六进制
short n2;
char c = 'a'; //97
double d1 = 7.809;
double d2;
n2 = c+1; //n2变为98 , 97是'a'的ASCII码
printf("c=%c,n2=%d\n",c,n2); //输出 c=a,n2=98
c = n1; // n1是0x562(直接取低位的一个字节), 0x62(2+6*16=98)被当做ASCII码赋值给c,c变为 'b'
printf("c=%c,n1=%d\n",c,n1); //输出 c=b,n1=1378
n1 = d1;
printf("n1=%d\n", n1); //d1=7.809 去掉小数部分赋值给n1 n1=7
d2 = n1; //d2变为7
printf("d2=%f\n",d2); //输出 d2=7.000000
return 0;
}
4. 常量
什么是常量
- 常量就是在程序运行过程中值不会发生改变,而且一眼就能看出其值的量 如:12 ‘a’ 7.809 “Hello,C++”
- 常量也可以分成多种:整型,浮点型,字符型,字符串,符号常量
整型常量
- 十进制整型常量
0 123 -456 677363 - 十六进制整型常量,以“0x”开头
0x123 -0x1a 0x2abcdef 0xFFA 0x100
十六进制数中,用A(a)表示10, B(b)表示11 … F(f)表示15
一个十六进制位,正好对应于4个二进制位 F = ( 1111 ) 2 F = (1111)_2 F=(1111)2 - 八进制整型常量,以0开头
01 0123 -0456 0677
字符型常量
- 字符型常量表示一个字符,用单引号括起来,如:‘a’ ‘B’ ‘,’ ‘0’ ‘9’ ‘:’
- 字符型常量可用于给char 和unsigned char类型的变量赋值
char c = 'a';
unsigned char ch;
ch = '9';
- 字符型常量和变量都占一个字节,内部存放的是字符的ASCII编码。 ASCII编码是一个0~255的整数.
- C++中还有一类字符常量,以’‘开头,如’\n’、’\r’、’\t’等,称为“转义字符”。所 谓“转义”就是指’'后面的字符被转成别的含义。
字符串常量
- 字符串常量是用双引号括起来的一串字符 如:“a” “abc” “1234567”
- “” 也是一个字符串常量,它代表一个空串,即不包含任何字符的字符串
- "a"和’a’是不一样的,前者是只有一个字符的字符串,后者是一个字符,不能
用前者给一个char类型的变量赋值。 - "1234567"当然也和1234567是不一样的,不能用前者给一个int类型变量赋值。
- 字符串常量里可以包含转义字符
printf("123\t456\nabc\n");
printf("123\'45\n");
printf("UVWX\"YZ\n");
符号常量
- 为了阅读和修改的方便,常用一个由字母和数字组成的 符号来代表某个常量,这样的常量就叫符号常量
#define 常量名 常量值 //宏定义
- 定义之后,程序中所有出现“常量名”的地方,就等价于出现的是“常量值”
- “常量名”的命名规则和变量名相同,“常量值”则写什么常量都可以
#define MAX_NUM 1000
#define UNIVERSITY_NAME "Peking University"
#define MYINT i = 5;
- 尽量少使用数值常量,用符号常量替代它,这样便于修改