从C走进C++
- 程序的基本成分
- 数组和字符串(字符数组和字符串的差别)
- 函数和递归(汉诺塔问题)
- 指针
- 结构体和链表
- 对象和类
- 例题
一:程序的基本成分
- 数据成分,用以描述程序中所涉及的数据
- 运算成分,用以描述程序中所包含的运算
- 控制成分,用以表达程序中的控制构造
- 传输成分,用以表达程序中的数据传输
二:数组和字符串
对于字符数组,其长度是固定的,其中任何一个数组元素都可以为 null 字符。因此,字符数组不一定是字符串。
对于字符串,它必须以 null 结尾,其后的字符不属于该字符串。字符串一定是字符数组,它是最后一个字符为 null 字符的字符数组。
三:函数和递归(汉诺塔问题)
#include <stdio.h>
void Hanoi(int n,char from, char pass, char to)
{
if (n==1)
printf("把第%d块从%c移动到%c\n", n, from, to);
else
{
Hanoi(n - 1, from, to, pass);
printf("把第%d块从%c移动到%c\n", n, from, to);
Hanoi(n - 1, pass, from, to);
}
}
int main()
{
int n = 0;
scanf("%d", &n);
Hanoi(n, 'A', 'B', 'C');
}
四:指针
//指针的应用
#include <stdio.h>
int main()
{
char a[] = "I like it,too";
char *p = "I like C++";
printf("%s\n", p);
p+=5;
printf("%s\n", p);
p = a;
printf("%s\n", p);
}
//指针可以大大的提高效率
//例子
//用struct来实现英雄升级
#include <iostream>
#include <time.h>
using namespace std;
struct Hero {
long long blood;//英雄的血量
long long power;//英雄的力量
long long level;//英雄的等级
char name[64];//英雄的名字
char remarks[1024];//备注
};
//使用结构体
struct Hero upgrade_struct(struct Hero hero)
{
hero.blood += 10;//升一级加20点血
hero.power++;//升一级加1点力量
hero.level++;
return (hero);}
//使用指针实现
void upgrade_pointer(struct Hero* hero) {
hero->blood += 10;
hero->power++;
hero->level++;
}
//英雄属性初始化
void hero_reset(struct Hero* hero)
{
hero->blood = 50;
hero->level = 1;
hero->power = 10;
}
int main(void) {
time_t start, end;//定义时间戳
struct Hero hero;
strcpy(hero.name, "hero");
hero_reset(&hero);//初始化
time(&start);//获取1970年1月1日0时分0秒至现在的秒数,并存到start上
for (int i = 0; i < 999999999; i++) { //为了看出效率,我们制定一个庞大的升级任务,升级999999999次
upgrade_pointer(&hero); //基于指针的升级函数
//hero=upgrade_struct(hero); //基于结构体的升级函数
}
time(&end);//获取1970年1月1日0时分0秒至现在的秒数,并存到end上
cout << "hero's name: " << hero.name << endl;
cout << "hero's blood: " << hero.blood << endl;
cout << "hero's level: " << hero.level << endl;
cout << "hero's power: " << hero.power << endl;
cout << "based on pointer: " << end - start << endl;
//cout << “based on struct: " << end - start << endl;
cout << endl;
}
五:结构体和链表
六:对象和类
类的基本概念
类 :是具有相同属性和行为的一组对象的集合,它为属于该类的全部对象提供统一的的抽象描述
类和对象的关系:类是对象实例的抽象定义
类的实例——用类定义的类变量,即对象。类是对多个特性相同的对象实例的抽象,所以同一类的不同实例之间必有:
- 相同的操作集合
- 相同的属性集合
- 不同的对象名,分配有不同的存储空间
//应用举例
using namespace std;
#include "head.h"
#include <iostream>
class student
{
public:
char name[10];//姓名
char id[100];//学号
int age;//年龄
void test()
{
cout<<"test"<<endl;
}
void sport()
{
cout << "sport" << endl;
}
void go_to_class()
{
cout << "go to class" << endl;
}
};
int main()
{
student* jack = new student;
jack->age = 18;
strcpy_s(jack->name, "Jack");
cout << jack->name <<"'s age is "<<jack->age<< endl;
return 0;
}
结果:
写一个程序, 输入矩形的宽和高, 输出面积和周长
#include<iostream>
using namespace std;
//设计一个矩形类
class Rectangle
{
public:
int width;//宽
int height;//高
int Area()//求面积
{
return width*height;
}
int Perimeter()//周长
{
return 2 * (width + height);
}
void Init(int width_, int height_)//初始化
{
width = width_;
height = height_;
}
};
int main()
{
Rectangle r; //r是一个对象
int w, h;
cin >> w >> h;
r.Init(w, h);
cout << "面积为:"<< r.Area()<<endl;
cout << "周长为:" << r.Perimeter() << endl;
}
对象的内存分配
- 每个对象有各自的存储空间,一个对象的某个成员变量被改变,不会影响到其他对象
对象之间的赋值 - 可以通过“=”进行赋值但不能用“==”,“!=”,“>”,“<”等符号进行比较,除非这些运算符经过了重载
每个对象都有各自的储存空间
- 一个对象的某个成员变量被改变,不会影响到其他对象
int main()
{
Rectangle r1;
Rectangle r2;
int w, h;
cin >> w >> h;
r1.Init(w, h);
cin >> w >> h;
r2.Init(w, h);
cout << "m1的面积为:"<< r1.Area()<<endl;
cout << "m1的周长为:" << r1.Perimeter() << endl;
cout << "m2的面积为:" << r2.Area() << endl;
cout << "m2的周长为:" << r2.Perimeter() << endl;
}
类的成员访问
- 对象指针->成员名
int w=1, h=2;
Rectangle r1;
Rectangle* pr1=&r1;
pr1->Init(w, h);
pr1->width = 10;
cout << r1.width << endl;
cout << pr1->width << endl;
- 对象引用名.成员名
int w=1, h=2;
Rectangle r1;
Rectangle &r3=r1;
r3.Init(w, h);
r3.width = 10;
cout << r1.width << endl;
cout << r3.width << endl;
类的成员函数的两种写法
//第一种
class Rectangle
{
public:
int width;//宽
int height;//高
int Area()//求面积
{
return width*height;
}
int Perimeter()//周长
{
return 2 * (width + height);
}
void Init(int width_, int height_)//初始化
{
width = width_;
height = height_;
}
};
//第二种
class Rectangle
{
public:
int width;//宽
int height;//高
int Area();
int Perimeter();
void Init(int width_,int height_);
};
int Rectangle::Area()//求面积
{
return width*height;
}
int Rectangle::Perimeter()//周长
{
return 2 * (width + height);
}
void Rectangle::Init(int width_, int height_)//初始化
{
width = width_;
height = height_;
}
例题
一:倒过来输出
/*题目:将大小不超过int 范围的整数进行反转*/
/*思路:从右到左分离出整数的数字,排列成新的整数*/
//代码
#include<iostream>
using namespace std;
int main()
{
int N;
cin >> N;
if (N < 0) {
N = -N;
if (N < 10)
{
cout << "-";
cout << N;
return 0;
}
int place = 0, num = 0;
while (N > 0)
{
num = num * 10;
place = N % 10;
num = num + place;
N = N / 10;
}
cout << "-";
cout << num;
return 0;
}
else
{
if (N < 10)
{
cout << N;
return 0;
}
int place = 0, num = 0;
while (N > 0)
{
num = num * 10;
place = N % 10;
num = num + place;
N = N / 10;
}
cout << num;
return 0;
}
}
二:做游戏
#include<iostream>
using namespace std;
int main() {
int n = 0, m = 0, x, p = 0;
cin >> n; //n组测试数据
int** a = (int**)malloc(sizeof(int*)*n);
for (int i = 0; i < n; i++)
{
a[i] = (int*)malloc(sizeof(int) * 100);
for (int j = 0; j < 100; j++)
a[i][j] = 0;
}
for (p = 0; p<n; p++) {
cin >> m >> x; //输入M个小孩和X步
int* k = new int[m];
for (int i = 0; i<m; i++) {
cin >> k[i]; //输入初始编号
}
for (int i = 0; i<x; i++) {
int temp = k[0];
for (int i = 0; i<m - 1; i++) {
k[i] = (k[i + 1] + k[i]) % 100;
}
k[m - 1] = (temp + k[m - 1]) % 100;
for (int i = 0; i<m; i++) {
a[p][i] = k[i];
} }
for (int i = 0; i<m; i++) {
cout << a[p][i] << " "; //输出第p组(总共N组)
}
cout << endl;
}
return 0;
}
三:比较版本号
/*比较两个版本号 version1 和 version2。
输出版本号较大的。
你可以假设版本字符串非空,并且只包含数字和 . 字符。
. 字符不代表小数点,而是用于分隔数字序列。
例如,2.5 不是“两个半”,也不是“差一半到三”,而是第二版中的第五个小版本。
你可以假设版本号的每一级的默认修订版号为 0。例如,版本号 3.4 的第一级(大版本)和第二级(小版本)修订号分别为 3 和
4。其第三级和第四级修订号均为 0。
*/
#include<stdio.h>
int main()
{
int version1[100] = { 0 }, version2[100] = { 0 }, i, j, count1, count2, count;
char point;
for (count1 = 0; count1 < 100; count1++)
{
scanf("%d", &version1[count1]);
point = getchar();
if ((point == 13))
break; }
for (count2 = 0; count2< 100; count2++)
{
scanf("%d", &version2[count2]);
point = getchar();
if ((point == -1))
break; } //分别输入版本字符串1和版本字符串2
if (count1 > count2)
count = count1;
else
count = count2;
//选取较短的字符串长度,避免在比较中内存泄露
for (j = 0; j < count + 1; j++)
{
if (version1[j] > version2[j])
{
for (i = 0; i <= count1; i++)
{
printf("%d", version1[i]);
if (i < count1)
printf(".");
}
break; }
else if (version1[j]<version2[j])
{
for (i = 0; i <= count2; i++)
{
printf("%d", version2[i]);
if (i < count2)
printf(".");
}
break; }
//分别比较每个字符段,如果发现不同则可以立刻判断大小并且跳出循环
}
if (j == count + 1)
{
for (i = 0; i <= count; i++)
{
printf("%d", version2[i]);
if (i < count)
printf(".");
} }
printf("\n");
return 0;
}
四:岛屿周长
/*给定一个包含 0 和 1 的二维网格地图,其中 1 表示陆地 0 表示水域。网格中的格子水平和垂直方向相连(对角线方向不相连)。整个网格被水完全包围,但其中恰好有一个岛屿(或者说,一个或多个表示陆地的格子相连组成的岛屿)。岛屿中没有“湖”(“湖” 指水域在岛屿内部且不和岛屿周围的水相连)。格子是边长为 1 的正方形。网格为长方形,且宽度和高度均不超过 100 。计算这个岛屿的周长。
示例 :
[[0,1,0,0],
[1,1,1,0],
[0,1,0,0],
[1,1,0,0]]
答案: 16
解释: 它的周长是下面图片中的 16 个黄色的边
*/
#include <stdio.h>
int main()
{
int a, b, i, j, s;
int c[100][100] = { 0 }; s = 0;
scanf("%d%d", &a, &b);
for (i = 1; i < a + 1; i++)
{
for (j = 1; j < b + 1; j++)
{
scanf("%d", &c[i][j]);
} }
for (i = 1; i < a + 1; i++)
{
for (j = 1; j < b + 1; j++)
{
if (c[i][j] == 1)//如果该坐标为陆地,那么判断周围是否沿海,如果沿海,周长+1
{
if (c[i - 1][j] == 0)
s++;
if (c[i + 1][j] == 0)
s++;
if (c[i][j - 1] == 0)
s++;
if (c[i][j + 1] == 0)
s++;
} } }
printf("%d", s);
return 0;
}
重点防护
/*
描述
在战争中,物资运输和兵力运输是非常重要的,但是,有一些城市和交通线路往往只有要落入到敌人手中,那么由于这城市的失陷,使已方控制的区域就不在连通。就会给自己造成战争的被动。往往这些城市都是已方重点防护或敌人重点进攻的对象。假设你就是某军的最搞指挥官,当你无论拿到已方地图或敌方地图,你能否尽快的在瞬息万变的战场形式下快速的找到要重点保护或是重点进攻的城市?
输入
输入有多组数据,每一组数据表示一张地图城市信息。
每一组数据的第一行为一个整数N(N<=100),接着下面有m(m<=N)行描述这个地图的数据。其中每一行由多个数据组成a1,a2,…..ak组成。表示城市a1和a2,….ak有道理相连,各个数据之间用空格分开,如:输入数据5 1 2 3 4,那么表示,城市5和其它城市1,2 ,3, 4均有通路。每一组数据输入以0结束,整个输入同样以0结束。
输出
输出重点防护的城市个数。
样例输入
5
5 1 2 3 4
0
6
2 1 3
5 4 6 2
0
9
2 1 3
7 8
5 6 4
9 8
0
3
1 2 3
2 3
0
0
样例输出
1
2
3
0
*/
#include <stdio.h>
#include <malloc.h>
int main()
{
int temp = 0, i = 0, j = 0, k = 0, count0 = 0, temp2 = 0, id = 0;
char tempc;
int max_city = 101, temp_sum = 0, total_sum = 0;
int* answers = (int*)malloc(sizeof(int)*max_city);
int** city_map = (int**)malloc(sizeof(int*)*max_city);
for (i = 0; i < max_city; i++)
city_map[i] = (int*)malloc(sizeof(int)*max_city);
for (i = 0; i < max_city; i++)
{
for (j = 0; j < max_city; j++)
{
city_map[i][j] = 0;
} }//建立城市之间的路径图
while (1)
{
scanf("%d%c", &temp, &tempc);
if (temp == 0)
{
count0++;
if (count0 >= 2)
break;
total_sum = 0;
for (i = 0; i < max_city; i++)
{
for (j = 0; j < max_city; j++)
{
if (city_map[i][j] == 1)//若发现城市i和j中有连接
{
temp_sum = 0;
for (k = 0; k < max_city; k++)
temp_sum += city_map[k][j];
if (temp_sum == 1) //是否城市j只和一个城市(i)有连接
{
total_sum++; //如果是的话,则i是重点城市
break; } } } }
answers[id++] = total_sum;
for (i = 0; i < max_city; i++)
{
for (j = 0; j < max_city; j++)
{
city_map[i][j] = 0;
} }
continue; }
else
{
count0 = 0;
while (tempc == ' ') {
scanf("%d%c", &temp2, &tempc);
city_map[temp2][temp] = 1;
city_map[temp][temp2] = 1;
} } }
for (i = 0; i < id; i++)
printf("%d\n", answers[i]);
return 0;
}