extern变量又称全局变量
extern 类型 变量名 = 初始化表达式 ;
register变量也属于局部变量。只能在函数体内定义register变量
只要是在外部,即不是在任何一个函数内定义的变量,编译器就将其当作全局变量,无论变量定义前是否有extern说明符
register 数据类型 变量1[=初始化表达式], 变量2[=初始化表达式]……;
static数据类型 变量1[=初始化表达式], 变量2[=初始化表达式]……; 与extern变量都是全局变量
static变量有静态全局变量和静态局部变量之分
C语言基础
#include<stdio.h> //预处理 用<>为系统提供 -> 用""为自定义 stdio.h为系统输入输出头文件
#include<stdlib.h>
//预处理作用:让系统知道有这个函数存在
//io->input output 接口->函数
//函数声明->函数原型
//返回值类型 函数名(参数列表);int add(int, int);
//函数功能:->参数 ->返回值
//测试函数
//每个项目有且仅有一个主函数
//项目的执行是从主函数开始,也是从主函数结束
//C语言的最小单位是函数->(行为,动作,接口,方法,数据处理)
//数据->属性,量
int main(int argc, char*argv[])
{
//printf(int a,...)
printf("Hello"); //printf -> stdio.h
system("pause"); //getchar(),加断点 解决跳闪
return 0;//函数与函数之间的数据交流 结束函数的作用
}
//数据交流:return,函数参数,全局变量
1.基本知识
什么是软件:一系列按照特定顺序组织的计算机数据和指令的集合
常见软件:系统软件,应用软件
什么是开发:制造软件
软件的出现实现了人与计算机之间的更好的交互
计算机组成:输入,输出,存储器,CUP(运算器,控制器)
位(bit):度量数据最小的单位
字节(byte):最常用的基本单位,一个字节有8位 1B(byte)=8b(bit)
K字节:1k=1024byte=2^10byte
M兆字节:1M=1024K=2^10K
G吉字节:
T太字节
进制转化2,8,10,16
正数的原码反码补码相同,移码变符号位
负数原码是二进制码符号位为1,反码在原码基础上符号位不变,其他位转变,补码在反码的基础上加1,移码在补码的基础上变符号位
计算机以补码保存,唯一性
+0 -0
原码:0000 0000 1000 0000
反码:0000 0000 1111 1111
补码:0000 0000 0000 0000
所有指令的集合称为计算机的指令系统
指令格式:操作码 操作数
32关键字
9中控制语句
运算符 优先级
CMD-DOS命令
typedef unsigned int u16;
//将unsigned int
简写成u16
,有了这句之后,u16 a;
等价于unsigned int a;
结构体
struct Students
{
int age_s;
float socre_s;
};
float MaxSocre(Student*s)
将Students简写成stu,等价于上面结构体
typedef struct Students
{
int age_s;
float socre_s;
}stu;//类型名
float MaxSocre(stu*s)
与上面相比缺少typedef,这里的stu为结构体变量名,Students类型的变量名
struct Students
{
int age_s;
float socre_s;
}stu;//变量名
实例
student.h文件
#ifndef STUDENT_H_
#define STUDENT_H_ //防止重复定义
//结构体
typedef struct Students{
int age_s;
float socre_s;
}stu;
float MaxSocre(stu*s); //形参
#endif;
student.c
#include"student.h"
float MaxSocre(Students*s)
{
return 0;
}
主函数文件
#include<stdio.h>
#include"student.h"
int main()
{
stu s[] = { { 12, 90.0 }, { 12, 90.0 }, { 12, 90.0 } };//定义多个stu对象,数组
//stu s[] = { 12, 90.0, 12, 90.0, 12, 90.0 };//等于上方
stu a = { 19, 98.8 }; //定义一个stu对象
MaxSocre(s); //实参 Students*s=s
MaxSocre(&a); //Students*s=&a
return 0;
}
实参与形参
#include<srdil.h>
//两个整形数据相加,将其和进行返回
//1.由实参传入
int add(int, int);//函数原型,只有续形式不带变量名,也可以写入变量名
int add(int a, int b);//同上
//定义
int add(int a1, int b1)
{
return a+b;
}
int add1()
{
int a,b;
scanf("%d %d",&a, &b);
return a+b;//int obj = a+b; int *obj = &(a+b);
//所有返回值类型都属于一个命名空间
}
//等式的左边:返回值类型,形参
//等式的右边:return 后面的表达式,实参
int main()
{
int a=5, b=7;
add(4, 4);//int a=4,b=4;
add(a, b);//int a=a,b=b;
add1();
int a; //整形变量->整形数据
int *p; //p指针变量->指针(地址)
p = &a;
int pr[4];//pr是一个地址常量
p = pr;
for (int i = 0; i<4; i++)
{
scanf_s("%d", p + i);//如果是p++最后p指向末尾,如果要用,需执行语句p=pr或p=p-4
}
//p = pr;
//p = p-4;
for int i=0;i<4;i++)
{
printf("%d",*p++);
}
p++;
return 0;
}
变量
//局部大于全局
int a=6; //全局变量
int main()
{
printf("%d\n", a); //6
int a=3;
printf("%d\n", a); //3
{//语句块
int a=5;
printf("%d\n", a); //5
}//语句块结束,其中的a被释放
printf("%d\n", a); //3
}
2021.5.23
C语言类型
构造类型 基本类型 指针类型 void空类型
基本类型:int, short, long, float, double, char, enum
构造<-基本类型
数组:int p[3]; int p[2][3];
结构体:struct(),union
int a; //a是整形变量
struct{ //匿名结构体
}s; //s是结构体变量
struct stu{ //stu是结构体类型名
}s; //s是stu结构体类型变量
typedef struct stu{ //stu是结构体类型名
}s; //s是stu结构体类型名
//只能合并不能拆解,一定要单一最大字节对齐,不够补充
typedef struct stu{
unsinged int age_s; //4字节,不够8个,score_s8个,则补4个,为8个
double score_s; //8个字节
unsinged int num_s; //4字节,不够8个,补四个,为8个
}s; //24字节
printf("%d\n", sizeof(s)); //24
typedef struct stu{
unsinged int age_s; //4字节,不够8个,num_s是4个,两则合并为8个
unsinged int num_s; //4字节,与age_s合并,总共8个
double score_s; //8个字节
}s; //16字节
printf("%d\n", sizeof(s)); //16
//最大字节用单独最大字节对齐,最大的为name_s[20]为20字节,单一最大为double 8字节,与其对齐为24字节,没有double则与单一最大字节int 4字节对齐,对齐字节为20
union stu{
char name_s[20];
unsinged int age_s; //
unsinged int num_s; //
double score_s; //
};
void 变量名; //void a;错误,不能直接声明变量
void 函数的返回值
void add(int, int);
void *malloc(int size_t);//空类型指针可以指向任意数据类型
int *p=(int*)malloc(sizeof(int)*5);
基本类型
void test()
{
int p[] = { 2, 34, 6 };
char str[] = "dasfdf";
printf("%d\n", sizeof(p) / sizeof(int)); //3
printf("%d\n", sizeof(str) / sizeof(char)); //7
printf("%d\n", strlen(str)); //6 cstring头文件,#include<cstring>
//用strlen求字符串长度不包括'\0'
//sizeof是运算符,不是函数
printf("%d\n", sizeof(long)); // 4
printf("%d\n", sizeof(int)); // 4
printf("%d\n", sizeof(short)); // 2
printf("%d\n", sizeof(float)); // 4
printf("%d\n", sizeof(double)); // 8
printf("%d\n", sizeof(char)); // 1
}
#include<math.h>
sqrt(); //开方
转义字符
字符串:每个字符串尾自动加入‘\0’作为字符串结束标志
字符用单引号,字符串用双引号
ASCII码值
大写字母转小写字母
char c1, c2;
c1 = 'A';
c2 = c1 + 32;
printf("%c\n", c2);
printf("%d\n", c2);
数据类型极限
定义常量——define/const
#define N 3;//N定义成一种符号,N只是3的别名,直接替换
const float N = 3;//定义成变量,值固定不变
//define只能放开头
const可以放任意位置,值是固定不变的
#define M 4+3*4 //直接替换,不加任何修饰
void test()
{
printf("%d", M * 5 + 4); //M*5+4=4+3*4*5+4=68
}
const int a = 3; //常量const修饰int->a
int b;//
const int *p1 = &a;//const修饰int->*p1 p1是指针变量->pi可变的
p1 = &a;
//*p1 = 2; //错误,*p是常量,不可变
int const* p2 = &b;//const修饰*p2
int * const p2 = &b;//const修饰p2 常量指针->必须有初值
2021.5.24
类型转换
隐式转换
不同数据类型直接运算会自定类型转换
强制类型转换
精度损失问题:较高类型向较低类型转换时可能发生
int main()
{
bool b = 33; //输出b为1
int a = b; //输出a为1 b进行隐式转换int
int a = (int)b; //显示转换int
//ctatic
void test()
{
unsigned char a = -1;//1000 0001->1111 1110->1111 1111 (0-255)无符号 -1补码无符号为255
printf("%d", a);//255
}
运算符
赋值的转换规则:使赋值号右边表达式值自动转换成其左边变量的类型
int i; i=2.56;则i=2
float f;int i;i=10; f=i;则f=10.0
void test()
{
int a = 2;
printf("%d\n", (a++, a++));// 3
int b=(3,4,5);//等于最后一个值5
int c=(a,b+3);//8 b=3
int d=(c++,c);//9 c
}
条件运算符的结合方向为“自右到左”
int a = 5, b = 6, c = 7, d = 8;
printf("%d\n",a>b ? a : c>d ? c : d);//a>b?a:(c>d?c:d) 8 从右到左,先(c>d?c:d)
void test()
{
int a = 2, b = 3;
//0000 0010
//0000 0011
//0000 0011
printf("%d\n", a | b);// 3
//0000 0010
//0000 0011
//0000 0010
printf("%d\n", a & b);//2
//0000 0010
//0000 0011
//0000 0001
printf("%d\n", a ^ b);//1
printf("%d\n", !a);//0 非0即1
}
输入与输出
#incldue<stdio.h>
输出——putchar字符、printf格式、puts字符串
输出格式符
中括号可以省
char name[4] = "asd";
char a[4];//a指针常量
strcpy_s(a, name); //#include<string> 复制
printf("%07s", a);//0000asd
printf("%s", a);
printf("%07.4f",10.0);//10.0000
putchar 函数是字符输出函数, 其功能是在显示器上打印单个字符
putchar(c);//c为字符型或整型数据,也可输出转义字符,如“\n”等.输出c所代表的一个字符
putchar('a');//a 字符数据也可以是一个字符常量
putchar(65);//A 整数
char c_var='a';
putchar(c_var);//a 字符型变量
putchar('a'+25);//z 表达式
putchar('\n'); //转义字符
puts函数功能非常单一,在显示器屏幕上输出一个字符串,并换行
puts(字符串);
puts("hello world"); //hello world
char a[4] = "af";
puts(a); // af
输入——getchar字符、scanf_s格式、gets_s
scanf_s:如果数据不止一个,应在数据之间用一个或多个空格间隔,也可以用回车键或跳格键tab间隔
scanf_s("%d,%d",&a,&b);输入时需要输入逗号用于匹配
int a, b;
scanf_s("%d,%d", &a, &b); //1,3
printf("%d,%d", a, b); //1,3
//指定输入的数据所占据的字符个数,scanf_s函数自动按照指示截取所需长度的数据
int a, b;
scanf_s("%3d%3d", &a, &b);
printf("%d,%d", a, b); // 123 456
//%后面的*格式符,用来表示在解析时,将读入的数据忽略不赋给任何变量
int a, b;
scanf_s("%d%*d%d", &a, &b);//1 2 3
printf("%d,%d", a, b);//1,3
如果格式字符串中有非空白字符,也就是除了格式控制字符和空白字符之外的字符,则用户在输入的时候一定也要输入这些字符。否则将出现不匹配格式控制字符串的情况
在用%c格式符时,空格字符和转义字符都被当作有效字符输入
char c1, c2, c3;
scanf_s("%c,%c,%c", &c1, 1, &c2, 1, &c3, 1);//a,b,c
printf("%c %c %c", c1, c2, c3);//a b c
char a[5], b[5];
scanf_s("%s%s", &a, sizeof(a), &b, sizeof(b)); // ab cd
printf("%s,%s", a, b); //ab cd
getchar 函数是得到用户输入的一个字符
char ch;
ch = getchar();//a
printf("%c", ch);//a
gets_s可以接受空格
scanf_s遇到空格、回车和Tab键都认为输入结束
//gets(), scanf();
void test()
{
char str[15];
gets_s(str); //abc def puts();
printf("%s\n", str); //abc def
//scanf_s在使用%c和%s读入字符或字符串时,应在地址参数后附加一个缓冲区边界值。使用sizeof
scanf_s("%s", &str, sizeof(str)); //abc def
printf("%s\n", str); //abc
}
strcpy_s字符串复制
strcpy(str2, str1); 将字符串1复制给字符串2
char p[5];
strcpy_s(p, "sa,");
printf("%s", p);
getchar(); 等待,按任意键继续
strcmp(str2, str1); 字符串比较
语句结构——if、switch、goto
if(a>b)
c = a;
else
c = b;
c = a>b?a:b; //等价于上方
switch (1 + 2)
{
case 2:
printf("2");
break;
case 3:
printf("3");
break;
default:
printf("0");
break;
}
continue//退出本次循环,进行下一个循环,只放循环语句中
break//退出该循环
int main()
{
int i = 0;
AAA:
i++;
if (i<5)goto AAA;
return语句中表达式的类型应与函数值类型一致。若不一致时,则以函数值的类型为准int max(float x)返回的是int类型(强转)
5.25
若有p=a(p指向数组a),则:
p++(或p+=1),表示p指向下一元素。
p++与(p++)等价。同样优先级,结合方向为自右向左。
(p++) 与(++p)。前者是先取p的值,后使p值加1,相当于a[i++];后者是先使p加1,再取p,相当于a[++i]。
(*p)++表示p所指向的元素值加1,而非指针值加1。
指针指向函数
int test(int a, int b)
{
if (a > b)
return a;
else
return b;
}
int main()
{
int a = 3, b = 4;
int (*p)(int, int);
p = test;
printf("%d", test(a, b));
printf("%d", p(a, b));
system("pause");
return 0;
}
void swap(int, int);//值传递,实参复制值给形参,单向传递,形参变化不影响实参变换 分配了两个整形数据空间
void swap(int*, int*);//指针传递,实参地址给形参,通过实参地址取实参数据进行交换,最后实参变化,形参分配了两个指针空间
//不要调用局部变量
int *max(int* a, int* b) // 返回指针函数
{
if (*a>*b)return a;
return b; // 返回值是指针
}
int main()
{
int a = 5, b = 3;
int c = *max(&a, &b);
system("pause");
return 0;
}
//形参赋值是从参数右边开始,连续,不能间断
//int add(int a=3, int b, int c) //错误
int add(int a, int b, int c=3)
{
return a + b + c;
}
int main()
{
printf("%d\n", add(2, 3));
printf("%d\n", add(2, 3, 5));
system("pause");
return 0;
}
5.26
可变参数…
/*
可变参数
1.首尾确定长度的
2.首尾结束符
va_list:首地址
va_strat:从首地址开始遍历参数
va_arg:从内存读取数据,类型转换
va_end:结束
*/
#include<stdarg.h>
int add(int num, ...)//最后一个数字为-1结束
{
int res = 0, arg;
va_list argp;
va_start(argp, num);
arg = num;
do{
res += arg;
arg = va_arg(argp, int);
} while (arg != -1);
va_end(argp);
return res;
}
int add1(int num, ...) //数字位数,相加的数字
{
int res = 0;
va_list argp;
va_start(argp, num);
for (int i = 0; i < num; i++)
res += va_arg(argp, int);
va_end(argp);
return res;
}
5.28
指针
/*
p[4][3]
p->整个数组的首地址
p+0
&p[0][0]->第0行第0列的地址
*(p+0)+0->第0行第0列的地址
p[0]->第0行的首地址
*(p+0)->第0行的首地址
*p
*/
void test()
{
int p[4][3];
printf("%x\t", p); // bff89c
printf("%x\t", &p[0][0]); // bff89c
printf("%x\t", &p[1][0]); // bff8a8
printf("%x\t", p[0]); // bff89c
printf("%x\t", p[1]); // bff8a8
printf("%x\t", *(p + 0)); // bff89c
printf("%x\t", *(p + 1)); // bff8a8
printf("%x\t", *p); // bff89c
printf("%x\t", *(p+0)+0); // bff89c
//p+11数组第11行,*p+11数组第11个数
printf("%x\t%x\t%x\t%x\t", &p[3][2], *(p + 3) + 2, *p + 11, p + 11);
//f3fa50 f3fa50 f3fa50 f3faa8
//地址加*为值
printf("%x\t", *(*(p+0)+0)); // 值
printf("%x\t", **p); // 值
printf("%d\t", *(&p[0][0])); // 值
printf("%d\t", *p[0]); // 值
printf("%d\t", **(p + 0)); // 值
}
双指针
int num = 3; //值3 地址0xffffff
int *p = #//值0xffffff 地址0xfffffc
int **p1 = &p;
/*
num = *p=3
&num = &(*p)=0xffffff
&num = p=0xffffff
*(&num)=*p=3
*(&p) = 0xffffff
**(&p) = 3
p1 = &p
*/
数组
相同类型的元素集合
#include<string.h>
void test()
{
char p[5] = { "abc" };
}
//4*3数组输出
void test(int p[][3])
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
printf("%d\t", *(p[i] + j)); //p[i][j]
printf("\n");
}
}
int main()
{
int p[4][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
//int p[][3] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 }; //等同于上方的
test(p);
return 0;
}
/*
void test(int (*p)[3])
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
printf("%d\t", p[i][j]);
printf("\n");
}
}
test(p);
void test(int *p)
{
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 3; j++)
printf("%d\t",*(p+i*3+j));
printf("\n");
}
}
test(*p);
*/
一维数组指针
int *ptr = NULL;
int arr[5];
ptr = arr;//p指针指向arr数组首地址
//arr[0] = *(ptr + 0) = *ptr = ptr[0] = *arr = *(arr + 0)
//&arr[0] = &(*ptr + 0) = &prt[0] = &(*arr) = ptr = arr
动态分配整形变量空间
int *ptr = (int*)malloc(sizeof(int));
*ptr = 5;
printf("%d\n", *ptr);
free(ptr);
动态分配数组空间
#define MaxSize 100
int *ptr = (int*)malloc(sizeof(int)*MaxSize);
for (int i = 0; i < MaxSize; i++)
{
scanf_s("%d", ptr + i);
}
for (int i = 0; i < MaxSize; i++)
{
printf("%d\n", *(ptr + i));
}
free(ptr);
ptr = NULL;
int test(int *a, int *b) //形参有存放整形数据的地址空间,返回值类型是存放数据空间
{
if (*a > *b)
return *a;
else
return *b;
}
int main()
{
int a = 1, b = 3; //存放整形数据空间
printf("%d\n", test(&a, &b));//存放整形数据的地址空间
/*
int (*p)(int*, int*);
p = &test;
(*p)(&a, &b);//等价于test(&a, &b)
*/
system("pause");
return 0;
}
5.31
student.h
#ifndef STUDENT_H_
#define STUDENT_H_
extern int Map[4][5];
#endif;
student.c
#include"student.h"
int Map[4][5] = { 1, 2 }; //定义,并且给该数组赋值
主函数test.c
#include<stdio.h>
#include<stdlib.h>
#include"student.h"
int main()
{
printf("%d\t%d\n", Map[0][0], Map[0][1]);
system("pause");
return 0;
}
//错误代码
char str[20];
str = "asg sdg e";
//正确代码
char *str;
str = "asg sdg e";
指针先有地址,再有值
int *p; //p先有地址,*p再有值
数组字符串赋值
char str[14];
str = "fsgerg";//错误,str是一个常量
//错误
char *a;
scanf_s("%s",a);
//正确
char *a, str[10];
a = str;
scanf_s("%s", a);
char *p;
p = (char*)"aggrag"; //const char[]
//p = "aggrag";
printf("%s\n", p);
//char *p = "aggrag"; //等价于上方
char str[] = { "afsdger" };
char str[] = "afsdger";
char str[] = { 'a', 'g', 'e' };
char *str = "ageg";
int a[] = { 1, 2, 3, 4, 5 };
结构体
结构体输入输出
#pragma warning(disable:4996)
struct Students
{
int num_t;
char sex_t;
float score_t;
char name_t[20];
}stu[N];
struct Students
{
int num_t;
char sex_t;
float score_t;
char name_t[20];
}stu;
struct Students
{
int num_t;
char sex_t;
float score_t;
char name_t[20];
}stu[N]={{}{}};
typedef struct Students
{
int num_t;
char sex_t;
float score_t;
char name_t[20];
}stu;
struct Students
{
int num_t;
char sex_t;
float score_t;
char name_t[20];
};
input(Students* p)
input(Students p)
共用体
//共用体,边输入边输出,否则会覆盖之前的值,两个变量只有一个用,总共分配20字节
//分配最大的空间,即只分配char[20]空间
union MyUnion
{
int num;
char name[20];
}ss;
int main()
{
scanf_s("%d", &ss.num);//使用char[20]空间
printf("%d", ss.num);
scanf_s("%s", ss.name);//使用char[20]空间
printf("%s", ss.name);
return 0;
}
移位
int a = 3;
printf("%d\n", a << 2); //12
printf("%d\n", a >> 2); //0
printf("%d\n", a ^ 2);//异或 相同为0,不同为1 0000 0010,0000 0011—>0000 0001
printf("%d\n", ~a);//取反 3的补码0000 0011->补码:1111 1100->反码:1111 1011-> 源码1000 0100-> -4
文件
//printf scanf gets puts getc putc
//fprintf fscanf fgets fputs fgetc fputc
//fprintf
//打开文件fopen(char *filename,char *mode)
/*
mode:
1.r/rb只读文件是已有的文件进行读,不存在不会创建
2.w/wb只写文件,没有该文件,会自动新建
3.a/ab向文件尾部追加数据
4.r+/rb+为读写建立文本
5.w+/wb+为读写建立文本
6.a+/ab+为读写打开或建立文本
FILE* fp;
char *filename = "a.txt"; //路径用反斜杠/或双斜杠\\
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("there are not file %s\n", filename);
}
fclose(fp);
写文件
fp = fopen(filename, "w");
if (fp == NULL)
{
printf("there are not file %s\n", filename);
}
fputs("abcdef", fp); //将字符串写入文件
读文件
char str[20];
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("there are not file %s\n", filename);
}
fgets(str, 20, fp);
printf("%s\n", str);//输出
puts(str);//输出
或
char str[20];
fp = fopen(filename, "r");
if (fp == NULL)
{
printf("there are not file %s\n", filename);
}
int i = 0;
while (!feof(fp))
{
str[i++] = fgetc(fp);
}
puts(str);//abcdef烫烫烫烫烫烫烫烫烫烫谈Xi
for (int j = 0; j < 7; j++)
printf("%c", str[j]); //abcdef
项目 属性 配置属性 调试命令参数后输入
int main(int argc, char* argv[])
{
while (argc > 1)
{
++argv;
printf(" % s\n", *argv);
--argc;
}
return 0;
}
俄罗斯方块项目
info.cpp
#include"info.h"
int gameMap[24][30] = { 0 };
int gscore = 0;
int glevel = 0;
int score = 0; //历史分数
//记录19种图形的结构体,这个思维数组初学者还是不太容易理解的
char g_aCubeShape[7][4][4][4] = {
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 0, 0 }, //■■
{ 1, 1, 0, 0 } // ■■
},
},
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 1 } //■■■■
},
{
{ 0, 1, 0, 0 }, //■
{ 0, 1, 0, 0 }, //■
{ 0, 1, 0, 0 }, //■
{ 0, 1, 0, 0 }, //■
},
},
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 1, 1, 0 }, // ■■
{ 1, 1, 0, 0 } //■■
},
{
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 }, //■
{ 1, 1, 0, 0 }, //■■
{ 0, 1, 0, 0 } // ■
}
},
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 0, 0 }, //■■
{ 0, 1, 1, 0 } // ■■
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 }, // ■
{ 1, 1, 0, 0 }, //■■
{ 1, 0, 0, 0 } // ■
}
},
{
{
{ 0, 0, 0, 0 },
{ 1, 1, 0, 0 }, //■■
{ 0, 1, 0, 0 }, // ■
{ 0, 1, 0, 0 } // ■
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 0, 1, 0 }, // ■
{ 1, 1, 1, 0 } //■■■
},
{
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 }, //■
{ 1, 0, 0, 0 }, //■
{ 1, 1, 0, 0 } //■■
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 0 }, //■■■
{ 1, 0, 0, 0 } //■
}
},
{
{
{ 0, 0, 0, 0 },
{ 1, 1, 0, 0 }, //■■
{ 1, 0, 0, 0 }, //■
{ 1, 0, 0, 0 } //■
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 1, 1, 0 }, //■■■
{ 0, 0, 1, 0 } // ■
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 }, // ■
{ 0, 1, 0, 0 }, // ■
{ 1, 1, 0, 0 } //■■
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 },//■
{ 1, 1, 1, 0 } //■■■
}
},
{
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 }, // ■
{ 1, 1, 1, 0 } //■■■
},
{
{ 0, 0, 0, 0 },
{ 1, 0, 0, 0 }, //■
{ 1, 1, 0, 0 }, //■■
{ 1, 0, 0, 0 } //■
},
{
{ 0, 0, 0, 0 },
{ 0, 0, 0, 0 }, //
{ 1, 1, 1, 0 }, //■■■
{ 0, 1, 0, 0 } // ■
},
{
{ 0, 0, 0, 0 },
{ 0, 1, 0, 0 }, // ■
{ 1, 1, 0, 0 }, //■■
{ 0, 1, 0, 0 } // ■
}
},
};
//设置缓冲区窗口,开机动画
void openAnimal()
{
SetConsoleTitleA("俄罗斯方块");
HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
COORD size = { 90, 50 };
SetConsoleScreenBufferSize(handle, size);
SMALL_RECT rect = { 0, 0, 90 - 1, 50 - 1 };
//设置窗体大小
SetConsoleWindowInfo(handle, true, &rect);
}
//初始化地图
void initMap()
{
memset(gameMap, 0, sizeof(gameMap));
for (int y = 0; y < 24; y++) {
for (int x = 0; x < 30; x++) {
if (x == 0 || y == 0 || x == 29 || y == 23)
{
gameMap[y][x] = WALL;
//printf("%d",gameMap[y][x]);
}
}
//printf("\n");
}
}
//将字符串写入windows窗口,并设置颜色
void WriteWchar(int x, int y, const char szString[], int attr)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//API
COORD pos = { x * 2, y };
SetConsoleTextAttribute(hOut, attr);
SetConsoleCursorPosition(hOut, pos);
printf("%s", szString);
}
//绘制游戏地图
void drawMap()
{
for (int y = 0; y < 24; y++) {
for (int x = 0; x < 30; x++) {
if (gameMap[y][x] == WALL)
WriteWchar(x, y, "■", F_H_WHITE);
else {
WriteWchar(x, y, " ", F_H_WHITE);
}
}
printf("\n");
}
//右边的设置
WriteWchar(34, 2, "俄罗斯方块", F_H_GREEN);
//绘制分数、等级、下一个方块
WriteWchar(32, 5, "分数:", F_H_GREEN);
WriteWchar(32, 7, "等级:", F_H_GREEN);
//把成绩格式化到缓存区
char buf[6] = { 0 };
sprintf_s(buf, sizeof(buf), "%d", gscore);
//sprintf(buf, "%d", gscore); vc 6.0写法
WriteWchar(36, 5, buf, F_H_GREEN);
//绘制等级
char buf1[6] = { 0 };
//把等级格式化输出到缓存区中
sprintf_s(buf1, sizeof(buf1), "%d", glevel);
sprintf(buf1, "%d", glevel); vc 6.0写法
WriteWchar(36, 7, buf1, F_H_GREEN);
WriteWchar(32, 11, "NEXT:", F_H_GREEN);
WriteWchar(32, 17, "操作说明:", F_H_GREEN);
WriteWchar(34, 19, "(W)键 变形", F_H_GREEN);
WriteWchar(34, 20, "<-(A)键 ->(D)键", F_H_GREEN);
WriteWchar(34, 21, "↓(S)键", F_H_GREEN);
}
//获取随机的形状,方向,颜色
void getRandom(pRandom pRand)
{
srand(time(NULL));
//随机生成
pRand->shape = rand() % 7;//0-6
pRand->dir = rand() % 4;//0-3
pRand->color = rand() % 11;
//特殊处理,比如:第一种形状,没有必要随机变化方向
//因为不知道什么时候会产生第一种形状
while (true)
{
if (pRand->shape == 0) {
pRand->dir = 0;
break;
}
else if (pRand->shape == 1 && pRand->dir > 1)
{
pRand->dir = rand() % 4;
}
else if (pRand->shape == 2 && pRand->dir > 1)
{
pRand->dir = rand() % 4;
}
else if (pRand->shape == 3 && pRand->dir > 1)
{
pRand->dir = rand() % 4;
}
else
break;
}
//随机分配颜色
switch (pRand->color)
{
case 0:
pRand->color = F_BLUE;
break;
case 1:
pRand->color = F_H_BLUE;
break;
case 2:
pRand->color = F_GREEN;
break;
case 3:
pRand->color = F_H_GREEN;
break;
case 4:
pRand->color = F_RED;
break;
case 5:
pRand->color = F_H_RED;
break;
case 6:
pRand->color = F_YELLOW;
break;
case 7:
pRand->color = F_H_YELLOW;
break;
case 8:
pRand->color = F_PURPLE;
break;
case 9:
pRand->color = F_H_PURPLE;
break;
case 10:
pRand->color = F_CYAN;
break;
default:
break;
}
}
//获取形状
void getShape(pShapeInfo shape)
{
Random m_ran = { 0 };
COORD pos = { 15, 3 };
getRandom(&m_ran);//重新获取随机数
//下一个形状
shape->isMove = TRUE;
shape->pos = pos;
shape->ran = m_ran;
}
//绘制图形
void drawShape(ShapeInfo shape)
{
//printf("%d,\t%d",shape.pos.X,shape.pos.Y);
for (int y = shape.pos.Y - 3; y <= shape.pos.Y; y++)
{
for (int x = shape.pos.X - 3; x <= shape.pos.X; x++)
{
//WriteWchar(x, y, " ", F_H_WHITE);
if (g_aCubeShape[shape.ran.shape][shape.ran.dir][y - shape.pos.Y + 3][x - shape.pos.X + 3])
{
gameMap[y][x] = SHAPE;
WriteWchar(x, y, "■", shape.ran.color);
}
}
}
//有可能方块图案出生时将边框覆盖掉。
for (int X = 12; X <= 15; X++)
{
gameMap[0][X] = WALL;
WriteWchar(X, 0, "■", F_WHITE);
}
}
//右边显示下一个出现的图形
void drawNextShape(ShapeInfo shape)
{
COORD pos = { 38, 15 };
for (int y = pos.Y - 3; y <= pos.Y; y++)
{
for (int x = pos.X - 3; x <= pos.X; x++)
{
WriteWchar(x, y, " ", F_H_WHITE);//先清除在画
if (g_aCubeShape[shape.ran.shape][shape.ran.dir][y - pos.Y + 3][x - pos.X + 3]) {
WriteWchar(x, y, "■", shape.ran.color);
}
}
}
}
//清除原先形状(4*4数组),为新形状变化后,使得地图干净
void clsShape(ShapeInfo shape)
{
for (int y = shape.pos.Y - 3; y <= shape.pos.Y; y++)
{
for (int x = shape.pos.X - 3; x <= shape.pos.X; x++)
{
if (g_aCubeShape[shape.ran.shape][shape.ran.dir][y - shape.pos.Y + 3][x - shape.pos.X + 3])
{
WriteWchar(x, y, " ", F_BLUE);
gameMap[y][x] = 0;
}
}
}
}
//判断形状是否移动
BOOL isMove(ShapeInfo shape)
{
for (int y = shape.pos.Y - 3; y <= shape.pos.Y; y++)
{
for (int x = shape.pos.X - 3; x <= shape.pos.X; x++)
{
if (gameMap[y][x] == WALL && g_aCubeShape[shape.ran.shape][shape.ran.dir][y - shape.pos.Y + 3][x - shape.pos.X + 3])
return FALSE;
}
}
return TRUE;
}
//相当于画,擦,判段方块都在这里面
void drawMoveShape(pShapeInfo newShape, pShapeInfo oldShape)
{
//方块在移动
if (isMove(*newShape))
{
//擦除就方块
clsShape(*oldShape);
//绘制新方块
drawShape(*newShape);
//更新方块信息
*oldShape = *newShape;
return;//结束此方法
}
//方块左右碰到墙壁
ShapeInfo shape = *oldShape;
shape.pos.Y++;
if (isMove(shape))
{
//更新方块信息
*newShape = *oldShape;
return;
}
newShape->isMove = FALSE;
}
//通过键盘控制图形变化方向,左移,右移,加速下移
void keyControl(pShapeInfo shape)
{
char ch = _getch();
switch (ch)
{
case 72:
case 'w':
case 'W':
if (shape->ran.shape == 0)
shape->ran.dir = 0;
else if (shape->ran.shape == 1 || shape->ran.shape == 2 || shape->ran.shape == 3)
shape->ran.dir = (shape->ran.dir+1) % 2;//0-1
else shape->ran.dir = (shape->ran.dir+1) % 4;
break;
case 75:
case 'a':
case 'A':
shape->pos.X--;
break;
case 77:
case 'd':
case 'D':
shape->pos.X++;
break;
case 80:
case 's':
case 'S':
shape->pos.Y++;
break;
default:
break;
}
}
void drawFallShape(ShapeInfo shape)
{
for (int y = shape.pos.Y - 3; y <= shape.pos.Y; y++)
{
for (int x = shape.pos.X - 3; x <= shape.pos.X; x++)
{
if (g_aCubeShape[shape.ran.shape][shape.ran.dir][y - shape.pos.Y + 3][x - shape.pos.X + 3])
{
gameMap[y][x] = WALL;
WriteWchar(x, y, "■", F_GREEN);
}
}
}
}
//消除函数
void clsRow(int posY)
{
//将以找到的满行,标为红色
for (int x = 1; x < 29; x++)
{
WriteWchar(x, posY, "■", F_H_RED);
}
Sleep(100);//休眠0.1s
//将以找到的满行,填充空格
for (int x = 1; x < 29; x++)
{
gameMap[posY][x] = 0;
WriteWchar(x, posY, " ", F_H_RED);
}
//从posY行上方所有格子下移
for (int x = 1; x < 29; x++)
{
for (int y = posY - 1; y > 3; y--)
{
if (!gameMap[y][x])
break;
for (int i = y + 1; i <= 22; i++)
{
if (!gameMap[i][x]) //只有格子为空才进行下移
{
//下一行使用绿色填充
gameMap[i][x] = WALL;
WriteWchar(x, i, "■", F_H_GREEN);
gameMap[y][x] = 0;//将上一行清空
WriteWchar(x, y, " ", F_H_WHITE);
continue;
}
break;
}
}
}
gscore += 100;
switch (gscore / 100)
{
case 3:
glevel++;
break;
default:
break;
}
}
//遍历行,和列满,并处理行满返回TRUE,列满返回FALSE
BOOL findFull()//查看行和列是否满
{
for (int y = 22; y > 3; y--) {
label:
int count = 0;
for (int x = 1; x < 29; x++)
{//列满,游戏结束
for (int j = 1; j < 29; j++)
if (gameMap[4][j] == 1)return FALSE;
//行满
//1.有空格就跳下一行
if (!gameMap[y][x])break;
//2.不是空格
count++;
}//列识别结束
if (count == 28)//行满消行
{
//消行
clsRow(y);
count = 0;
y = 22;
goto label;
}
}//行
//分数和等级显示
//把成绩格式化到缓存区
char buf[6] = { 0 };
sprintf_s(buf, sizeof(buf), "%d", gscore);
//sprintf(buf, "%d", gscore); vc 6.0写法
WriteWchar(36, 5, buf, F_H_GREEN);
//绘制等级
char buf1[6] = { 0 };
//把等级格式化输出到缓存区中
sprintf_s(buf1, sizeof(buf1), "%d", glevel);
sprintf(buf1, "%d", glevel); vc 6.0写法
WriteWchar(36, 7, buf1, F_H_GREEN);
return true;
}
//欢迎界面
void drawPic(){
//相对于电脑
//定义四个坐标点
COORD posDown = { 9, 0 };
COORD posUp = { 29, 41 };
COORD posRight = { 39, 11 };
COORD posLeft = { 0, 29 };
//设定死循环
int k = -20;
while (true)
{
Sleep(100);
if (k < 2)
{
system("cls");
k++;
if (k>0) WriteWchar(9, k, " ■■ ", F_RED);
if (k>-1) WriteWchar(9, k + 1, " ■■ ■■ ", F_RED);
if (k>-2) WriteWchar(9, k + 2, "■■■■ ■■ ■■ ■■ ■■ ■■", F_RED);
if (k>-3) WriteWchar(9, k + 3, "■■■■ ■■ ■■■■ ■■ ■■ ■■ ", F_RED);
if (k>-4) WriteWchar(9, k + 4, "■■■■ ■■ ■■■■ ■■■■■■ ■■■■■■ ■■■■■■", F_RED);
if (k>-5) WriteWchar(9, k + 5, "■■■■ ■■ ■■ ■■■■■■ ■■■■■■ ■■■■■■", F_RED);
if (k>-6) WriteWchar(9, k + 6, " ■■ ■■ ", F_RED);
if(k>-7) WriteWchar(9, k + 7, " ■■ ", F_RED);
if (k>-10) WriteWchar(9, k + 10, " ■■■■■■ ■■ ■■ ■■ ■■ ", F_RED);
if (k>-11) WriteWchar(9, k + 11, " ■■■■■■ ■■ ■■■ ■■ ■■ ", F_RED);
if (k>-12) WriteWchar(9, k + 12, " ■■ ■■ ■■ ■■ ■■ ■■■■ ", F_RED);
if (k>-13) WriteWchar(9, k + 13, " ■■ ■■ ■■ ■■ ■■ ■■■ ", F_RED);
if (k>-14) WriteWchar(9, k + 14, " ■■■■■■ ■■ ■■■■■■ ■■", F_RED);
if (k>-15) WriteWchar(9, k + 15, " ■■■■■■ ■■ ■■■■■■ ■■ ", F_RED);
if (k>-16) WriteWchar(9, k + 16, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
if (k>-17) WriteWchar(9, k + 17, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
}
else
break;
}
//执行控制台命令cls,就是CMD下面的cls,功能是清屏,清除所有显示的信息。
system("cls");
WriteWchar(9, 4, " ■■ ", F_RED);
WriteWchar(9, 5, " ■■ ■■ ", F_RED);
WriteWchar(9, 6, "■■■■ ■■ ■■ ■■ ■■ ■■", F_RED);
WriteWchar(9, 7, "■■■■ ■■ ■■■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 8, "■■■■ ■■ ■■■■ ■■■■■■ ■■■■■■ ■■■■■■", F_RED);
WriteWchar(9, 9, "■■■■ ■■ ■■ ■■■■■■ ■■■■■■ ■■■■■■", F_RED);
WriteWchar(9, 10," ■■ ■■ ", F_RED);
WriteWchar(9, 11," ■■ ", F_RED);
WriteWchar(9, 14, " ■■■■■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 15, " ■■■■■■ ■■ ■■■ ■■ ■■ ", F_RED);
WriteWchar(9, 16, " ■■ ■■ ■■ ■■ ■■ ■■■■ ", F_RED);
WriteWchar(9, 17, " ■■ ■■ ■■ ■■ ■■ ■■■ ", F_RED);
WriteWchar(9, 18, " ■■■■■■ ■■ ■■■■■■ ■■", F_RED);
WriteWchar(9, 19, " ■■■■■■ ■■ ■■■■■■ ■■ ", F_RED);
WriteWchar(9, 20, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 21, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
//分数
readFile();
//检测键盘是否输入,检测当前输入的键盘是否是enter键
while (!(_kbhit() && _getch() == 0x0d)){
WriteWchar(27, 26, "press enter to start", F_RED);
}
//清零屏幕
system("cls");
}
//读文件
void readFile()
{
WriteWchar(23, 24, "最高分:", F_RED);
FILE *fp;
errno_t err;
char filename[20] = "a.txt";
err = fopen_s(&fp, filename, "r");
fscanf_s(fp, "%d", &score);
char str[20];
_itoa_s(score, str, 10);
WriteWchar(28, 24, str, F_RED);
fclose(fp);
}
//写文件
void writeFile()
{
if (gscore > score)
{
FILE *fp;
errno_t err;
char filename[20] = "a.txt";
err = fopen_s(&fp, filename, "w");
fprintf_s(fp, "%d", gscore);
fclose(fp);
}
}
//结束动画
void drawOver(){
//相对于电脑
//定义四个坐标点
COORD posDown = { 9, 0 };
COORD posUp = { 29, 41 };
COORD posRight = { 39, 11 };
COORD posLeft = { 0, 29 };
//设定死循环
//执行控制台命令cls,就是CMD下面的cls,功能是清屏,清除所有显示的信息。
system("cls");
WriteWchar(9, 7, "■■■■ ■■ ■■■■■ ■■■ ■■ ■ ■ ■■■ ■■■ ", F_RED);
WriteWchar(9, 8, "■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ", F_RED);
WriteWchar(9,9, "■ ■■ ■■■■ ■ ■ ■ ■■■ ■ ■ ■ ■ ■■■ ■■■ ", F_RED);
WriteWchar(9, 10, "■ ■ ■ ■ ■ ■ ■ ■ ■ ■ ■■ ■ ■■ ", F_RED);
WriteWchar(9, 11, "■■■■ ■ ■ ■ ■ ■ ■■■ ■■ ■ ■■■ ■ ■", F_RED);
WriteWchar(20, 18, "本次游戏获得的分数是:", F_RED);
char str[20];
_itoa_s(gscore, str, 10);
WriteWchar(32, 18, str, F_RED);
//检测键盘是否输入,检测当前输入的键盘是否是enter键
while (!(_kbhit() && _getch() == 0x0d)){
}
//清零屏幕
system("cls");
}
//游戏实现函数
void playGame()
{
ShapeInfo newShape, nextShape, oldShape;//定义形状
getShape(&newShape);//获取形状
drawShape(newShape);
oldShape = newShape;
getShape(&nextShape);//获取形状
drawNextShape(nextShape);
int time = 10000;
while (TRUE) {
//绘制下一个方块,去查看方块本身属性
if (newShape.isMove == FALSE)
{
//到把以下落不能移动方块对应的值修改为1,为墙
drawFallShape(oldShape);
//消行且计分或则上方已经满
if (findFull() == FALSE)break;
newShape = nextShape;
oldShape = nextShape;
getShape(&nextShape);//获取形状
drawNextShape(nextShape);//绘制下一个图形
drawShape(newShape);//绘制移动的图形
}
time--;
if (!time)
{
//绘制移动形状
newShape.pos.Y++;
drawMoveShape(&newShape, &oldShape);
time = 10000;
}
if (!_kbhit())
{
continue;
}
keyControl(&newShape);
drawMoveShape(&newShape, &oldShape);
}
WriteWchar(12, 8, "游戏结束!", F_RED);
WriteWchar(8, 12, "本次游戏获得的分数是:", F_RED);
char str[20];
_itoa_s(gscore, str, 10);
WriteWchar(20, 12, str, F_RED);
drawOver();
writeFile();
}
info.h
#ifndef INFO_H_
#define INFO_H_
/*头文件*/
#include <stdio.h>//
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <conio.h>//键值
#define WALL 1//墙壁
#define SHAPE 2//图形
// 字体颜色
#define F_BLUE FOREGROUND_BLUE // 深蓝
#define F_H_BLUE 0x0001|0x0008 // 亮蓝
#define F_GREEN 0x0002 // 深绿
#define F_H_GREEN 0x0002|0x0008 // 亮绿
#define F_RED 0x0004 // 深红
#define F_H_RED 0x0004|0x0008 // 亮红
#define F_YELLOW 0x0002|0x0004 // 深黄
#define F_H_YELLOW 0x0002|0x0004|0x0008 // 亮黄
#define F_PURPLE 0x0001|0x0004 // 深紫
#define F_H_PURPLE 0x0001|0x0004|0x0008 // 亮紫
#define F_CYAN 0x0002|0x0004 // 深青
#define F_H_CYAN 0x0002|0x0004|0x0008 // 亮青
#define F_WHITE 0x0004|0x0002|0x0001//白
#define F_H_WHITE 0x0004|0x0002|0x0001|0x0008//空白
/*变量声明*/
extern int gameMap[24][30];
extern char g_aCubeShape[7][4][4][4];
extern int gscore;
extern int glevel;
/*结构体声明*/
//获取随机数
typedef struct _RANDOM{
//4种方向0-3
int dir;
//7种图形0-6
int shape;
//11颜色0-10
int color;
}*pRandom, Random;
typedef struct _SHAPEINFO {
//是否移动
BOOL isMove;
//坐标
COORD pos;
//获取随机的形状,方向,颜色
Random ran;
}*pShapeInfo, ShapeInfo;
/*函数声明*/
void openAnimal();//设置缓冲区窗口,开机动画
void initMap();//初始化地图
//绘制设置位置和颜色
void WriteWchar(int x, int y, const char szString[], int attr);
void drawMap();//绘制地图
获取随机的形状,方向,颜色
void getRandom(pRandom pRand);
//绘制图形
void drawShape(ShapeInfo shape);
//下一个图形
void drawNextShape(ShapeInfo shape);
//获取形状
void getShape(pShapeInfo shape);
//清楚形状
void clsShape(ShapeInfo shape);
//判断形状是否移动
BOOL isMove(ShapeInfo shape);
//相当于画,擦,判段方块都在这里面
void drawMoveShape(pShapeInfo newShape, pShapeInfo oldShape);//绘制移动图形
void keyControl(pShapeInfo shape);//按键控制游戏
void drawFallShape(ShapeInfo shape);//不再移动的形状处理
//行满,消行并统计分数
void clsRow(int posY); //消除行
BOOL findFull();//遍历行,和列满,并处理行满返回TRUE,列满返回FALSE
void drawPic();//欢迎界面
void readFile();//读文件
void writeFile();//写文件
void drawOver();
void playGame();
#endif // !INFO_H_
test.cpp
#include"info.h"
#include<stdlib.h>
int main()
{
drawPic(); //开始界面
openAnimal();//设置window窗口
initMap();//初始化地图
drawMap();//绘制地图
playGame();
drawOver();//结束界面
//getchar();
return 0;
}
推箱子项目
test.cpp
#include"info.h"
#include<stdio.h>
int main()
{
drawPic(); //开始界面
PleyGame(); //开始游戏
return 0;
}
info.h
#ifndef INFO_H_
#define INFO_H_
/*头文件*/
#include <stdio.h>
#include <stdlib.h>
#include <Windows.h>
#include <time.h>
#include <conio.h>
// 字体颜色
#define F_BLUE FOREGROUND_BLUE // 深蓝
#define F_H_BLUE 0x0001|0x0008 // 亮蓝
#define F_GREEN 0x0002 // 深绿
#define F_H_GREEN 0x0002|0x0008 // 亮绿
#define F_RED 0x0004 // 深红
#define F_H_RED 0x0004|0x0008 // 亮红
#define F_YELLOW 0x0002|0x0004 // 深黄
#define F_H_YELLOW 0x0002|0x0004|0x0008 // 亮黄
#define F_PURPLE 0x0001|0x0004 // 深紫
#define F_H_PURPLE 0x0001|0x0004|0x0008 // 亮紫
#define F_CYAN 0x0002|0x0004 // 深青
#define F_H_CYAN 0x0002|0x0004|0x0008 // 亮青
#define F_WHITE 0x0004|0x0002|0x0001 //白
#define F_H_WHITE 0x0004|0x0002|0x0001|0x0008//空白
/*函数声明*/
//绘制设置位置和颜色
void WriteWchar(int x, int y, const char szString[], int attr);
void drawPic(); // 欢迎界面
void drawMap(); // 绘制游戏地图
int PleyGame(); // 开始游戏
int MoveMap(); // 移动
void readFile(); // 读文件
void Winter(); // 绘制胜利界面
void writeFile(); // 写文件
void GameOver(); // 结束界面
void CopyMap(); // 复制关卡
void anew(); // 从新开始
#endif // !INFO_H_
info.cpp
#include"info.h"
int gscore = 0; //游戏步数
#define N 15
#define M 3
int limit[M] = { 30, 100, 100 }; //步数限制
int level = 0;
int game[15][15]; //保存当前关卡地图
//关卡,地图
int gameMap[M][15][15] = {//0空白 1墙 3目的地 4箱子 5人
{//关卡1
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 4, 0, 4, 3, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 3, 0, 4, 5, 1, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 1, 1, 1, 1, 4, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 3, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
{//关卡2
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 1, 3, 3, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 1, 0, 3, 1, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 1, 0, 0, 4, 3, 1, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 0, 4, 0, 0, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 4, 4, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 5, 0, 0, 0, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
{//关卡3
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 0, 3, 4, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 4, 0, 0, 4, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 0, 1, 3, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 1, 3, 0, 5, 1, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
}
};
//复制关卡
void CopyMap()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
game[i][j] = gameMap[level][i][j];
}
}
}
//从新开始
void anew()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
gameMap[level][i][j] = game[i][j];
}
}
gscore = 0;
}
//将字符串写入windows窗口,并设置颜色
void WriteWchar(int x, int y, const char szString[], int attr)
{
HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//API
COORD pos = { x * 2, y };
SetConsoleTextAttribute(hOut, attr);
SetConsoleCursorPosition(hOut, pos);
printf("%s", szString);
}
//读文件
void readFile()
{
WriteWchar(43, 5, ".............................", F_GREEN);
WriteWchar(43, 6, ":", F_GREEN);
WriteWchar(57, 6, ":", F_GREEN);
WriteWchar(43, 7, ":", F_GREEN);
WriteWchar(57, 7, ":", F_GREEN);
WriteWchar(43, 8, ":", F_GREEN);
WriteWchar(57, 8, ":", F_GREEN);
WriteWchar(43, 9, ":", F_GREEN);
WriteWchar(57, 9, ":", F_GREEN);
WriteWchar(43, 10, ":", F_GREEN);
WriteWchar(57, 10, ":", F_GREEN);
WriteWchar(43, 11, ":", F_GREEN);
WriteWchar(57, 11, ":", F_GREEN);
WriteWchar(43, 12, ":", F_GREEN);
WriteWchar(57, 12, ":", F_GREEN);
WriteWchar(43, 13, ":", F_GREEN);
WriteWchar(57, 13, ":", F_GREEN);
WriteWchar(43, 14, ":", F_GREEN);
WriteWchar(57, 14, ":", F_GREEN);
WriteWchar(43, 15, ":", F_GREEN);
WriteWchar(57, 15, ":", F_GREEN);
WriteWchar(43, 16, ".............................", F_GREEN);
WriteWchar(49, 7, "排行榜", F_GREEN);
WriteWchar(45, 10, "关卡1最快步数:", F_GREEN);
WriteWchar(45, 12, "关卡2最快步数:", F_GREEN);
WriteWchar(45, 14, "关卡3最快步数:", F_GREEN);
FILE *fp;
int a[M];
errno_t err;
char str[20];
err = fopen_s(&fp, "a.txt", "r");
for (int i = 0; i < M; i++)
{
fscanf_s(fp, "%d", &a[i]);
_itoa_s(a[i], str, 10);
WriteWchar(55, 10 + 2*i, str, F_GREEN);
}
fclose(fp);
}
//欢迎界面
void drawPic(){
//相对于电脑
//定义四个坐标点
COORD posDown = { 9, 0 };
COORD posUp = { 29, 41 };
COORD posRight = { 39, 11 };
COORD posLeft = { 0, 29 };
//设定死循环
int k = -20;
while (true)
{
Sleep(100);
if (k < 2)
{
system("cls");
k++;
if (k>0) WriteWchar(9, k, " ■■■ ■■■■ ■■■■", F_YELLOW);
if (k>-1) WriteWchar(9, k + 1, " ■☆■ ■☆☆■ ■ ■■■", F_YELLOW);
if (k>-2) WriteWchar(9, k + 2, " ■ ■■■■ ■■ ☆■■ ■■■ ☆□ ■", F_YELLOW);
if (k>-3) WriteWchar(9, k + 3, " ■■■□ □☆■ ■ □☆■ ■ □ □ ■ ", F_YELLOW);
if (k>-4) WriteWchar(9, k + 4, " ■☆ □○■■■ ■■ □ ■■ ■ ■☆ ■", F_YELLOW);
if (k>-5) WriteWchar(9, k + 5, " ■■■■□■ ■ ■□□ ■ ■■■☆ ○■■", F_YELLOW);
if (k>-6) WriteWchar(9, k + 6, " ■☆■ ■ ○ ■ ■■■■■", F_YELLOW);
if (k>-7) WriteWchar(9, k + 7, " ■■■ ■■■■■■■■ ", F_YELLOW);
if (k>-10) WriteWchar(9, k + 10, " ■■■■■■ ■■ ■■ ■■ ■■ ", F_RED);
if (k>-11) WriteWchar(9, k + 11, " ■■■■■■ ■■ ■■■ ■■ ■■ ", F_RED);
if (k>-12) WriteWchar(9, k + 12, " ■■ ■■ ■■ ■■ ■■ ■■■■ ", F_RED);
if (k>-13) WriteWchar(9, k + 13, " ■■ ■■ ■■ ■■ ■■ ■■■ ", F_RED);
if (k>-14) WriteWchar(9, k + 14, " ■■■■■■ ■■ ■■■■■■ ■■", F_RED);
if (k>-15) WriteWchar(9, k + 15, " ■■■■■■ ■■ ■■■■■■ ■■ ", F_RED);
if (k>-16) WriteWchar(9, k + 16, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
if (k>-17) WriteWchar(9, k + 17, " ■■ ■■■■■■ ■■ ■■ ■■ ", F_RED);
}
else
break;
}
//分数
readFile();
//检测键盘是否输入,检测当前输入的键盘是否是enter键
while (!(_kbhit() && _getch() == 0x0d)){
WriteWchar(43, 24, "press enter to start", F_RED);
}
//清零屏幕
system("cls");
}
//绘制游戏地图
void drawMap()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
switch (gameMap[level][i][j])
{
case 0:
WriteWchar(j, i, " ", F_YELLOW);
break;
case 1:
WriteWchar(j, i, "■", F_YELLOW);
break;
case 3:
WriteWchar(j, i, "☆", F_YELLOW);
break;
case 4:
WriteWchar(j, i, "□", F_YELLOW);
break;
case 5:
WriteWchar(j, i, "○", F_YELLOW);
break;
case 7: //4 + 3 箱子在目的地中
WriteWchar(j, i, "★", F_YELLOW);
break;
case 8: // 5 + 3 人在目的地当中
WriteWchar(j, i, "○", F_YELLOW);
break;
}
}
}
//右边的设置
WriteWchar(34, 2, "推箱子", F_H_GREEN);
//绘制分数、等级、下一个方块
WriteWchar(32, 5, "步数:", F_H_GREEN);
WriteWchar(32, 7, "关卡:", F_H_GREEN);
char buf[6] = { 0 };
sprintf_s(buf, sizeof(buf), "%d", gscore);
WriteWchar(36, 5, buf, F_H_GREEN);
char buf1[6] = { 0 };
sprintf_s(buf1, sizeof(buf1), "%d", level+1);
WriteWchar(36, 7, buf1, F_H_GREEN);
WriteWchar(32, 14, "操作说明:", F_H_GREEN);
WriteWchar(37, 15, "W(上", F_H_GREEN);
WriteWchar(37, 16, "A(左)", F_H_GREEN);
WriteWchar(37, 17, "D(右)", F_H_GREEN);
WriteWchar(37, 18, "S(下)", F_H_GREEN);
WriteWchar(37, 20, "Q(退出)", F_H_GREEN);
WriteWchar(37, 21, "T(从新开始)", F_H_GREEN);
}
//移动
int MoveMap()
{
int r, c; //人的坐标
for (int i = 0; i < 9; i++)
{
for (int j = 0; j < 11; j++)
{
if (gameMap[level][i][j] == 5 || gameMap[level][i][j] == 8) //i j 人的下标
{
r = i;
c = j;
}
}
}
char ch; //字符变量
ch = _getch(); //键盘的输入保存到字符中
switch (ch)
{
case 'W': //W A S D方向 72 80 75 77 虚拟键值
case 'w':
case 72:
if (gameMap[level][r - 1][c] == 0 || gameMap[level][r - 1][c] == 3)
{
gameMap[level][r - 1][c] += 5;
gameMap[level][r][c] -= 5;
gscore++;
}
else if (gameMap[level][r - 1][c] == 4 || gameMap[level][r - 1][c] == 7)
{
if (gameMap[level][r - 2][c] == 0 || gameMap[level][r - 2][c] == 3)
{
gameMap[level][r - 2][c] += 4;
gameMap[level][r - 1][c] += 1;
gameMap[level][r][c] -= 5;
gscore++;
}
}
break;
case 'S': //enter按键的作用 确认 返回
case 's':
case 80:
if (gameMap[level][r + 1][c] == 0 || gameMap[level][r + 1][c] == 3)
{
gameMap[level][r + 1][c] += 5;
gameMap[level][r][c] -= 5;
gscore++;
}
else if (gameMap[level][r + 1][c] == 4 || gameMap[level][r + 1][c] == 7)
{
if (gameMap[level][r + 2][c] == 0 || gameMap[level][r + 2][c] == 3)
{
gameMap[level][r + 2][c] += 4;
gameMap[level][r + 1][c] += 1;
gameMap[level][r][c] -= 5;
gscore++;
}
}
break;
case 'A':
case 'a':
case 75:
if (gameMap[level][r][c - 1] == 0 || gameMap[level][r][c - 1] == 3)
{
gameMap[level][r][c - 1] += 5;
gameMap[level][r][c] -= 5;
gscore++;
}
else if (gameMap[level][r][c - 1] == 4 || gameMap[level][r][c - 1] == 7)
{
if (gameMap[level][r][c - 2] == 0 || gameMap[level][r][c - 2] == 3)
{
gameMap[level][r][c - 2] += 4;
gameMap[level][r][c - 1] += 1;
gameMap[level][r][c] -= 5;
gscore++;
}
}
break;
case 'D':
case 'd':
case 77:
if (gameMap[level][r][c + 1] == 0 || gameMap[level][r][c + 1] == 3)
{
gameMap[level][r][c + 1] += 5;
gameMap[level][r][c] -= 5;
gscore++;
}
else if (gameMap[level][r][c + 1] == 4 || gameMap[level][r][c + 1] == 7)
{
if (gameMap[level][r][c + 2] == 0 || gameMap[level][r][c + 2] == 3)
{
gameMap[level][r][c + 2] += 4;
gameMap[level][r][c + 1] += 1;
gameMap[level][r][c] -= 5;
gscore++;
}
}
break;
case 'q': //退出
case 'Q':
return 0;
case 'T': //从新开始
case 't':
anew(); // 从新开始当前关卡
}
return 1;
}
//是否胜利
BOOL isWin()
{
for (int i = 0; i < N; i++)
{
for (int j = 0; j < N; j++)
{
if (gameMap[level][i][j] == 3 || gameMap[level][i][j] == 4)
return false;
}
}
return true;
}
//绘制胜利界面
void Winter()
{
system("cls");
WriteWchar(9, 10, " ■■ ■■ ■■ ■■■■ ■■■ ■■ ", F_RED);
WriteWchar(9, 11, " ■■ ■■■ ■■ ■■ ■■■■ ■■ ", F_RED);
WriteWchar(9, 12, " ■■ ■■■■ ■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 13, " ■■ ■■ ■■ ■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 14, " ■■■■ ■■■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 15, " ■■■ ■■■ ■■ ■■ ■■■■ ", F_RED);
WriteWchar(9, 16, " ■■ ■■ ■■■■ ■■ ■■■ ", F_RED);
WriteWchar(27, 20, "exit:q", F_RED);
WriteWchar(27, 23, "continue:r", F_RED);
}
//写文件
void writeFile()
{
FILE *fp;
int a[M];
errno_t err;
char str[20];
err = fopen_s(&fp, "a.txt", "r");
for (int i = 0; i < M; i++)
{
fscanf_s(fp, "%d", &a[i]);
_itoa_s(a[i], str, 10);
WriteWchar(55, 10 + 2 * i, str, F_GREEN);
}
fclose(fp);
if (a[level] == 0 || gscore < a[level])
{
a[level] = gscore;
err = fopen_s(&fp, "a.txt", "w");
fprintf_s(fp, "%d\n", a[0]);
fprintf_s(fp, "%d\n", a[1]);
fprintf_s(fp, "%d\n", a[2]);
fclose(fp);
}
}
//结束界面
void GameOver()
{
system("cls");
WriteWchar(9, 10, " ■■ ■■ ■■ ■■■■■ ■■■■■■ ", F_RED);
WriteWchar(9, 11, " ■■ ■■ ■■ ■■ ■■■■■ ■■■■■■ ", F_RED);
WriteWchar(9, 12, " ■■ ■■ ■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 13, " ■■ ■■ ■■ ■■ ■■■■■ ■■■■■■ ", F_RED);
WriteWchar(9, 14, " ■■ ■■ ■■ ■■ ■■■■■ ■■■■ ", F_RED);
WriteWchar(9, 15, " ■■ ■■ ■■ ■■ ■■ ■■ ■■ ", F_RED);
WriteWchar(9, 16, " ■■ ■■ ■■■ ■■■■■ ■■ ■■ ", F_RED);
WriteWchar(9, 17, " ■■ ■■ ■■■■■ ■■ ■■ ", F_RED);
while (true){
WriteWchar(43, 24, "exit:q", F_RED);
if (_getch() == 'q')
{
break;
}
}
}
//开始游戏
int PleyGame()
{
drawMap();//绘制游戏地图
CopyMap(); //复制关卡
while (true)
{
if (gscore > limit[level])
{
WriteWchar(12, 7, "超过步数失败按enter从新开始", F_RED);
gscore = 0;
anew();
while (!(_kbhit() && _getch() == 0x0d))
{
}
}
if(!MoveMap()) // 移动,退出
return 0;
system("cls");
drawMap();//绘制游戏地图
if (isWin())
{
writeFile();
gscore = 0;
level = (level + 1);
CopyMap(); //复制关卡
if (level >= M) //超过规定关卡则退出
return 0;
Winter(); //绘制胜利界面
while (true)
{
if (_getch() == 'q')
{
return 0;
}
if (_getch() == 'r')
{
system("cls");
drawMap();
break;
}
}
}
}
return 0;
}
C++
2021.6.7
友元:朋友,要使用成员仍必须通过对象 friend
静态成员:属于类,静态成员在类外定义 static
?using
有多少使用方式
constexpr
,const
四种对象的使用
int a; int *p; int arr[3]; int &ap = a;
类名 a; 类名 *p=nullptr;(NULL) 类名 arr[3]; 类名 &p = a;
抽象类至少拥有一个纯虚函数,此类不能定义对象,可以定义对象指针或引用
抽象类一般都是作为父类存在
cout
、cin
都是对象
#include<iostream>
//istream ostream
//using namespace std;
int main()
{
int a = 3;
char str[3] = "sa";
std::cout << "3" << std::endl;
std::cout << a << std::endl;
std::cout << str << std::endl;
getchar();
return 0;
}
3
3
sa
#include<iostream>
using namespace std;
int main()
{
int a = 3;
char str[3] = "sa";
cout << "3" << endl;
cout << a << endl;
cout << str << endl;
getchar();
return 0;
}
3
3
sa
域
#include<iostream>
using namespace std;
namespace ddd{
int a = 3;
};
int a = 2;
int main()
{
int a = 7;
cout << "a=" << ::a << endl; // 5 ::前没加相当于全局变量
cout << "a=" << ddd::a << endl; // 3 ::前有ddd相当于ddd域里的变量
cout << "a=" << a << endl; // 7 前面什么都没有为该区域变量
getchar();
return 0;
}
a=2
a=3
a=7
静态成员
#include<iostream>
using namespace std;
void func();
int main()
{
//静态成员:只初始化一次,它有记忆功能,最后才释放空间,下回使用时会计入上次的值
//a为静态成员,b不是
//第一次定义a=5,b=4,a++,结果a=6,b=10
func();//a=6,b=10
//第二次使用上一次的值,即a=6,b=4
func();//a=7,b=11
//第三次使用上一次的值,即a=7,b=4
func();//a=8,b=12
getchar();
return 0;
}
void func()
{
static int a = 5;
int b = 4;
a++;
b = a + b;
cout << "a=" << a << ",b=" << b << endl;
}
a=6,b=10
a=7,b=11
a=8,b=12
类
#include<iostream>
using namespace std;
//class/struct有相同的作用
//默认为public公有属性
struct students{ //students类名->类类型名
private:
int a;//不能在这直接给值,这里没有空间
public:
//const只能修饰类中函数,成为常函数
//常函数只能获取值,不能修改值,即const只能获取值,不能修改值
int getA()const; //void getA();
void setA(int a); // void setA();
}s1;//对象名
int students::getA()const
{//类中的函数可以使用类中所有成员,不需要通过对象
return a;//cout<<a<<endl;
}
void students::setA(int a)
{//通过传入参数a给本对象的私有成员a赋值
this->a = a;//cin>>a;
}
//默认为private私有属性
class Student{ //
int b;//私有
}s2;
int main()
{//类外所定义的对象只能用类中的公有成员
//在类外函数要使用类中成员,必须通过对象(只有对象才是实体)
//int a;int*p;int arr[3];int ≈
//对象创建时系统自动调用构造函数,给其数据成员初始化 上面有new
//对象结束时系统自动调用析构, 下面就有delete
students stu, *sut1 = nullptr, arr[3];//0-2
stu.setA(3);
cout<<stu.getA()<<endl;//3
//*sut1 = nullptr
stu1 = &stu;
(&stu)->setA(4);
(*stu1).setA(5);
stu1->setA(6);
cout<<stu1->getA()<<endl; // 6
for (int i = 0; i < 3; i++)
{
arr[i].setA(i+2);//(arr+i)->setA(i+2);
}
for (int i = 0; i < 3; i++)
{
cout << arr[i].getA() << endl;
}
getchar();
return 0;
}
//enum web{a, b=2, c}; //无赋值为0
enum class web{a, b, c};
int main()
{
int k;
//k = a;//隐式转换
k=static_cast<int>(web::a); //显示类型转换
k = (int)web::a; //强转
cout << k << endl; //0
getchar();
return 0;
}
左值引用
#include<iostream>
using namespace std;
//左值引用
class AAA{
int x, y; //数据成员->属性
public:
//成员函数->方法->数据处理
void setInfo(int a, int b);
int getX()const;
int getY()const;
};
void AAA::setInfo(int a, int b)
{
x = a;
y = b;
}
int AAA::getX()const
{
return x;
}
int AAA::getY()const
{
return y;
}
/*void swap(int, int);//值传递
void swap(int*, int*);//指针传递
*/
void swap(int&a, int&b)//引用传递
{
int temp;
temp = a;
a = b;
b = temp;
}
int main()
{//左值引用是给响应的变量取别名,不会分配自己的空间
//引用必须定义时给其赋初值,赋的必须是变量名
//引用名用法与普通变量名用法相同
int a = 3;
int &b = a;//int &b;会报错,没有初始化
cout << "a=" << a << ",b=" << b << endl;//a=3b=3
cout << "&a=" << &a << ",&b=" << &b << endl;//&a=00CFFEAC&b=00CFFEAC
AAA a1;//通过AAA类类型定义对象a1
AAA &b1 = a1;//给a1取别名b1
b1.setInfo(3, 4);
cout << "b1.x=" << b1.getX() << ",b1.y=" << b1.getY() << endl;//b1.x=3,b1.y=4
int a=3, b=4;
swap(a, b);
getchar();
return 0;
}
6.8
输入
cin get(),getline(),read()
gcount(),ignore(),sync(),clear()
char str;
str = cin.get();//原型int get();
cout << "str=" << str << endl;
q
str = q
形式不一样,含义一样
cin.get(str);//istream& get(char&c) //char&c = str;
cout << "str=" << str << endl;
q
str = q
char str[20];
cin.getline(str, 20); //首地址,字符长度 可以获取空格
cout << str << endl;
ahge rglieg a
ahge rglieg a
char str[20];
cin.getline(str, 20, '#');//读取字符从#结束
cout << str << endl;
dsfer#w
dsfer
char str[20];
cin.read(str, 20);//块语句读法,只有满足字符长度才结束,可以获取换行,空格等
cout << "str=" << str << endl;
afe gg
ger grege
fsg er
str=afe gg
ger grege
fsg烫烫E^彎曾
char str[20];
cin.get(str, 20);
cout << "input char number:" << cin.gcount() << endl;
awef fwef
input char number : 9
char str[20];
cin.getline(str, 5);//Study C++!
cout << str << endl;//Stud
cin.clear();//设置失效位,从新打开输入流
cin.getline(str, 20);//y C++!
cout << str << endl;
Study C++!
Stud
y C++!
int m;
cin >> m;
char str[20];
cin.ignore();//cin.ignore(int);cin.ignore(int,char);
cin.getline(str, 20);
cout << "m=" << m << endl;
cout << "str=" << str << endl;
5
f er sdf
m=5
str=f er sdf
int m;
cin >> m;
char str[20];
//cin.ignore();
cin.getline(str, 20);
cout << "m=" << m << endl;
cout << "str=" << str << endl;
忽略cin.ignore();
5
m=5
str=
cin.sync();//清空输入缓冲区
int a;
bool b;
char c;
double d;
//cin >> a >> b >> c >> d;//需要对应格式输入,空格区分
//cout << a << b << c << d;
cin >> a;
//cin >> b;//bool输入0,1
cin >> boolalpha >> b;
cout << a << " " << boolalpha << b << endl;
int a = 17;
cout << hex << a;//十六进制输出
float a = 17.6;
cout << hexfloat << a;
#include<cstdio> //stdio.h
#include<cmath> //math.h
#include<cstring>//srlen,strcpy
string
#include<string>
int a(1), b = 2;//给a,b赋除值
cout << a << endl;//1
cout << b << endl;//2
char str[] = "中国江西"; //一个中文两个字符,反斜杠结束符为一个字符
cout << sizeof(str) / sizeof(char) << endl; //9
string s1 = "This is a test string ";
string s2("teacher"); //使用字符串常量初始化
//string(string&,int n);
string s3(s1); //使用string对象初始化,对象给新对象赋初值
string s4(str, 4); //使用字符数组前4个字符初始化
string s5(s1, 10, 12);//使用string对象子串初始化,10起始位,12长度
cout << "s1:" << s1 << endl;
cout << "s2:" << s2 << endl;
cout << "s3:" << s3 << endl;
cout << "s4:" << s4 << endl;
cout << "s5:" << s5 << endl;
9
s1:This is a test string
s2:teacher
s3:This is a test string
s4:中国
s5:test string
内存动态分配new,delete
void test()
{
//内存动态分配
//int *p=&a;->int *p=NULL;p=&a;
//int *p = new int(3); ->int *p = nullptr; p = new int(3);
int *p = new int(3);//动态申请整形变量地址,返回给p,并且给其赋初值为3
cout << "*p=" << *p << endl;
delete p;//先释放,才能执行下面的分配
//动态分配4个连续整形空间,将其首地址返回给p,没赋值的为0
p = new int[4]{1, 2, 3};
for (int i = 0; i < 4; i++)
cout << *(p + i) << " ";
cout << endl;
delete []p;
p = nullptr;
}
*p=3
1 2 3 0
void test()
{
string*str = new string("sad");
cout << *str << endl;//sad
delete str;
str = new string[3]{"da", "asd"};
for (int i = 0; i < 3; i++)
cout << *(str + i) << " ";//da asd
cout << endl;
delete []str;
str = nullptr;
}
void test()
{
char*ch = new char('a');
cout << *ch << endl;//a
delete ch;
ch = new char[6]{'a','b','c','d'};
for (int i = 0; i < 6; i++)
cout << *(ch + i) << " "; //a b c d
cout << endl;
delete []ch;
ch = nullptr;
}
6.9
左值引用,右值引用
#include<iostream>
#include<stdlib.h>
#include<string>
using namespace std;
//namespace防止命名冲突
int main()
{
//左值引用
int a = 3;
int &b = a;
int&& p = 3;//右值引用
//不可以int&& p=a,可以int&& p=a+2
//int&& p=move(a),a地址被移除,不能再被使用,move来自std::move(),move(a)只能用一次
cout << "&p=" << &p << endl;
/*
int a=3;
int&& p=move(a);
int&& d=move(p);//可以
*/
system("pause");
return 0;
}
取别名
typedef unsigned int u16;
using u16 = unsigned int;//等同于上一行
#define u16 unsigned int;//等同于上一行
const不能改变
void test()//const修饰谁谁不变
{
//1.常函数->类中函数,不改变其中的值
int b = 3;
const int a = 2;//a不能变,不能出现a=
const int *p = nullptr;//p指针变量可以重新赋值,*p常量,不能变,不能出现*p=
p = &a;
//*p = 4; //错误
int const *p1 = nullptr; //p1指针变量可以重新赋值,*p1常量,不能变,不能出现*p1=
p1 = &a;
//*p1 = 5;//错误
int * const p2 = &b; //p2指针常量,不能出现p2=,*p2属于变量可变
//p2 = &a;//错误
*p2 = 3; //int * const p2 = nullptr未给初值这行会报错
const int const *const p3 = &a;
}
值传递,指针传递,引用传递
//函数原型/声明
int Max(int, int);//int Max(int a, int b);
int main()
{
int a1 = 3, b1 = 4;
cout << "Max=" << Max(3, 4) << endl;//值传递
cout << "Max=" << Max(a1, b1) << endl;//值传递
system("pause");
return 0;
}
//值传递:
//1.实参值复制一份给形参
//2.形参会有自己的空间
//3.实参传给形参,单向传递
int Max(int a, int b)
{
return a > b ? a : b;
}
指针传递
//函数原型/声明
int* Max(int*, int*);
int main()
{
int a1 = 3, b1 = 4;
cout << "Max=" << *Max(&a1, &b1) << endl;//指针传递
system("pause");
return 0;
}
//指针传递:形参3个存放地址的空间
int* Max(int *a, int *b)
{
return *a > *b ? a : b;
}
引用传递
int &Max(int &, int&);
int main()
{
int a1 = 3, b1 = 4;
cout << Max(a1, b1) << endl;
system("pause");
return 0;
}
//引用传递,形参不申请任何空间
int &Max(int &a, int& b)//int&a=a1;
{
return a>b ? a : b;
}
int arr[10] = { 1, 2 };
int (&p)[10] = arr;
cout << p[0] << endl;
int max(int *, int n);
int &max1(int(&p)[5], int n);
int main()
{
int a[5] = { 2, 6, 3, 4, 8 };
cout << max(a, 5) << endl;
cout << max1(a, 5) << endl;
system("pause");
return 0;
}
int max(int *p, int n)
{
int a = *p;
for (int i = 1; i < n; i++)
{
if (a < *(p+i))
a = *(p+i);
}
return a;
}
int &max1(int(&p)[5], int n)
{
int a = p[0],j = 0;
for (int i = 1; i < n; i++)
{
if (a < p[i])
{
a = p[i];
j = i;
}
}
return *(p+j);
}
//指针讲究的是指向问题
//默认参数,必须是在函数调用前给定 声明用int add(int,int) 函数用int add(int a,int b=3)报错,只能int add(int a,int b)
//默认参数,必须从右往左连续给定,不能有间隔,可以int add(int,int=3,int=4);不能int add(int,int=3,int);
int add(int, int, int = 4);
函数重载
//函数重载:函数名相同
//条件
//1.参数个数不同
//2.参数类型不同
//3.参数个数和参数类型均不同
//注意:只有返回值不能判定函数重载,比如int add(); double add();这两个不能重载
int add(int, int, int = 4);
int add(int);//与上一行构成重载函数
内联函数
//内联函数内部不存在结构化语句,使用时是直接替换,没有进行函数调用
//与函数调用相比,不会有保护现场,恢复现场的情况,使用时是直接替换
inline int add()//类似于define
{
return 1 + 2;
}
class Base{
//数据->数据成员 属性
int x;
public:
//数据处理->成员函数 方法
//设置
void setX(int i){x = i;}
//获取
int getX()const{ return x; }
};
6.10
// 赋值运算operator=();
// 类外函数要使用类中成员(非静态成员)必需通过对象,而且通过对象能使用的自由公有函数
class Dog{ // Dog是类类型 //typedef class Dog{ }ddd; //class Dog{ }ddd;ddd是Dog类型所定义的对象
// private权限下的成员只能本类成员直接用。其他要使用该成员必须通过本类对象(友元),或者本类公有函数
private: // 私有权限
int x;
// 属性
// 本类成员可以直接用,派生类成员也可以直接用(要看继承方式),类外不能直接用,也不能通过对象使用
protected: // 保护权限
int y;
// 类中成员可以直接用,派生类成员也可以直接用,类外需要通过对象使用
public: // 公有权限
void setX(int a);
void SetY(int b);
int getX()const;
int getY()const;
};
class Dog{
private: // 私有权限
int x;
protected: // 保护权限
int y;
public: // 公有权限
void setX(int a);
void SetY(int b);
int getX()const;
int getY()const;
}ddd; //
void Dog::setX(int a)
{
x = a;
}
void Dog::SetY(int b)
{
y = b;
}
int Dog::getX()const
{
return x;
}
int Dog::getY()const
{
return y;
}
int main()
{
Dog d;
d.setX(3);
ddd.setX(3);
cout << "d.x=" << d.getX() << " ddd.x=" << ddd.getX() << endl;
system("pause");
return 0;
}
构造函数,析构函数
在return后设置断点,不然运行不会出现析构函数效果
/*构造函数
构造函数名与类名相同
构造函数没有返回值类型(void也不存在)
对象创建时由系统自动调用
构造函数放在public下面
构造函数可以写出内联函数形式
构造函数可以重载
在类中没有显示定义构造与析构,系统会提高默认无参构造与析构
*/
/*析构函数
析构函数名与类名相同,并且加~
析构函数没有返回值类型(void也不存在)
对象结束时由系统自动调用
析构函数放在public下面
析构函数可以写出内联函数形式
每个类只有一个析构
在类中没有显示定义构造与析构,系统会提高默认无参构造与析构
*/
class Dog{
private: // 私有权限
int x;
protected: // 保护权限
int y;//*y Dog(int a=0){ y = new int(a); } //*y=3错误 先给地址,再拿值
public: // 公有权限
/*只要类中显示写出任意一个构造,系统都不会再提供默认构造函数*/
//Dog() = default; //系统默认无参构造
Dog(int a, int b){ x = a; y = b; } //构造函数的作用是给成员赋初值
Dog(int a=0){ x = a; } //Dog();Dog(int);
~Dog(){ cout << "Distruce " << x << endl; }
};
//先构造,后析构
int main()
{/*构建怎样的对象就应该拥有怎样的构造函数*/
Dog d, d1(3);//对象d创建时系统自动调用无参函数
Dog d2(2, 3);
system("pause");
return 0;
}
拷贝构造
/*什么时候调用拷贝构造?
1.对象给新对象赋初值
2.对象作为函数参数
3.对象作为返回值
*/
class Dog{
private: // 私有权限
int x;
protected: // 保护权限
int y;//*y Dog(int a=0){ y = new int(a); } //*y=3错误 先给地址,再拿值
public: // 公有权限
//构造函数只要参数与系统默认不同,就不会覆盖,系统仍会提供
Dog(int x=3){ this->x = x; y = 4; }
Dog(Dog&d, int n = 2){ x = n; cout << "copy construct!" << x << endl; }//拷贝构造
~Dog(){ cout << "Distruce " << x << endl; }
};
void test(Dog d)//函数参数
{
}
Dog test1(Dog d)
{
return d;//拷贝
}
int main()
{
Dog d;
Dog d1(d, 1);//调用拷贝构造函数
test(d);//对象成员作为函数参数
test1(d);//拷贝
//system("pause");
return 0;
}
class B{};
class Base{
private:
Base *b1; //Base b;错误
Base &b2;
B b3,*b4,&b5;
//auto d;//错误
int a;
const int c2;
decltype(a) b6; //获取a的类型递给b6,b6与a的类型一样
static int b7;
//extren int c1;//错误
//constexpr int c3;//错误
public://构造函数一定现实写出:成员里面拥有带参的对象成员,常成员
Base(int a1):a(a1){}
};
auto a = 2;//数据什么类型,自动给什么类型,不能放类中
decltype(a) b;//获取a的类型递给b
class B{
int b;
public:
B(int b = 8){ this->b = b; cout << "con" << b << endl; }
};
class Base{
private: //由声明的顺序决定构建顺序
B b3, &b2;
int a;
//Base &b1;
const int c2, c3;
public://构造函数一定现实写出:成员里面拥有带参的对象成员,常成员
//如果拥有常量成员,必须用初始化列表形式给其赋初值
//如果拥有对象成员,拥有无参构造,可以不写初始化列表
//如果该类没有无参构造,必须在该类中显示写出构造函数用初始化列表进行给其初始化
//对象的引用要通过初始化列表赋初值
Base(int a1) :c2(a1),c3(5), b2(b3), b3(a1){}
Base() :c2(2), c3(5), b2(b3), b3(3){ cout << "con" << c2 << endl; }
};
int main()
{
Base b;//基类先构造->对象成员->派生类构造
//system("pause");
return 0;
}
深拷贝,浅拷贝
//深拷贝,浅拷贝
struct AString{
private:
int *p;
public:
AString(){ p = new int(3); }//p=new int;*p=3;
AString(AString&);
//如果构造出现new,那么就得显示写出析构delete
~AString(){ delete p; }
};
//对象给新对象赋初值,对象做参数,对象做返回值
AString::AString(AString&s1)//浅拷贝,拷贝值和空间
{
p = s1.p;//存在多次析构同一个地址问题
}
int main()
{
AString s;//AString()
AString s1(s);//Astring(Astring&)
//system("pause");
return 0;
}
AString::AString(AString&s1)//深拷贝
{
p = new int;//只拷贝值,空间自己解决,解决了浅拷贝存在多次析构同一个地址的问题
*p = *s1.p;
}
struct AString{
private:
char *str;
public:
AString(const char*s = " ");//构造
AString(AString&);//拷贝
AString& operator=(AString&);//赋值运算符函数
AString(AString&&);//移动拷贝构造
AString& operator=(AString&&);//移动赋值运算符函数
//如果构造出现new,那么就得显示写出析构delete
~AString(){ delete []str; }
};
AString::AString(const char*s = " ")//构造
{
str = new char[strlen(s) + 1];//根据传入参数的大小,分配相应的空间
strcpy(str, s);//将传入参数值赋给成员变量
}
AString::AString(AString&s)//拷贝
{
str = new char[strlen(s.str)+1];
strcpy(str, s.str);
}
AString& AString::operator=(AString&s)//赋值运算符函数
{
//先判定是够是自赋值情况
if (this == &s)return *this;
//不是自赋值情况下,先清除自己的空间,申请相应空间存放所需要存放数据
delete []str;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
return *this;
}
AString::AString(AString&&s)//移动拷贝构造
{
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
}
AString& AString::operator=(AString&&s)//移动赋值运算符函数
{
//先判定是够是自赋值情况
if (this == &s)return *this;
//不是自赋值情况下,先清除自己的空间,申请相应空间存放所需要存放数据
delete[]str;
str = new char[strlen(s.str) + 1];
strcpy(str, s.str);
return *this;
}
int main()
{
AString s("abcd");
AString s1;
//当类中出现构造或者构造拷贝,那么系统不会提供移动构造
s1 = s;
s1 = move(s);//AString& operator=(AString&&);
int a = 3;
int &&b = move(a);
//system("pause");
return 0;
}
//怎么通过指针使用类中成员
class B{
public:
int i, j;
void setI(int a){ i = a; }
void setJ(int b){ j = b; }
int getI()const{ return i; }
int getJ()const{ return j; }
};
int main()
{
int B::*p;
void (B::*t)(int);
int (B::*q)()const;
t = &B::setI;
p = &B::i;
q = &B::getI;
B b;
b.*p = 2;//b.i=2;
cout << (b.*q)() << endl;//b.getI()
//system("pause");
return 0;
}
静态成员static
//static
//静态成员初始化
//静态成员属于类,不属于对象
class DemoStatic{
public:
//int i;
static int a;
int getA()const{ return a; }
};
//int DemoStatic::i = 2; //错误,普通成员只能通过对象
//int DemoStatic::a;//静态成员初始化,默认值为0
int DemoStatic::a = 2;//静态成员初始化,默认值为2
int main()
{
cout << DemoStatic::a << endl;
DemoStatic v1;
v1.a = 77;
cout << DemoStatic::a << endl;
DemoStatic::a = 111;
cout << DemoStatic::a << endl;
cout << DemoStatic::getA << endl;
//system("pause");
return 0;
}
友元函数friend->属于类外函数
普通函数作为类中友元函数
class DemoFriend{
int x;
public:
DemoFriend(int a = 3){ x = a; }
friend int add(DemoFriend&);//普通函数定义为友元函数->类外函数
};
int add(DemoFriend&d)//友元函数在类外定义不需要使用类名::函数名
{
return d.x + 3;//友元函数可以使用类中所有成员,但是必须通过对象
}
int main()
{
DemoFriend d1;
cout << add(d1) << endl;
return 0;
}
扩展:
class DemoFriend{
int x;
public:
DemoFriend(int a = 3){ x = a; }
int add();//类中成员函数
};
int DemoFriend::add()//类中成员函数在类外,需要使用类名::函数名
{
return x + 3;//成员函数用私有成员直接用
}
void add()//普通函数
{
DemoFriend d(4);
cout << "成员:" << d.add() << endl;
cout << "友元:" << add(d) << endl;
}
int main()
{
DemoFriend d1;
cout << d1.add() << endl;
add();
return 0;
}
成员函数作为另一个类的友元函数
class DemoFriend;
class C{
int y;
public:
C() :y(11){}
int add(DemoFriend&);//C类的成员函数
};
class DemoFriend{
int x;
public:
DemoFriend(int a = 3){ x = a; }
friend int C::add(DemoFriend&);//普通函数定义为友元函数->类外函数
};
//C类中成员函数为DemoFriend类的友元函数
int C::add(DemoFriend&d)
{
return y + d.x;
}
int main()
{
C c1;
DemoFriend d;
cout << c1.add(d) << endl;
//system("pause");
return 0;
}
一个类称为另一个类的友元
class DemoFriend;
class C{
int y;
public:
C() :y(11){}
void set();
int add(DemoFriend&);//c类的成员函数
};
class DemoFriend{
int x;
public:
DemoFriend(int a = 3) :x(a){}
friend class C;//该类属于DemoFriend的友类
};
//C类中成员函数为DemoFriend类的友元函数
int C::add(DemoFriend&d)
{
return y + d.x;
}
void C::set(){
DemoFriend m;
y = m.x;
}
int main()
{
C c1;
DemoFriend d;
c1.set();
cout << c1.add(d);//6
return 0;
}
6.16
继承
/*
单继承
class 派生类名:继承权限 基类名{};
继承权限:private、protected、public
多继承
class 派生类名:继承权限 父类名1,继承权限(可省) 父类名2 ...{};
*/
class Base{
private:
int i;
protected:
int j;
public:
int k;
void setI(int a){ i = a; }
int getI()const{ return i; }
};
//任何继承方式,基类的私有成员在子类当中不能直接用
//子类继承 父类,单继承
struct Derived:Base{ //public方式继承
void print();
};
void Derived::print()
{
j = 4;//父类当中的保护在子类担当者可以直接用
setI(5);//父类中的私有只能通过公有函数
cout <<"i="<< getI() << "\tj=" << j << "\tk=" << k << endl;
}
int main()
{
Derived d;
//d.setI(3);
//d.j = 4;
d.k = 5;
d.print();
return 0;
}
//继承
单继承
class 派生类名:继承权限 基类名{};
继承权限:private、protected、public
多继承
class 派生类名:继承权限 父类名1,继承权限(可省) 父类名2 ...{};
/*
公有继承:
基类的私有成员派生类中必须通过基类公有函数直接用
基类中的保护成员也是派生类的保护成员,在派生类中可以直接用
基类中的公有成员也是派生类中的公有成员,在派生类中可以直接用
私有继承:
基类的私有成员派生类中必须通过基类公有函数直接用
基类中的保护成员也是派生类的私有成员,在派生类中可以直接用
基类中的公有成员也是派生类中的私有成员,在派生类中可以直接用
保护继承:
基类的私有成员派生类中必须通过基类公有函数直接用
基类中的保护成员也是派生类的保护成员,在派生类中可以直接用
基类中的公有成员也是派生类中的保护成员,在派生类中可以直接用
*/
class Derived:Base{ //private方式继承
public:
void print();
};
struct Derived:Base{ //public方式继承
void print();
};
#include<iostream>
#include<stdlib.h>
#include<string>
#include<iomanip>
using namespace std;
class Base{
private:
int i;
protected:
int j;
public:
int k;
void setI(int a){ i = a; }
int getI()const{ return i; }
};
//任何继承方式,基类的私有成员在子类当中不能直接用
//子类继承 父类,单继承
class Derived:Base{ //private方式继承
public:
void print();
};
void Derived::print()
{
j = 4;//父类当中的保护在子类担当者可以直接用
setI(5);//父类中的私有只能通过公有函数
cout <<"i="<< getI() << "\tj=" << j << "\tk=" << k << endl;
}
int main()
{
Derived d;
//d.setI(3);
//d.j = 4;
//d.k = 5;//k成为子类私有
d.print();
return 0;
}
class Base{
private:
int i;
public:
Base(){ cout << "Base construct" << endl; }
~Base(){ cout << "~Base construct" << endl; }
};
class Derived:public Base{
public:
Derived(){ cout << "Derived construct" << endl; }
~Derived(){ cout << "~Derived construct" << endl; }
};
int main()
{
Derived d;
return 0;
}
class Base{
private:
int i;
public:
Base(int i){ this->i = i; cout << "Base construct "<< i << endl; }
~Base(){ cout << "~Base construct " << i << endl; }
};
class Derived:public Base{
Base b1, b2;
public:
//所有类中的对象成员初始化,必须在列表
Derived():Base(2), b1(3), b2(4){ cout << "Derived construct" << endl; }
~Derived(){ cout << "~Derived construct" << endl; }
};
//基类-对象成员-派生类
int main()
{
Derived d;
return 0;
}
/*
根据声明顺序
Base construct 2
Base construct 3
Base construct 4
Derived construct
~Derived construct
~Base construct 4
~Base construct 3
~Base construct 2
*/
6.17
//1.不能将派生类对象赋给基类指针
//静态类型和动态类型
//静态是编译时确定
//动态是运行时确定
//不存在从基类向派生类隐士转换:即不存在Dri*d=new Base; 和Base b1; Dri&d=b1;
//对象之间不存在类型转换 Dri d1; Base b1(d1);调用拷贝构造//Base&b=d1;
class Base{
int x;
public:
Base() :x(3){ cout << "constructor " << endl; }
~Base(){}
void print(){ cout << "Base x=" << x << endl; }
};
class Dri:public Base{
int y;
public:
Dri() :y(6){ cout << "constructor " << y << endl; }
~Dri(){}
void print(){ Base::print(); cout << "Dri y=" << y << endl; }
};
int main()
{
Dri d1, *d2 = &d1, *d3 = new Dri;
//Dri *d4 = new Base(); //
Base b1, *b2 = new Base(), &b3 = b1, b4[3];
Base *b6 = &b1;
Base &b7 = d1;
Base *b5 = new Dri(); //基类指针可以指向派生类对象,左边基类,右边派生类
return 0;
}
class Base{
int x;
public:
Base() :x(3){ cout << "constructor " << endl; }
~Base(){}
void print(){ cout << "Base x=" << x << endl; }
};
class Dri:public Base{
int y;
public:
Dri() :y(6){ cout << "constructor " << y << endl; }
~Dri(){}
void print(){ Base::print(); cout << "Dri y=" << y << endl; }
};
int main()
{
Dri d1;
Base *b1 = new Dri;
b1->print();//Base
Base &b6 = d1;
b6.print();//Base
d1.print();
return 0;
}
/*
int main()
{
Dri d1;
Base b1(d1);
return 0;
}
*/
静态与继承
//静态成员
//如果基类定义了一个静态成员,则整个继承体系中只存在该成员的唯一定义
class Base{
public:
static void staticfun();
};
class Drived :public Base{
public:
void ff(const Drived &);
};
void Drived::ff(const Drived&d)
{
Base::staticfun();
Drived::staticfun();
d.staticfun();
staticfun();
}
友元与继承
//友元与继承
//友元关系不能传递,友元函数不能继承
class Base{
private:
int pri_number;
protected:
int pro_number;
friend class C;
};
class Derived :public Base{//私有
friend void f(Derived &);//是Derived的友元
friend void f(Base&);//是Derived的友元函数
friend void ff(Derived&);//是Derived的友元函数
int j;
};
//先看继承int pro_number;属于子类的保护成员
//友元函数属于类外函数
//j是Derived的私有成员,友元函数可以通过本类对象使用
//通过继承int pro_number也属于Derived的保护成员
//友元函数可以通过本类对象使用
void f(Derived&d){ d.pro_number = 4; d.j = 3; }
//void f(Base&b){ b.pro_number = 3; }//是Drived的友元函数 错误:友元关系不能传递
//void ff(Derived&d){ d.pri_number = 1; }//子类的友元函数,可以用自己的私有成员和继承的非私有,但不能用基类的私有
class C{
public:
//f1是Base的友元函数,可以通过Base对象用Base的所有成员
int f1(Base d){ return d.pri_number; }
//错误:友元不被继承,所以C中的成员函数,只是Base的友元函数,并不是Derived友元,所以不能使用Derived的私有
//int f2(Derived d){ return d.j; }
//f3是Base的友元函数,能使用Base的保护成员
int f3(Derived d){ return d.pro_number; }
};
class Deri :class C{
public:
//错误,友元函数不被继承,Base是C的友元类,Deri不会继承其友元关系
int f(Base b){ return b.pro_number; }
};
命名冲突
//命名冲突
class A{
public:
void f(){ cout << "A" << endl; }
};
class B:public A{
public:
void f(){ cout << "B" << endl; }
};
int main()
{
//派生类中有用于基类相同名的函数,会覆盖基类函数
B b;
b.f();//B类的
b.A::f();//A类的
return 0;
}
//命名冲突
class A{
public:
void f(){ cout << "A" << endl; }
};
class B:public A{
public:
};
class C :public A{
public:
};
class D :public B,public C{
public:
};
int main()
{
D d;
d.B::f();
return 0;
}
class A{
public:
A(){ cout << "A" << endl; }
};
class B:public A{
public:
B(){ cout << "B" << endl; }
};
class C :public A{
public:
C(){ cout << "C" << endl; }
};
class D :public B,public C{
public:
D(){ cout << "D" << endl; }
};
int main()
{
D d;
return 0;
}
A
B
A
C
D
class A{
public:
A(){ cout << "A" << endl; }
};
class B:virtual public A{
public:
B(){ cout << "B" << endl; }
};
class C :virtual public A{ // 虚基类解决二义性问题
public:
C(){ cout << "C" << endl; }
};
class D :public B,public C{
public:
D(){ cout << "D" << endl; }
};
int main()
{
D d;
return 0;
}
A
B
C
D
组合
class SS{};
//组合
class DD{
SS s;//对象成员
public:
};
6.18
class B{
public:
void print(){ cout << "B" << endl; }
};
class C:public B{
public:
void print(int x){ cout << "C" << x << endl; }
};
int main()
{
B*b;
b = new C;
C c;
c.B::print();//通过类名::函数名,解决子类覆盖父类同名函数
c.print(3);//C当中的
b->print();//B类中的函数
return 0;
}
class Base{
public:
void who(){ cout << "Base who()" << endl; }
};
class Derived:public Base{
public:
void who(){ cout << "Derived who()" << endl; }
};
int main()
{//联编->连接
Derived d;
Base *b = &d;
b->who();//Base->静态联编
d.who();//Derived
d.Base::who();//Base
((Derived*)b)->who();//强转Derived
return 0;
}
class Base{
public:
virtual void who(){ cout << "Base who()" << endl; } //virtual
};
class Derived:public Base{
public:
void who(){ cout << "Derived who()" << endl; }
};
class C :public Derived{
public:
void who(){ cout << "C who()" << endl; }
};
int main()
{
Derived d;
C c;
Base *b = &d;
b->who();//Derived 上方有virtual
b = &c;
b->who();//C
return 0;
}
一旦出现基类指针指向new出的派生类对象,那么基类中析构一定要写为虚析构
构造函数不能是虚函数
阻止继承,不能做基类继续继承
class Base final{
};
抽象类,纯虚函数
class Shape{//抽象类:拥有纯虚函数的类称为抽象类
int x, y, z;
public:
virtual void area(int x=5, int y=4, int z=3) = 0;//纯虚函数->只有原型,没有定义
virtual void print() = 0;
};
//抽象类不能声明对象,抽象类一般情况作为基类
//抽象类可以是声明指针或引用
class Tri :public Shape{//只要存在一个虚函数,就是抽象类
public:
void area(int x = 5, int y = 4, int z = 3);
void print();//没有这一行则继承了该纯虚函数,为抽象类,有则是实体类
};
//class Tri :public Shape{//抽象类
//public:
// void area(int x = 5, int y = 4, int z = 3);
//};
//class Tri :public Shape{//实体类
//public:
// void area(int x = 5, int y = 4, int z = 3);
// void print();
//};
6.21
运算符重载
//运算符重载:成员函数和友元函数
//默认存在:默认构造,析构,拷贝构造,赋值构造
//双目运算符用的是友元,单目运算符用成员函数
class A{
int n, m;
public:
A(){ n = 2; m = 3; }
//operator 运算符<<、>>一般情况下用友元
friend void operator<<(ostream&os,A &a);
friend void operator>>(istream&os, A &a);
};
void operator<<(ostream&os, A &a)
{
os << a.m << " " << a.n;
}
void operator>>(istream&is, A &a)
{
is >> a.n >> a.m;
}
int main()
{
A a;
operator>>(cin, a);
operator<<(cout, a);//等于cout << a;
return 0;
}
class A{
int n, m;
public:
A(){ n = 2; m = 3; }
//operator 运算符<<、>>一般情况下用友元
friend ostream& operator<<(ostream&os,A &a);
friend istream& operator>>(istream&os, A &a);
};
ostream& operator<<(ostream&os, A &a)
{
os << a.m << " " << a.n;
return os;
}
istream& operator>>(istream&is, A &a)
{
is >> a.n >> a.m;
return is;
}
int main()
{
A a;
operator>>(cin, a);
operator<<(cout, a);//等于cout << a;
return 0;
}
class A{
int n, m;
public:
A(){ n = 2; m = 3; }
//operator 运算符<<、>>用成员函数
ostream& operator<<(ostream&os);
istream& operator>>(istream&is);
};
ostream&A::operator<<(ostream&os)
{
os << m << " " << n;
return os;
}
istream&A::operator>>(istream&is)
{
is >> n >> m;
return is;
}
int main()
{
A a;
a >> cin;// a.operator>>(cin);
a << cout;//a.operator<<(cout);
return 0;
}
前置后置++
class A{
int n, m;
public:
A(){ n = 2; m = 3; }
//成员函数
void operator++(); // 前置++
A operator++(int); // 后置++
//友元
friend ostream& operator<<(ostream&os, A &a);
friend istream& operator>>(istream&os, A &a);
};
void A::operator++() //A&
{
++n;
++m;
} //return *this;
A A::operator++(int)
{
A a;
a.n = this->n++;
a.m = this->m++;
return a;
}
ostream& operator<<(ostream&os, A &a)
{
os << a.m << " " << a.n;
return os;
}
istream& operator>>(istream&is, A &a)
{
is >> a.n >> a.m;
return is;
}
int main()
{
A i;
cout << i << endl;//operator<<(cout,i);
++i;//i.operator++();//前置++
cout << i << endl;
cout << i++ << endl;
cout << i << endl;
return 0;
}
friend int operator+(A&,A&);
int operator+(A&a1, A&a2)
{
a1.n = a1.n + a2.n;
return a1.n;//return a1.n + a2.n;
}
A b1, b2;
int a = b1 + b2;
cout << a;
friend A operator+(A&,A&);
A operator+(A&a1, A&a2)
{
A a;
a.n = a1.n + a2.n;
a.m = a1.m + a2.m;
return a;
}
A b1,b2;
A a=b1+b2;
cout << a;
A& operator+(A&a1, A&a2)
{
a1.n = a1.n + a2.n;
a1.m = a1.m + a2.m;
return a1;
}
A b1,b2;
cout << b1+b2;
class B{
public: virtual void f(){ cout << "B:f()" << endl; }
};
class D1:public B{
public:void f(){ cout << "D1:f()" << endl; }
};
class D2 :public B{
public:
void f(){ cout << "D2:f()" << endl; }
void g(){ cout << "D2:g()" << endl; }
};
void accessB(B* pB)
{//if(D2*p=(D2*)pB)
if (D2 *p = dynamic_cast<D2*>(pB))
p->g();
else
pB->f();
}
/*
void accessB(B* pB)
{
try{
D2 &p = dynamic_cast<D2&>(*pB);
p.g();}
catch (bad_cast){//处理转型失败
pB->f();}
}
*/
int main()
{
B b;
accessB(&b);//B
//B:f()
D1 d1;
accessB(&d1);//D1
//D1:f()
D2 d2;
accessB(&d2);//D2:f()
return 0;
}
6.22
模板函数
//T,K,V
template <typename T>//每次写都不能省
//template <class T>
T add(T, T);
int main()
{
add<int>(2, 4);//add(2, 4);//int可省
add<double>(2.4, 3.6);//double可省
return 0;
}
template <typename T>//每次写都不能省
T add(T a, T b)
{
return a + b;
}
//T,K,V
template <typename T, typename T1>//每次写都不能省
//template <class T>
T add(T, T1);
int main()
{
add<int, double>(2, 4.5);
return 0;
}
template <typename T, typename T1>//每次写都不能省
T add(T a, T1 b)
{
return a + b;
}
/*
class A{
int i, j;
public:
A(int i, int j){ this->i = i; this->j = j; }
};
class B{
double i, j;
public:
B(double i, double j){ this->i = i; this->j = j; }
};
*/
// 简化
template<typename T>
class A{
T i, j;
public:
A(T i, T j){ this->i = i; this->j = j; }
};
template<typename T>
class A{
T i, j;
public:
A(T i, T j);
};
template<typename T>
A<T>::A(T i, T j)
{
this->i = i; this->j = j;
}
template<typename T,typename T1>
class A{
T i;
T1 j;
public:
A(T i, T1 j);
};
template<typename T,typename T1>
A<T, T1>::A(T i, T1 j)
{
this->i = i; this->j = j;
}
int main()
{
A<int, double> a1(2, 3.5);
return 0;
}
lambda函数
//lambda函数:函数式编程也是与命令式编程,面向对象编程并列的一种编程泛型
//[capture](parameters)mutable->T{statement};
//[]捕捉列表
//()参数列表
//mutable:可选择的修饰符
//->T:返回值类型
//statement:函数体
//lambda:最简形式:[]{}
int main()
{
int dogs = 5, cats = 6;
auto totalAnimal = [](int x, int y)->int{return x + y; };//lambda函数 返回值为int类型(->int)
cout << totalAnimal(dogs, cats) << endl;
return 0;
}
//[var]//以值传递方式捕捉var
//[=]//以值传递方式捕捉外围作用域的所有值(包括this)
//[&var]以引用方式捕捉var
//[&]以引用方式捕捉外围作用域的所有值(包括this)
//[this]以值传递方式捕捉当前的this指针
void f()
{
[]{};//最简lambda,不做任何事情
int a = 3, b = 4;
[=]{return a + b; };//省略参数和返回值,可推断出返回值为int
auto f1 = [&](int c){b = a + c; };//省略返回值类型
auto f1 = [=,&b](int c)->int{return b = a + c; };
}
阻止隐士转换
//3.explicit构造函数阻止隐士转换
class A{
int i;
public:
A(int a) :i(a){}//explicit A(int a) :i(a){}则a=100报错
};
int main()
{
A a(100);
a = 100;
return 0;
}
//2.隐式转换的隐患
class A{
char *str;
public:
A(int size){ cout << "A:size" << endl; }//1
A(const char*s = NULL){ cout << "A:char*" << endl; }//2
};
int main()
{
A a = 'a';//A:size
int b = static_cast<int>('a');//显示转换
return 0;
}
6.23
容器
#include<functional>
#include<list>
#include<algorithm>
using namespace std;
void print_member(int element)
{
cout << element << endl;
}
void(*ptr)(int) = print_member;
const int N = 4;
int main()
{
int a1[N] = { 1, 2, 3, 4 };
list<int> Intlist(a1, a1 + 4);//给链表初始化
for_each(Intlist.begin(), Intlist.end(), ptr);
Intlist.push_back(0);//尾部插入
for_each(Intlist.begin(), Intlist.end(), ptr);
Intlist.remove_if(bind2nd(modulus<int>(), 2));//除去不能被2整除的数
for_each(Intlist.begin(), Intlist.end(), ptr);
return 0;
}
void test(int*a1)
{
list<int> Intlist(a1, a1 + 4);//给链表初始化
for_each(Intlist.begin(), Intlist.end(), ptr);
Intlist.push_back(0);//尾部插入
for_each(Intlist.begin(), Intlist.end(), ptr);
Intlist.remove_if(bind2nd(modulus<int>(), 2));//除去不能被2整除的数
for_each(Intlist.begin(), Intlist.end(), ptr);
}
int main()
{
int a1[N] = { 1, 2, 3, 4 };
test(a1);
return 0;
}
void test()
{
list<char> charlist;
//"a-z"
for (char c = 'a'; c <= 'z'; ++c)
{
charlist.push_back(c);
}
list<char>::iterator iter;//迭代器
for (iter = charlist.begin(); iter != charlist.end(); ++iter)
{
cout << *iter << "\t";
}
}
#include<vector>
void test()
{
vector<int> vec;
for (int i = 0; i < 5; i++)
vec.push_back(i + 1);
vector<int>::iterator iter;
for (iter = vec.begin(); iter != vec.end(); ++iter)
cout << *iter << "\t";
}
void test()
{
vector<int> vec;
for (int i = 0; i < 5; i++)
vec.push_back(i + 1);
for (int i = 0; i < 5; i++)
cout << vec[i] << "\t";
}
//计算个数
void test()
{
string s = "agerg";
int count=0;
for (auto c : s)count++;
cout << count << endl;
}
QT
6.28
QWidget
按钮
#include<QPushButton>
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
/*
QPushButton *btn=new QPushButton();
//btn->show(); // 在界面上方弹出新的控件
btn->setParent(this);
btn->setText("第一个按钮");
*/
/*
QPushButton *btn=new QPushButton("第一个按钮", this); // 同上
*/
// 用此构造函数创建,其窗口大小与控件大小一致
QPushButton *btn=new QPushButton("第一个按钮", this);
setFixedSize(600, 400); // 设置窗口大小,不可修改
//QSize q(600,400);
//resize(q); // q或(600,400) 设置窗口大小,可修改
setWindowTitle("应用程序"); // 设置标题
}
按钮重合
QPushButton *btn=new QPushButton();
btn->setParent(this);
btn->setText("第一个按钮");
QPushButton *btn1=new QPushButton();
btn1->setParent(this);
btn1->setText("第二个按钮");
btn->move(300,0); // 按钮位置移动, 解决两个按钮位重合覆盖
自己创建类创建控件
mybutton.h
#ifndef MYBUTTON_H
#define MYBUTTON_H
#include <QPushButton>
class MyButton : public QPushButton
{
Q_OBJECT
public:
explicit MyButton(QWidget *parent = nullptr);
~MyButton();
signals:
};
#endif // MYBUTTON_H
mybutton.cpp
#include "mybutton.h"
#include<QDebug>
MyButton::MyButton(QWidget *parent) : QPushButton(parent)
{
qDebug()<<"MyButton constructor";
}
MyButton::~MyButton()
{
qDebug()<<"MyButton Destructor";
}
mywidget.cpp
#include "mywidget.h"
#include<QPushButton>
#include"mybutton.h"
#include<QDebug>
MyWidget::MyWidget(QWidget *parent)
: QWidget(parent)
{
MyButton *btn=new MyButton;
btn->setParent(this);
btn->setText("第三个按键");
}
MyWidget::~MyWidget()
{
qDebug()<<"MyWidget Destructor";
}
信号可以和信号连接,信号和槽连接
信号函数的参数与槽函数的参数:信号的参数可以多于槽函数,槽函数参数不能多于信号函数
信号与槽——关闭窗口
QPushButton *btn=new QPushButton("第一个按钮", this);
// 信号发送者,按下信号(信号函数),接收者,信号处理函数(槽函数)
connect(btn,&MyButton::clicked,this,&MyWidget::close); // 点击按钮关闭窗口
//connect(btn,&QPushButton::clicked,this,&QWidget::close); // 同上
信号与槽——按钮点击时间处理
Teacher类,hunger函数teach在Teacher中定义Teacher *teach
Student类,treat函数stu在Student中定义Student stu
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
//创建对象
teach= new Teacher(this);
stu = new Student(this);
//连接
//信号和槽
//connect(teach,&Teacher::hungry,stu,&Student::treat);
//下课了
//classIsOver();
//信号和信号
QPushButton *btn=new QPushButton("点击",this);
resize(600, 400);
connect(btn,&QPushButton::clicked,stu,&Student::treat);
}
void (Teacher::*p)(QString)=&Teacher::hungry;
void (Student::*q)(QString)=&Student::treat;
connect(teach,p,stu,q);
//int data=[=]()->int{return 5;}();
//qDebug()<<data;
connect(btn,&QPushButton::clicked,teach,[=](){
emit teach->hungry("fush");
});
6.29
QMainWindow
menu菜单栏
#include "mainwindow.h"
#include<QMenuBar>
#include<QToolBar>
#include<QPushButton>
#include<QStatusBar>
#include<QLabel>
#include<QDockWidget>
#include<QTextEdit>
setWindowTitle("应用程序");
resize(600,400);
//菜单栏 #include<QMenuBar> 最多一个
QMenuBar* menuBar=new QMenuBar(this);
setMenuBar(menuBar);
//在菜单栏加menu
QMenu* fileMenu = menuBar->addMenu("文件(F)");
QMenu* editMenu = menuBar->addMenu("编辑(E)");
//在menu中添加action
fileMenu->addAction("新建");
fileMenu->addSeparator();//添加分隔符
fileMenu->addAction("打开");
//工具栏 #include<QToolBar> 可以有多个
QToolBar* toolBar = new QToolBar(this);
//在界面中添加工具栏
addToolBar(toolBar);
addToolBar(Qt::LeftToolBarArea,toolBar);//位置
toolBar->addAction("工具");
//设置停靠位置
toolBar->setAllowedAreas(Qt::LeftToolBarArea|Qt::RightToolBarArea);
//禁止移动
//toolBar->setMovable(false);
//禁止浮动
toolBar->setFloatable(false);
QPushButton*btn=new QPushButton(this);
btn->setText("按钮");
toolBar->addWidget(btn); //添加按钮
//状态栏 #include<QStatusBar>
QStatusBar*stBar = new QStatusBar(this);
setStatusBar(stBar);
//添加小部件
QLabel* label = new QLabel("提示信息",this);
stBar->addWidget(label);
//添加小部件
QLabel* label1 = new QLabel("右边提示信息",this);
stBar->addPermanentWidget(label1);
//可添加按钮
//浮动框 #include<QDockWidget>
QDockWidget*docw = new QDockWidget("浮动框",this);
addDockWidget(Qt::BottomDockWidgetArea,docw);
//添加中心部件 #include<QTextEdit> 中心部件只能有一个
QTextEdit* edit = new QTextEdit(this);
setCentralWidget(edit);
资源文件
#include<QMenuBar>
resize(600,400);
//创建菜单栏
QMenuBar* menuBar=new QMenuBar(this);
setMenuBar(menuBar);
//添加菜单menu
QMenu* fileMenu = menuBar->addMenu("文件");
fileMenu->addAction(QIcon(":/Image/Luffy.png"),"新建");
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QDialog>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
ui->actionnew->setIcon(QIcon(":/Image/Luffy.png"));
ui->actionopen->setIcon(QIcon(":/Image/Frame.jpg"));
connect(ui->actionnew,&QAction::triggered,this,[=](){
//模态
QDialog dia;
dia.show();
dia.exec(); //防止闪退
??????????????????????????????????????????
//非模态
//QDialog *dia=new QDialog(this);
//dia->resize(200, 200);
//dia->show();
//dia->exec();
});
}
MainWindow::~MainWindow()
{
delete ui;
}
connect(ui->actionnew,&QAction::triggered,this,[=](){
//模态
/*QDialog dia;
dia.resize(300,200);
dia.exec(); //防止闪退
qDebug()<<"模态情况";*/
//非模态
QDialog *dia=new QDialog(this);
dia->resize(200, 200);
dia->show(); // 隐藏该句为模态
//自动销毁窗口类对象
//dia->deleteLater();//函数设置对话框关闭时,自动销毁对话框
dia->setAttribute(Qt::WA_DeleteOnClose);//在当前事件
qDebug()<<"非模态情况";
//#include<QMessageBox>
//错误信息对话框 静态成员函数:基类,QString title,Qstring 信息内容
//QMessageBox::critical(this, "critical", "错误");
//消息对话框
//QMessageBox::information(this, "info", "信息");
//问题对话框
//if (QMessageBox::Save == QMessageBox::question(this, "question", "问题",QMessageBox::Save|QMessageBox::Cancel,QMessageBox::Cancel))//最后一个参数默认初始选择在哪个选项即Cancel
// qDebug()<<"是一个保存按钮";
//else
// qDebug()<<"是一个取消按钮";
//警告对话框
//QMessageBox::warning(this, "warning", "警告");
//字体对话框 #include<QFontDialog>
//bool flag;
//QFont col = QFontDialog::getFont(&flag,QFont("仿宋", 24));
//qDebug()<<"字体类型:"<<col.family().toUtf8().data()<<"是否加粗"<<col.bold();
//颜色对话框 #include<QColorDialog>
QColor color = QColorDialog::getColor(QColor(255, 0, 0));
qDebug()<<"r="<<color.red()<<" g="<<color.green()<<" b="<<color.blue();
});
ui->setupUi(this);
ui->btn1->resize(80,40);
ui->btn1->setText("open");
connect(ui->btn1, &QPushButton::clicked,[=](){
QDialog*dlog=new QDialog(this);
dlog->resize(300,300);
dlog->show();
dlog->setAttribute(Qt::WA_DeleteOnClose);
});
void (QSpinBox::*spsignal)(int)=&QSpinBox::valueChanged;
connect(ui->spinBox,spsignal,ui->horizontalSlider,&QSlider::setValue);
//Slider变化->spinBox变化
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
connect(ui->pushButton,&QPushButton::clicked,[=](){
qDebug()<<ui->widget->GetValue();
});
connect(ui->pushButton_2,&QPushButton::clicked,[=](){
ui->widget->SetValue(50);
});
SmallWidget::SmallWidget(QWidget *parent) :
QWidget(parent),
ui(new Ui::SmallWidget)
{
ui->setupUi(this);
//spinBox变化->Slider变化
void (QSpinBox::*spsignal)(int)=&QSpinBox::valueChanged;
connect(ui->spinBox,spsignal,ui->horizontalSlider,&QSlider::setValue);
//Slider变化->spinBox变化
connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
}
//设置SpinBox的值
void SmallWidget::SetValue(int val)
{
ui->spinBox->setValue(val);
}
//获取spinBox的值
int SmallWidget::GetValue()
{
return ui->spinBox->value();
}
#include<QEvent>
void eventWidget::enterEvent(QEvent *event)
{
qDebug()<<"鼠标进入";
}
void eventWidget::leaveEvent(QEvent *)
{
qDebug()<<"鼠标离开";
}
#include<QMouseEvent>
//鼠标按下
void eventWidget::mousePressEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标按下";
}
//鼠标释放
void eventWidget::mouseReleaseEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标释放";
}
//鼠标移动
void eventWidget::mouseMoveEvent(QMouseEvent *ev)
{
qDebug()<<"鼠标移动";
}
void eventWidget::mousePressEvent(QMouseEvent *ev)
{
if(ev->button()==Qt::RightButton)//鼠标右键按下
{
qDebug()<<"鼠标按下 ";
}
QString str=QString("鼠标按下的坐标:x=%1,y=%2").arg(ev->x()).arg(ev->y());
qDebug()<<"鼠标按下 "<<str;
}
//计时器
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
startTimer(1000);//时间1s
}
void Widget::timerEvent(QTimerEvent *event)
{
static int num = 1;
ui->label->setText(QString().number(num++));
}
QTimer *time=new QTimer(this);
time->start(3000);//3秒变化一次
connect(time,&QTimer::timeout,[=](){
static int num = 1;
ui->label->setText(QString().number(num++));
});
Widget::Widget(QWidget *parent)
: QWidget(parent)
, ui(new Ui::Widget)
{
ui->setupUi(this);
id1 = startTimer(1000);
id2 = startTimer(2000);
}
void Widget::timerEvent(QTimerEvent *event)
{
if(event->timerID()==id1){
static int num = 1;
ui->label->setText(QString().number(num++));
}
if(event->timerID()==id2){
static int num = 1;
ui->label->setText(QString().number(num++));
}
}