C/C++程序设计
C/C++的联系与差异
联系:
c++是c的超集,完全涵盖了C语言的内容
差异
-C语言
- 结构化程序设计语言(面向过程)
- 侧重如何设计一个过程,对输入进行运算处理得输出
- 强调算法与数据结构
-C++
- 面向对象
- 侧重如何构造一个与描述问题相对应得的对象模型
- 融入抽象设计的概念
C/C++的输入与输出
-C语言
- 通过scanf与printf实现输入输出
-C++语言
- 保留scanf与printf实现输入输出,使用cin与cout操作进行输入输出
以下采用C++格式数据输出:
cout<<表达式1<<表达式2<<...<<表达式n;
- 说明
- cout代表显示器,‘<<’是插入运算符。表达式的值插入到显示器屏幕上,即输出各表达式的值。
- 各表达式可以是任意类型,数据的输出格式由系统自动决定
- 必须为‘<<’分隔,不能用逗号分隔。
- cout的定义信息存放在C++的输入输出流库中,所以使用如下的文件包含预处理命令以及名字空间说明语句。
#include<iostream>
using namespace std;
数据输出示例:
以下采用C++格式数据输入:
cin>>变量1>>变量2>>...>>变量n;
- 说明
- cin代表显示器,‘>>’是提取运算符。表示从键盘提取数据分别给各个变量,即输入各个变量的值。
- 变量可以是任意类型。表达式间必须为‘>>’分隔,不能用逗号分隔。
- 输入数据时,各数据用空格、换行、制表符分隔
- ‘>>’后面必须是变量,不能加endl
- cin的定义信息存放在C++的输入输出流库之中,所以使用cin程序之前要加:
#include<iostream>
using namespace std;
数据输入示例:
数据类型、运算符与表达式
数据类型
数据是程序的操作对象,具有不同的类型,常量变量形式表达。
- 作用
- 决定数据的存储空间
- 决定数据的取值范围。32位系统,整数范围 -231~231-1
- 决定数据所能参与的运算
- 分类
- 基本数据类型(不可再分)
- 整型 int
- 字符型 char
- 实型:单精度 float、双精度 double (存储空间、精度、取值范围不同)
- 构造类型:数组、结构体、共用体…(由基本数据类型合成的复杂类型)
- 指针类型(*)
- 空指针(void)
- 基本数据类型(不可再分)
变量
程序运行过程中值可变的数据
变量定义
数据类型 变量名表
- 要求
- 先定义后使用
- 参与运算前必须先被赋值,否则运算结果无效。
初始化
定义变量同时指定变量的初值
数据类型 变量名= 表达式
数据类型 变量名(表达式)
常量
程序运行过程中值不能被改变的数据
- 种类
- 值常量
- 符号常量
const 数据类型 标识符 = 常量值
#define 标识符 常量值
运算符
知识点省略,只取题目验证掌握程度
问题:如何编程实现华氏温度到摄氏温度的转化? 转化公式:
C
=
5
/
9
∗
(
F
−
32
)
C = 5 / 9 * (F - 32)
C=5/9∗(F−32)
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
double f,c;
cout << "请输入华氏温度:"<< endl;
cin >> f;
c = 5.0/ 9.0 * (f - 32);
cout << "对应的摄氏温度为:" << c << endl;
system("pause");
return 0;
}
在此处应注意:整数除法运算先去尾,再进行运算。 所以应为5.0 与9.0 浮点数运算
常见应用:
- 分解整数数位
- 判别整除关系
问题:求三位正整数m的个、十、百位
百位: m/100
十位: m%100/10
各位: m%10
控制结构
问题:利用公式
s
=
p
(
p
−
a
)
(
p
−
b
)
(
p
−
c
)
s = \sqrt{p(p-a)(p-b)(p-c)}
s=p(p−a)(p−b)(p−c)
编程求以a,b,c做三边的三角形面积。其中,p为三角形三边和的一半,即:p=(a+b+c)/2
顺序结构
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
double a, b, c, p, s;
cin >> a >> b >> c;
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
cout << "三角形面积为:" << s << endl;
system("pause");
return 0;
}
选择结构
还应判断是否构成三角形:
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
double a, b, c, p, s;
cin >> a >> b >> c;
if (a + b > c && a + c > b && b + c > a)
{
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
cout << "三角形面积为:" << s << endl;
}
else
{
cout << "输入有误无法构成三角形" << endl;
}
system("pause");
return 0;
}
switch循环:
switch(表达式)
{
case 常量表达式1:语句组1;[break;]
case 常量表达式2:语句组2;[break;]
...
case 常量表达式n:语句组n;[break;]
[default:语句组n+1]
}
- 说明
- 表达式必须为整型或者字符型;
- case常量表达式为一一列举的具体取值不是取值范围
- 多个常量表达式可用一组语句
循环结构
产生了新问题:输入有误时候如何继续输入新的三条边
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
double a, b, c, p, s;
cin >> a >> b >> c;
while (!(a + b > c && a + c > b && b + c > a))
{
cout << "输入有误无法构成三角形,重新输入:" << endl;
cin >> a >> b >> c;
}
p = (a + b + c) / 2;
s = sqrt(p * (p - a) * (p - b) * (p - c));
cout << "三角形面积为:" << s << endl;
system("pause");
return 0;
}
另外循环
for(m = 0; m<1000;m++)
do
{
}while(表达式);
数组
一维数组
问题:给定N个学生成绩,求高于平均分的学生人数
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
int k = 0;
float s[N], ave, sum = 0;
for (int i = 0; i < N; i++)
{
cin >> s[i];
sum = sum + s[i];
}
ave = sum / N;
for (int i = 0; i < N; i++)
{
if (s[i] > ave)
k++;
}
system("pause");
return 0;
}
- 数组的概念与特点
- 是同类型同性质的一组元素顺序存放构成的数据集合;
- 所有数据共同用一个名字,通过下标区分不同的数据
- 通过循环批处理
- 数组定义
数据类型 数组名[整型常量表达式]
- 数组名代表数组在内存中的首地址,地址由系统自动分配;
- 注意不可以如下定义
int n=5,s[n];
长度不允许用变量double d[];
长度不可为空float b[3.4];
长度不可为非整型
- 元素访问
数组名[下标]
- 一维数组的初始化
- 定义的同时允许为数组的部分或者全部元素赋值
问题:将十进制整数n转换成r(2~16)进制的形式
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
int i = 0, r, n, a[10];
char b[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
cin >> n >> r;
do
{
a[i] = n % r;
n = n / r;
i++;
} while (n!=0);
for ( --i; i >=0; --i)
{
n = a[i];
cout << b[n];
}
system("pause");
return 0;
}
二维数组
定义与存储
定义:
//表达式1代表行
数据类型 数组名[常量表达式1][常量表达式2]
问题:求一个3X3方阵的最大元素以及下标:
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
int a[][3] = { {0,0,1},{0,2,0},{3,0,0} };
int max = a[0][0];
int imax = 0, jmax = 0;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
{
if (a[i][j]>max)
{
max = a[i][j];
imax = i;
jmax = j;
}
}
}
cout << "max=" << a[imax][jmax] << endl;
cout << imax << jmax << endl;
system("pause");
return 0;
}
问题:矩阵转置
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
int i, j;
int a[3][3] = { {1,2,3},{4,5,6},{7,8,9} };
//for (i = 0; i < 3; i++)
//{
//for (j = 0;j<i;j++)
//{
//cout << a[i][j]<<" ";
//}
//cout << endl;
//}
for ( i = 0; i < 3; i++)
{
for (j = 0; j < i; j++)
{
cout << a[j][i] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
问题:杨辉三角
#include<iostream>
using namespace std; //使用std命名空间
const int n = 6;
int main()
{
int i, j;
int a[n][n];
//第一列与对角主线上的元素设为1
for ( i = 0; i < n; i++)
{
a[i][0] = a[i][i] = 1;
}
//其余元素
for ( i = 2 ; i < n; i++)
{
for (j = 1; j < i; j++) {
a[i][j] = a[i-1][j-1] + a[i-1][j];
}
}
//输出
for ( i = 0; i < n; i++)
{
for (j = 0; j <= i; j++)
{
cout << a[i][j] << " ";
}
cout << endl;
}
system("pause");
return 0;
}
字符串数组
问题:如何将任意长度的英文句子中的所有小写字母转换成大写字母
分析:
- 文本型数据,字符串数组描述;
- 每次处理的文本长度都在变化,如何输入;
- 将整个句子以字符串形式处理的;
#include<iostream>
#include<stdio.h>
using namespace std; //使用std命名空间
const int N = 100;
int main()
{
char s[N];
int i;
gets_s(s);
for ( i = 0; s[i]!='\0'; i++)
{
if (s[i] >= 'a' && s[i] <= 'z')
{
s[i] = s[i] - 'a' + 'A';
}
}
puts(s);
system("pause");
return 0;
}
定义与初始化
1.字符串为字符数组初始化
char s[] ={" I am fine"};
char s[] =" I am fine";
s是字符串,系统自动在末尾添加’\0’
2.字符串数组初始化
char s[3][8] ={" COBOL","FORTRAN","PASCAL"};
输入与输出
假设有定义char s[100];
- 字符串整体输出
cin>>s;
不能提取s中空白符后面的内容gets_s(s);
- 字符串整体输出
cout>>s;
puts(s);
函数gets与puts的原型说明在stdio.h中
字符串处理原则
- 整体输入输出
- 不用数组长度控制循环,而是通过当前字符是否达到’\0’判断循环结束与否
- 构造字符串时要保证结尾一定要有’\0’
问题1:复制字符串数组s到字符串t中
i = 0;
while(s[i]!='\0')
{
t[i] = s[i];
i++;
}
t[i] = '\0' //要保证构造字符串的末尾有'\0'
问题2:逐个比较两个字符串相对于位置的字符大小,输出“两个字符完全相等”的提示或者第一个不相等字符的ASCII码:
#include<iostream>
#include<stdio.h>
using namespace std; //使用std命名空间
const int N = 100;
int main()
{
char s[N],t[N];
int i;
gets_s(s);
gets_s(t);
i = 0;
while (s[i]!='\0'&&t[i]!='\0')
{
if (s[i] == t[i])
i++;
else
break;
}
if (s[i] != '\0' && t[i] != '\0')
cout << "两字符串相等" << endl;
else
cout << "两串相差" << s[i] - t[i];
system("pause");
return 0;
}
常用字符串处理
函数 | 作用 |
---|---|
strlen(str) | 求字符串str的长度,不包括’\0’ |
strlwr(str) | 大写换成小写 |
strupr(str) | 小写换成大写 |
strcpy(str1,str2) | 将str2所指的字符串复制到str1中 |
strcat(str1,str2) | 将字符串str2的内容连接到str1中 |
strcmp(str1,str2) | 比较str1与str2的大小(ASCII), 1小于2,返回-1;1等于2,返回0;1大于2,返回1 |
上述函数原型说明在头文件string.h中
指针与数组
指针的基本概念
概念
每个变量在内存中存放都对应一段地址,其中首字节即为变量的地址,将存放地址的变量成为指针变量。
定义
数据类型 *标识符;
- 数据类型代表指针所指向数据的类型;
- “*”不是变量名的一部分,仅仅是指针变量的一个标志;
初始化
在定义指针变量的同时为其赋一个地址值
int a = 5,*p=&a;
等价
int a =5,*p;
p=&a;
常用运算
赋值运算
假设有定义:int a,*p,*p1,*p2;
语句 | 含义 |
---|---|
p =NULL | 指针被赋值为NULL(0),表示不指向任何对象 |
p=&a | p指向变量a |
p1=&a;p2=p1 | 同类型的指针变量相互赋值 |
p=new int | 动态为p分配存放在一个整数的空间 |
p=new int[10] | 动态为p分配存放在10个整数的空间 |
假设有定义:int a,*p;float f;
需要避免:
1.随意将一个整数值赋值给指针变量:p=100
2.为指针变量赋予其类型不一样的变量的地址:p=&f
加减运算
- 假设p为指针变量,n为整数,则:p+n(p-n):指向p后面(前面)的第n个元素
- p++(p–)指向p后面(前面)的一个元素
指针相减运算
两个同类型指针变量相减的结果为这两个地址差之间能够存放的数据个数。如,有定义int *p1,*p2;
假设p1指向1000,p2指向1008,那么p2-p1的值为
指针与数组之间的关系
指针与一维数组
设有定义:int a[10],*p;
根据指针运算有以下等价关系:
1.p <=> a <=> &a[0]
2.p+i <=> a+i <=> &a[i]
3.*(p+i) <=> *(a+i) <=> a[i]
数组元素的表示
1.下标方式:数组名[下标]
2.地址方式:*(地址)
3.指针方式:*指针变量名
指针与字符串
问题:输入一字符串,用指针方式逐一显示字符,并求其长度。
#include<iostream>
using namespace std; //使用std命名空间
int main()
{
char *p, *q;
p = new char[100]; //为p可以申请能存放100个字符的空间
cin >> p;
q = p;//q记录字符串的首地址
cout << "输出每个字符";
while (*p!='\0') //出循环后p指向串尾
{
cout << *p++ << ' ';
}
cout << "\n字符串长度" << p - q << endl; //指针相减求得这段地址间存放的字符个数
system("pause");
return 0;
}