程序设计专题
文章目录
- Chapter 1 模块化程序设计
- 代码规范
- 结构化程序设计
- 头文件
- 编译预处理
- 递归
- Chapter 2 多文件项目
- 文本文件和二进制文件
- 多文件的程序结构
- 文件模块间的连接
- 文件包含
- 文件模块间的通信--存储类别
- 工程文件
- Chapter 3 链表
- 内存动态分配
- C程序内存分布区域
- 动态按需分配
- 所需函数
- 链表
- 单向链表的实现
- Chapter 4 指针进阶
- 主要内容
- 二级指针(指向指针的指针)
- 指针数组
- 字符数组,字符指针 字符串
- 命令行参数
- Chapter 5
- 指针补充
- 数组指针
- 二维数组与指针的关系
- 指针作为函数的返回值
- 函数指针(指向函数的指针)
- 题目 ==待做==
- Chapter 6 算法分析基础
- 数据结构和算法的关系
- 算法效率的度量方法和大0记法
- 查找算法—线性、二分
- 排序算法
- 冒泡排序
- 选择排序
- 插入排序
- 归并排序
- 位运算
- Chapter 7 图形程序设计基础
- GUI编程相关C基础知识
- Windows编程入门
- 基本图形函数
- 以画圆为例
- 交互式GUI编程基础
- 回调函数
- chapter 8 SimpleGUI
- button控件
- menulist控件
- text控件
- 控件颜色设置
- 其他辅助画图函数
Chapter 1 模块化程序设计
代码规范
-
不直接使用基础类型
使用指示了大小和符号的typedef
以代替基本数据类型typedef char char_t; typedef signed int int32_t;
typedef详见C语言笔记
-
变量、函数的命名符合编码规范
Pascal命名规则:当变量名和函数名称是由二个或二个 以上单字连结在一起,而构成的唯一识别字时,第一个单字首字母采用大写字母,后续单字的首字母亦用大写 字母,例如:FirstName、LastName。 -
小心使用全局变量
多线程代码中非常数全局变量是禁止使用的。内建类型的全 局变量是允许的,但使用时务必三思 -
用访问器子程序来取代全局数据
把数据隐藏到模块里面。用static关键字来定义该数据,写出可以read读、write和initialize初始化该数据的子程序来。要求模块外部的代码使用该访问器子程序来访问该数据,而不是直接操作它。
结构化程序设计
自顶向下,逐步求精,函数实现
调用返回结构:控制模块+工作模块(worker,单一)
降低程序的构思,编写,调试复杂度
可读性好
注意问题
起名:见名知意
少用全局变量
限制函数长度
函数参数:每个函数头要有注释
模块
较小的原文济南称为模块,包含main函数的模块叫做主模块(main module)
独立编译单元:utility.c->utility.obj
头文件
-
内容是函数声明(函数原型要求)、常量定义等
-
作用
调用函数功能 在很多场合,源代码不便(或不准)向 用户公布,只要向用户提供头文件和二进制的库即可。用户只需要按 照头文件中的接口声明来调用库功能,而不必关心接口怎么实现的。 编译器会从库中提取相应的代码。
加强类型安全检查 如果某个接口被实现或被使用时,其方式与头文件中的声明不一致,编译器就会指出错误,这一简单的规则 能大大减轻程序员调试、改错的负担 -
eg.如果一个源文件如:Utility.c中,要使用 Utility.h中声明的函数、类型和具名符号等,在该源文件开始处:
#include “Utility.h” #include <stdio.h>
-
组成:只用于声明,不包含或生成储存空间的变量或函数的定义
- 版权和版本说明
- 预处理块
- 函数,结构和枚举类型声明,外部变量声明、具名常量定义。typedef和宏等
-
#define保护
函数、变量的声明都可以重复,同一个声明出现多次也不会影响程序的运行,但重复引用头文件会浪费编译时间;
当头文件中包含结构的定义、枚举定义等一些定义时,这些定义时不可重复的,必须通过一定措施防止重复引用#ifndef _HEADERNAME_H #define _HEADERNAME_H .....//头文件内容 #endif
编译预处理
c语言由源代码生成的各阶段如下:
C源程序->编译预处理->编译->汇编程序->链接程序->可执行文件
编译预处理:读取C源程序,对其中的伪指令(以#开头)和特殊符号进行处理。扫描源代码,对其进行初步的转换,产生新的源代码提供给编译器。主要包括:条件编译,宏定义和文件包含
一整行语句构成了一条预处理指令,意味着程序的一行只能有一个有效的预处理命令行
伪指令(预处理指令)
#+指令关键字
# //空指令
#include //包含一个源代码文件
#include < >
//用于标准或系统提供的头文件,到保存系统标准头文件的位置查找头文件。
#include " "
//常用于程序员自己的头文件。先查找当前目录是否有指定名称的头文件,然后在从标准头文件目录中查找。
#define //定义宏
#undef //取消已定义的宏
#if //如果给定条件为真,编译下面代码
#ifdef //如果宏已定义,编译下面代码
#ifndef //如果宏没有定义,则编译下面代码
#elif //如果前面#if给定条件不为真,当前条件为真,编译下面代码
#endif //结束一个#if...#else条件编译块
#error //停止编译并显示错误信息
带参数的宏定义
#define 宏名(形参表) 字符串
- 带参宏定义中,宏名和形参表之间不能有空格出现
- 要宏展开,而且要用实参去代换形参。
- 形式参数是标识符,不分配内存单元,因此不必作类型定义。而宏调用中的实参有具体的值,要用它们去代换形参。实参也可以是表达式。
- 宏定义是直接替换,不包括任何其他处理,因此一般在定义时要用括号括起来
#define MA(x, y) ( x*y )i = 5;i = MA(i, i + 1) – 7;//=19
//i=i*i-1-7=5*5-1-7=19
修改: #define MA(x, y) ( (x)*(y) )
递归
- 调用递归函数:调用另一个有着相同名字和 相同代码的函数。
- 每次调用函数时分配参数和局部变量的存储 空间,退出函数时释放。
- 随着递归函数的层层深入,存储空间的一端 逐渐增加,然后随着函数调用的层层返回, 存储空间的这一端又逐渐缩短。
- 递归存在着可用堆栈空间过度使用的危险。(禁止没有base case的无穷递归)
- 对于某一小范围内的问题,使用递归会带来简单、优雅的解。对于大多 数问题,它所带来的解将会是极其复杂的。因此要有选择地使用递归。
- 递归存在着可用堆栈空间过度使用的危险,这能导致严重的错误。在安 全相关系统中强制规定:不能使用递归函数调用。
- **递归调用:**在调用一个函数的过程中又出现直接或间接地调用该函数本身。
**嵌套调用:**在调用一个函数时,其函数体内又包含另一个函数的调用。
汉诺塔问题
#include<stdio.h>
#include<string.h>
int tot=0;
void move(int num,char *a,char *b){printf("move %d from %s to %s\n",num,a,b);tot++;return ;
}
void hanoi(int num,char *x,char *y,char *z){//从x借助y转移到zif(num==1) move(num,x,z);else {hanoi(num-1,x,z,y);move(num,x,z);hanoi(num-1,y,x,z);}return ;
}
int main(){hanoi(3,"A","B","C");printf("%d",tot);
}
递归求简单交错幂级数的部分和
本题要求实现一个函数,计算下列简单交错幂级数的部分和:
f(x,n)=x−x2+x3−x4+⋯+(−1)n−1xn
double fn( double x, int n ){if(n==1) return x;return x*(1-fn(x,n-1));
}
Chapter 2 多文件项目
文本文件和二进制文件
例如:整数1234
文本文件: 49 50 51 52(4个字符)
二进制文件保存:04D2(1234的二进制数)
函数
fread(buffer,size,count,fp);
//从二进制文件中读入一个数据块到变量
fwrite(buffer,size,count,fp);
//向二进制文件中写入一个数据块buffer: 指针,表示存储数据的变量首地址
size:数据块的字节数
count:要读写的数据块数目
fp:文件指针
多文件的程序结构
- 一个大程序会由几个文件组成,把保存有一部分程序的文件成为程序文件模块(函数书写的载体)
多文件的程序结构(程序 - 文件 - 函数)
-
整个程序只允许有一个main函数,包含main函数的模块叫主模块
-
一个程序通常包含多个.h文件和 .c文件
-
.h文件(头文件)
为了方便模块中的函数被别人调用,专门形成一个头文件,内容是类型定义,typedef,函数原型声明,全局变量外部声明,常量定义等。
-
.c文件(实现文件)
函数定义(实现),全局变量定义
- 通常,每一个.c文件都有一个对应的.h文件。
-
- 补充:定义与声明的区别
定义:只能定义一次,意味着分配空间
声明:说明,不会再分配空间
文件模块间的连接
文件包含
通过#include "demo.h"
实现
重复包含
对声明没有影响,对定义有影响(定义不可以重复)
头文件#include保护符#define机制
也会出问题,不要在头文件中定义变量、函数(在link时会出现错误),而是声明变量
文件模块间的通信–存储类别
变量存储类别
-
extern
在某个文件定义了一个全局变量,在另一个文件中去使用该变量,用extern声明,告诉编译器该变量在其他文件中已经定义,此处引用。
不能对变量进行初始化 -
static
用static修饰局部变量(函数内的),那这个变量就不会存储在栈区,而是存储在静态数据区,其生命周期会一直持续到整个程序结束,该变量只在初次运行时进行一次初始化,但作用域只能在函数里面。
用static修饰一个全局变量,那这是一个只允许本源文件中所有函数使用的全局变量。 -
register
早期c语言编译器不会对代码进行优化 , 用register关键字修饰变量 , 请求让编译器将变量a直接放入寄存器里面,以提高读取速度,在C语言中register关键字修饰的变量不可以被取地址,但是c++中进行了优化 。
c++中依然支持register关键字,但是c++编译器也有自己的优化方式,即某些变量不用register关键字进行修饰,编译器也会将多次连续使用的变量优化放入寄存器中,例如入for循环的循环变量i。
c++中也可以对register修饰的变量取地址,不过c++编译器发现程序中需要取register关键字修饰的变量的地址时,register关键字的声明将变得无效。 -
auto
函数中未指定存储类别的局部变量,其隐含的存储类别为自动存储类别。
函数中的局部变量,如果不专门声明为static存储类别,都是动态的分配存储空间,数据存储在动态存储区中。这类变量叫做自动变量,可以用关键字auto作为存储类型的声明,实际上关键字auto是可以省略的(一般不写),不写则自动隐含为“自动存储类别”。在C语言中,使用 auto 修饰的变量,是具有自动存储器的局部变量,但很少有人去使用它,在C++11中,auto 有了新的含义,它不再是一个存储类型指示符,而是作为一个新的类型指示符来指示编译器,auto 声明的变量必须由编译器在编译时期推导而得。
文件模块与函数
-
外部变量/函数 extern
在引用其他文件的变量时,前缀 extern
-
静态全局变量 /函数 static
时全局变量只限于本文件引用,而不能被其他文件引用
工程文件
Chapter 3 链表
内存动态分配
C程序内存分布区域
1.代码区
主函数,其他函数
2.静态存储区(编译器内存静态分配
编译时分配空间,到程序结束时空间释放。
全局变量+静态局部变量
3.栈区/局部变量区(编译器内存静态分配
生命期短,函数调用时分配空间,函数结束时收回空间。
自动变量,在执行进入变量定义所在的复合语句时为它们分配存储,变量的大小也是静态确定的。
main局部变量
其他函数内局部变量
4.堆区
内存动态分配 随时开辟释放。
动态按需分配
编写程序时,不知道需要处理的数据量or难以评估数据量的变动程度
申请空间足够大?浪费+不能修改+数组越界----->按需动态分配
不是预先分配,而是在程序运行时由系统根据程序的需要即时分配内存,且分配的大小就是程序要求的大小,并在使用完毕后尽早释放不需要的内存。
-
用时申请
-
!用完释放 //不释放会出现内存溢出
-
同一段内存可以有不同的用途
步骤
-
了解需要多少内存空间
-
利用C语言提供的动态分配函数来分配所需要的存储空间
-
使指针指向获得的内存空间,以便用指针在该空间内实现运算或操作
-
当使用完毕内存后,释放这一空间
所需函数
-
void *malloc(unsigned size)
-
在内存的动态存储区中分配一连续空间,长度为size
-
申请成功,返回一个指向所分配内存空间的起始地址的指针
-
申请不成功,返回null
-
返回类型(void*):通用指针,需强制类型转换
#include<stdlib.h> void *malloc(unsigned size) ----------------------------- if((p=(int *)malloc(n*sizeof(int)))==NULL){ //sizeof计算大小 //强制类型转换赋值给p,p指向起始地址指针,p+1下一个int位置 //每次都要检查是否成功printf("Not able to allocate memory.\n");exit(1); }
-
-
void *calloc(unsigned n,unsigned size)
- 计数动态存储分配函数
- 分配n个连续空间,每一段长度为size,分配后会把存储块内全部初始化为0
- 若申请成功,则返回一个指向被分配内存空间的起始地址的指针
- 若申请内存空间不成功,则返回NULL
#include<stdlib.h>void *calloc(unsigned n,unsigned size)
-
void free(void *ptr)
- 动态存储释放函数
- ptr为指向要释放空间的首地址,释放ptr所在的整块内存空间
- 一定要存储内存首地址ptr,否则无法释放
- free不能重复释放一块内存
- ptr指向地址仍然存在,仍然可以调用,最好free之后令ptr=null,否则容易错误
#include<stdlib.h>void free(void *ptr)//动态存储释放函数
-
void *realloc(void &ptr,unsigned size)
-
更改以前的存储分配
-
ptr必须是以前通过动态存储分配得到的指针;size为现在所需要的空间大小
-
如果调整失败,返回NULL,同时原来ptr指向存储块的内容不变。
-
如果调整成功,返回一片能存放大小为size的区块,并保证该块的内容与原块的一致。如果size小于原块的大小,则内容为原块前size范围内的数据;如果新块更大,则原有数据存在新块的前一部分。
-
如果分配成功,原存储块的内容就可能改变了,因此不允许再通
过ptr去使用它。
#include<stdlib.h> void *realloc(void *ptr,unsigned size)//更改以前的存储分配
-
//计算任意n个数字的和
#include<stdio.h>
#include<stdlib.h>
int main(){int n,sum=0,i,*p;printf("Enter n:");scanf("%d",&n);if((p=(int *)calloc(n,sizeof(int)))==NULL){printf("NULL");exit(1);}for(i=0;i<n;i++) scanf("%d",p+i);for(i=0;i<n;i++) sum+=*(p+i);printf("%d",sum);free(p);return 0;
}
链表
一种动态存储分布的数据结构,若干个同一结构类型的结点依次串接而成
不连续的数组? 存储相同类型、不同地方的一批数,通过**链(指针)**连接起来。
与数组相比,链表是动态存储分布的数据结构。根据需要动态地开辟内存空间,可以比较自由方便地插入新元素(结点),故使用链表可以节省内存, 操作效率高。
单向链表 双向链表 环
单向链表的实现
链表节点的类型定义
//结构的递归定义
struct node{数据成员:int,double,stuct等struct node *next; //链成员(node型指针)
};
链表的表示
头指针struct node *head
,
尾结点
链表的基本操作
- 链表的建立
- 链表的遍历/求表长
- 插入结点
- 删除结点
- !!!不能使 链 断掉
#include<stdio.h>
#include<stdlib.h>
struct stu_node{int num;char name[20];int score;struct stu_node *next;
};
struct stu_node *head=NULL,*tail=NULL;struct stud_node *createlist(){//链表的建立
//首先建立一个空链表
//然后加入新节点到已有链表的末尾 int num,score;char name[20];int size=sizeof(struct stud_node);struct stud_node *q;scanf("%d",&num);while(num!=0){scanf("%s%d",name,&score);q=(struct stud_node *)malloc(size);q->num=num; q->score=score;strcpy(q->name,name);q->next=NULL;if(head==NULL) head=q;else tail->next=q;tail=q;scanf("%d",&num);}return head;
}
struct stud_node *deletelist( struct stud_node *head, int min_score ){//删除成绩小于min_score的结点struct stud_node *ptr1,*ptr2;//处理前部while(head!=NULL&&head->score<min_score){ptr2=head;head=head->next;free(ptr2);}if(head==NULL) return head;ptr1=head;ptr2=ptr1->next;while(ptr2!=NULL){if(ptr2->score<min_score){ptr1->next=ptr2->next;free(ptr2);}else ptr1=ptr2;ptr2=ptr1->next;}return head;
}int main(){struct stu_node *p;createlist();deletelist(head,20);
}
while(data>0){//逆向建表p=(struct ListNode *) malloc(size);p->data=data;p->next=head;head=p;scanf("%d",&data);
}
//合并链表
struct ListNode *mergelists(struct ListNode *list1, struct ListNode *list2){struct ListNode *head,*p;head=p=NULL;while(list1!=NULL&&list2!=NULL){if(list1->data < list2->data){if(head==NULL) head=p=list1;else p->next=list1,p=p->next;;list1=list1->next;}else {if(head==NULL) head=p=list2;else p->next=list2,p=p->next;list2=list2->next;}}if(head==NULL) return head;if(list1==NULL) p->next=list2;else p->next=list1;return head;
}
//链表奇偶分离
//函数getodd将单链表L中奇数值的结点分离出来,重新组成一个新的链表。返回指向新链表头结点的指针,同时将L中存储的地址改为删除了奇数值结点后的链表的头结点地址(所以要传入L的指针)。
struct ListNode *getodd( struct ListNode **L ){struct ListNode *p,*ptr1,*ptr2,*odd;p=*L;*L=odd=NULL;ptr1=ptr2=NULL;while(p!=NULL){if(p->data%2==1) {if(odd==NULL) odd=p,ptr1=p;else ptr1->next=p,ptr1=ptr1->next;}else {if(*L==NULL) *L=p,ptr2=p;else ptr2->next=p,ptr2=ptr2->next;}p=p->next;}if(ptr1) ptr1->next=NULL;if(ptr2) ptr2->next=NULL;return odd;
}//链表逆置
struct ListNode *reverse( struct ListNode *head ){if(head==NULL||head->next==NULL) return head;struct ListNode *ptr=head->next;if(ptr->next==NULL){ptr->next=head;head->next=NULL;return ptr;}struct ListNode *p=reverse(head->next);ptr->next=head;head->next=NULL;return p;
}
//链表逆置2
struct ListNode *reverse( struct ListNode *head )
{struct ListNode *L=head;if(L==NULL) return NULL; struct ListNode *l1=NULL;struct ListNode *l2=NULL; while(L!=NULL) { l1=L->next; L->next=l2; l2=L; L=l1; }return l2;}
Chapter 4 指针进阶
主要内容
二级指针的概念与变量定义
指针数组的定义和使用
指针数组名与二级指针的关系
命令行参数
数组指针的概念与变量定义
二维数组和指针的关系
二维数组名作为函数的参数
多个字符串的处理
函数指针的定义和使用
二级指针(指向指针的指针)
定义: 类型名 * * 变量名
二级指针 | 一级指针 | 变量 |
---|---|---|
int **p2 |
int *p1 |
int i |
p2 | p1 | i |
&p1 | &i | 3 |
#include<stdio.h>
int main(){int a=10,b=20,t;int *pa=&a,*pb=&b,*pt;int **ppa=&pa,**ppb=&pb,**ppt;ppt=ppb,ppb=ppa,ppa=ppt;pt=pb,pb=pa,pa=pt;t=b,b=a,a=t;printf("%d %d\n",a,b);// 20 10printf("%d %d\n",*pa,*pb);// 10 20printf("%d %d\n",**ppa,**ppb);//20 10
}
指针数组
类型名 * 数组名[数组长度]
数组元素是指针类型,用于存放内存地址
指针数组名是一个二级指针
int main(){int a[4]={1,2,3,4},i;int *b[4];for(i=0;i<4;i++) b[i]=&a[i];*b[i]==**(b+i)==*(a+i)==a[i]
}
/*例:使用指针数组输出5种颜色的英文名称*/
#include<stdio.h>
int main(){int i;char *color[5]={"red","blue","yellow","green","purple"};for(i=0;i<5;i++) printf("%s\n",color[i]); //输出字符串for(i=0;i<5;i++) printf("%c\n",*color[i]); //输出字符串首字母return 0;
}
字符数组,字符指针 字符串
#include<stdio.h>
int main(){char sa[]="hello";char *str="This is a string";str=sa;str="new string";//sa的长度与 串常量长度相等,可以视作串常量的备份 //sa是数组名,为常量指针,永远指向数组的首元素//str是字符指针,为变量,经修改可以指向新的字符
}
命令行参数
C语言源程序经编译和连接处理,生成可执行程序(例如test.exe)后,才能运行。
在OS的命令行模式窗口中,输入可执行文件名,就以命令方式运行该程序。
输入命令时,在可执行文件(命令)名的后面可以跟一些参数,这些参数被称为命令行参数,这些参数传递给main
win+R cmd 打开dir 查看该目录下可运行程序dir/p 翻页展开dir/w 平铺展开
命令行的一般形式为
命令行 参数1 参数2 …参数n
使用命令行的程序不能在编译器中执行,需要将源 程序经编译、链接为相应的命令文件(一般以.exe 为后缀),然后回到命令行状态,再在该状态下直 接输入命令文件名。
test.cpp
#include<stdio.h>
#include<stdlib.h>
int main(int argc,char *argv[]){//第一个参数argc接受命令行参数(包括命令名)的个数 //第二个参数argv接受以字符串常量形式存放的命令行参数, argv[0]是命令名(text),argv[i]是参数int x,y,sum;x=atoi(argv[1]);y=atoi(argv[2]);sum=x+y;printf("%d+%d=%d\n",x,y,sum);return 0;
} 命令行操作
C:\Users\PC>Desktop\test 123 123
123+123=246
Chapter 5
指针补充
指针的要素:基类型,地址值
double ***p5
p5的基类型是double **
指针加法对地址值的影响
- 地址值的增量=sizeof(基类型)
理解运算符
x[y]==*(x+y)
数组指针
数组指针:指向一个数组或一个二维数组某行的指针
变量定义:
类型名 (* 指针名)[数组长度]
int (*ap)[4];
char (*colorp)[5];
int (*p)[4]=NULL;
int a[8]={1,3,5,7,2,4,6,8};
p=(int (*)[4])a;
printf("%d ",(*p)[2]);
printf("%d",(*(p+1))[0]);
//out:5 2
二维数组与指针的关系
二维数组是数组元素为一维数组的一维数组
int a[n][m];
a[i]是整数指针 a[i]+1指向下一个int数
二维数组名a是一个数组指针 a+1指向下一行数组&a[i]==&a[i][0]==a+i
地址一样,但基类型不同
表达式 | 含义 |
---|---|
a |
数组首地址,即&a[0][0] |
a[0],*(a+0),*a |
&a[0][0] |
a+1,a[1],*(a+1) |
a[1]的首地址,即&a[1][0] |
a+i,a[i],*(a+i) |
a[i]的首地址,即&a[i][0] |
a[1]+2,*(a+1)+2 |
&a[1][2] |
a[i]+2,*(a+i)+2 |
&a[i][2] |
*(a[1]+2),*(*(a+1)+2) |
元素a[1][2] |
*(a[i]+j),*(*(a+i)+j) |
元素a[i][j] |
指针作为函数的返回值
在C语言中,函数返回值也可以是指针(返回一个地址,定义和调用这类函数的方法与其他函数是一样 的。
返回指针的函数一般都返回 全局数据对象或主调函数中 数据对象的地址
不能返回在函数内部定义的局部数据对象的地址,这是 因为所有的局部数据对象在 函数返回时就会消亡,其值 不再有效
函数指针(指向函数的指针)
- 每个函数都占用一段内存单元,它们有一个入口地址( 起始地址)
- 在C语言中,函数名代表函数的入口地址。
- 可以定义一个指针变量,接收函数的入口地址,让它指向函数,这就是指向函数的指针,也称为函数指针。
- 通过函数指针可以调用函数,它也可以作为函数的参数
函数指针定义
类型名(*变量名)(参数类型表)
int (*futher)(int int)
类型名指定函数返回值的类型,变量名是指向函数的指针变量的名称。
调用
(*函数指针名)(参数表)
int fun(int x,int y);
int (*funptr)(int,int);
funptr=fun;
(*funptr)(3,5);
作用
#include<stdio.h>
int maxx(int x,int y){if(x>y) return x;return y;
}
int sum(int x,int y){return x+y;
}
int process(int x,int y,int (*fun)(int,int))
{int ret;ret=fun(x,y);return ret;
}
int main(){printf("%d\n",process(1,2,sum));printf("%d\n",process(1,2,maxx));
} //out:3 2
题目 待做
行指针(数组指针)程序解析
#include<stdio.h>
#include<string.h>
char (*defy(char *p))[5]
{int i;for(i=0;i<3;i++)p[strlen(p)]='A';return (char(*)[5])p+1;
}
int main(){char a[]="FROG\0SEAL\0LION\0LAMB";puts(defy(a)[1]+2);
}
out: ONALAMB
Chapter 6 算法分析基础
数据结构和算法的关系
数据:所有能被计算机识别、存储和处理的符号的集合(包括数字、字符、声音、图像等信息)。
数据元素:是数据的基本单位,具有完整确定的实际意义(又称元素、结点,顶点、记录等)。
数据项:构成数据元素的项目。是具有独立含义的最小标识单位(又称字段、域、属性等)。
数据对象:性质相同的数据元素的集合。
数据结构:是相互之间存在一种或多种特定关系的数据元素的集合
**逻辑结构: **指数据对象中数据元素之间的相互关系,面向问题
eg 线性表:有起点终点,前驱后继
**物理结构: **指数据的逻辑结构在计算机中的存储形式,面向程序
eg 顺序存储 :可以用一组地址连续的存贮单元依次存储线性表元素(可通过数组实现)
算法效率的度量方法和大0记法
算法的特性: 输入,输出,有穷性,确定性,可行性
**算法设计要求:**正确性,可读性,健壮性(当输入数据不合法时,算法能做出相关处理,而非产生异常结果),时间效率高,存储量低
算法的时间复杂度
判断一个算法的效率时,函数中的常数和其他次要项常常可以忽略,更应该关注最高次项的次数(阶数)
除非特别指定,提到的都是最坏时间复杂度
常见的时间复杂度有:
常数阶O(1),对数阶O(log2n),线性阶O(n),线性对数阶O(nlog2n),平方阶O(n2),立方阶O(n3),k次方阶O(nk),指数阶O(2n),阶乘阶O(n!)
算法的空间复杂度
存储算法本身所占用的存储空间,算法的输入输出数据所占用的存储空间,算法在运行程序中临时占用的存储空间。 算法的空间复杂度S(n)算法是对一个算法在运行过程中临时占用存储空间大小的量 度。
查找算法—线性、二分
查找方法
- 静态查找:线性查找,折半查找,索引查找
- 动态查找:二叉排序树,平衡二叉树
- 哈希表:构造哈希函数,处理冲突方法 开放定址法(线性探测法,二次探测法,伪随机探测法),链地址法,再哈希法,建立一个公共溢出区
二分查找
-
在已排好序的数列中查找
-
可以用while语句实现,也可用递归函数实现
while(low<=high){mid=(low+high)/2;if() high=mid-1;else low=mid+1; }
插值查找法
核心是插值公式 时间复杂度不变(平均变快)
适用于分布均匀的情况
二分查找法
mid=(low+high)/2=low+(high-low)/2
优化:插值查找法
mid=low+(high-low)*(key-a[low])/(a[high]-a[low])
排序算法
排序方法 | 最好时间 | 平均时间 | 最坏时间 | 辅助空间 | 稳定性 |
---|---|---|---|---|---|
简单选择 | n^2 | n^2 | n^2 | 1 | 不稳定 |
冒泡排序 | n | n^2 | n^2 | 1 | 稳定 |
直接插入 | n | n^2 | n^2 | 1 | 稳定 |
归并排序 | nlogn | nlogn | nlogn | n | 稳定 |
稳定排序:
值相同的元素排序后相对位置不发生改变。
内排序 插入,选择,交换 等
在排序过程中待排序的记录全部放置在内存中
冒泡排序
两两比较相邻记录的关键字,若反序则交换,直至没有反序对
含有n个元素的数组原则上要进行n-1次排序。 对于每一次排序,从第一个数开始,依次比较前一个数与后一个数的大小。如果前一个数比后一个数大,则进行交换。这样一轮过后,最大的数将会“沉到底”,成 为最末位的元素。第二轮则去掉最后一个数,对前n-1个 数再按照上面的步骤找出最大数,该数将成为倒数第二 位的元素…n-1轮过后,就完成了排序。
时间效率: O(n^2) ,稳定排序
void bubblesort0(){int i,j;for(i=1;i<L->length;i++){for(j=i+1;j<L->length;j++)if(L->r[i]>L->r[j])swap(L,i,j);}
}void bubblesort1(){//真实的冒泡int i,j;for(i=1;i<L->length;i++){for(j=L->length-1;j>=i;j--)if(L->r[j]>L-r[j+1])swap(L,j+1,j);}
}
选择排序
对一组数据,每次将其中的一个数据放在它最终要放的位置。第一步 是找到整个数据中最小的数据并把它放在最终要放的第一个位置上,第 二步是在剩下的数据中找最小的数据并把它放在第二个位置上。对所有 数据重复这个过程,最终将得到按从小到大顺序排列的一组数据。
int temp,index;
for(k=1;k<=n;k++){index=k;for(int i=k+1;i<=n;i++)if(x[i]<x[index]) index=i;temp=x[index];x[index]=x[k];x[k]=temp;
}
插入排序
将待排序的记录Ri插入,到已排好序的记录表 R1, R2 ,…., Ri-1中,得到一个新的、记录数增加1的有序表。 直到所有的记录都插入完为止。
设待排序的记录顺序存放在数组R[1…n]中,在排序的某一时刻,将记录序列分成两部分:
◆ R[1…i-1]:已排好序的有序部分;
◆ R[i…n]:未排好序的无序部分。
显然,在刚开始排序时,R[1]是已经排好序的。
int i,j;
for(i=2;i<=n;i++){if(x[i]<x[i-1]){x[0]=x[i];/*设置哨兵*/for(j=i-1;x[j]>x[0];j--)x[j+1]=x[j];x[j+1]=x[0];}
}
归并排序
对于一个规模为n的问题,若该问题可以容易地解决 (比如说规模n较小)则直接解决,否则将其分解为k 个规模较小的子问题,这些子问题互相独立且与原问题 形式相同,递归地解这些子问题,然后将各子问题的解 合并得到原问题的解。这种算法设计策略叫做分治法。
归并排序就是一个典型的分治法的例子,将一个数列 分成两部分,分别排序,然后合并。 合并操作与递归分解相结合,产生了新的排序算 法——归并排序。
算法描述:首先判断数组大小,若无元素或只有一个 元素,则数组必然已被排序;若包含的元素多于1个, 则执行下列步骤:
- step1: 把数组分为大小相等的两个子数组;
- step2: 对每个子数组递归采用归并算法进行排序;
- step3: 合并两个排序后的子数组。
#define MAXSIZE 1000
void Merge(int *x,int *y,int s,int m,int t){int i=s,j=m+1,k=s;while(i<=m&&j<=t){if(x[i]<x[j])y[k]=x[i],i++;elsey[k]=x[j],j++;k++; }while(i<=m) {y[k]=x[i];i++;k++;} while(j<=t){y[k]=x[j];j++;k++;}
}
void MergeSort(int *SR,int *TR,int s,int t){int m;int TR2[MAXSIZE];if(s==t)TR[s]=SR[s];else{m=(s+t)/2;MergeSort(SR,TR2,s,m);MergeSort(SR,TR2,m+1,t);Merge(TR2,TR,s,m,t);}
}
int main(){int x[100],n;scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&x[i]);}MergeSort(x,x,1,n);
}
位运算
位运算的操作数必须是int型或者char型
位逻辑运算 ~, &, ^, |
移位运算 << , >>
复合位赋值运算 &= , |= , ^= , >>= , <<=
符号 | 名称 | 规则 |
---|---|---|
~ |
按位取反 | 单目,右结合 |
& |
按位与 | 同1则1 |
^ |
按位异或 | 不同取1,相同取0 |
| |
按位或 | 有1则1 |
<< |
左移 | 高位丢弃,低位补0 |
>> |
右移 | 低位丢弃,高位补0或1(系统实现不同) |
Chapter 7 图形程序设计基础
- 初步了解Windows程序,理解Windows消息机制和事件编程
- 学习课程交互式图形编程的基本框架
- 学习使用Windows API来编写GUI程序
- 熟悉graphics.h的接口函数,实现基本的图形程序,实践综合性交互式图形程序
GUI编程相关C基础知识
typedef
已有类型重新命名
函数指针
int (*funptr)(int a,int b);
typedef void (*FunPtr)(int a,int b);
FunPtr fptr;//<==> void (*fptr)(int a,int b);
值调用
switch (a){case 0:a0();break;case 1:a1();break;case 2:a2();break;
}
// <==>
void(*fa[])()={a0,a1,a2};
if(a>=0&&a<sizeof(fa)/sizeof(fa[0]))(*fa[a])();
void bubble(int array[],int n,int (*compare)(int a,int b))
{int i,j,k;for(j=0;j<n-1;j++)for(i=0;i<n-1-j;i++)if((*compare)(array[i],array[i+1])){t=array[i];array[i]=array[i+1];array[i+1]=t;}
}
联合体
union perdata
{int class;char officae[10];
}
perdata a,b;
结构体中,各成员有各自的内存空间
联合体中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。联合变量可被赋予任一成员值,但每次只能赋一种值,赋入新值则冲去旧值。
枚举
enum DAY{MON=1,TUE,WED,THU,FRI,SAT,SUN
};
enum today;
today=TUE;
- 枚举型是一个集合,集合中的元素(枚举成员)是一些命名的整型常量,元素之间用逗号隔开。
- DAY是一个标识符,可以看成这个集合的名字,是一个可选项,即是可有可无的项。
- 第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1.
- 可以人为设定枚举成员的值,从而自定义某个范围内的整数。
- 枚举型是预处理指令#define的替代。
- 枚举变量类型取值集合即为枚举成员
Windows编程入门
windows API 应用程序编程接口
在windows上运行的程序,本质上都是通过调用Windows API来完成功能的
DOS VS Windows
- DOS是磁盘操作系统的缩写,它是一个单任务的操作系统,一般都是黑底白色文字的界面。DOS下的程序是过程驱动的。
- Windows是一个多任务的操作系统,它有方便用户使用的交互式界面。Windows下的程序是事件驱动的。
windows程序结构
控制台程序以main()为入口函数,Windows程序以WinMain()为入口函数
窗口
句柄
基本图形函数
绘图函数 | |
---|---|
InitGraphics() | Initializes the graphics package, open the window for rendering |
MovePen(x, y) | Moves the pen to an absolute position |
DrawLine(dx, dy) | Draws a line from current position to a relative coordinates |
DrawArc(r, start, sweep) | Draws an arc specified by a radius and two angles |
GetWindowWidth() | Returns the width of the graphics window |
GetWindowHeight() | Returns the height of the graphics window |
GetCurrentX() | Returns the current x-coordinate of the pen |
GetCurrentY() | Returns the current y-coordinate of the pen |
文本函数 | |
---|---|
DrawTextString(char *string*) |
从当前位置开始输出文本(字符串)string(字符串指针) |
int sprintf(char *str,const char *format) |
将格式化数据输出到一个缓冲区中,形成一个字符串 |
其他函数 | |
---|---|
void InitConsole(void); | 打开一个控制窗口 ; 从而可以用scanf/printf进行 quick&dirty 输入输 出 ;方便调试程序 |
void SetWindowSize(double w, double h); | 设置窗口的大小 w - 窗口宽度,单位英寸 ;h -窗口高度,单位英寸 。如果设置的尺寸大于屏幕尺寸,那么 系统会进行等比例的缩小 ,使得符合屏幕大小 |
void StartFilledRegion(double density); void EndFilledRegion(void); | 区域填充开启函数 ,开启填充->绘制封闭图形->停止填充 |
其他函数
void SetWindowTitle(string title);void SetPointSize(int size);
int GetPointSize(void);void SetPenSize(int size);
int GetPenSize(void);void DrawTextString(string text);
double TextStringWidth(string text);void DrawArc(double r, double start, double sweep);
void DrawEllipticalArc(double rx, double ry, double start, double sweep);
void DefineColor(string name, double red, double green, double blue);void SetFont(string font);
string GetFont(void);
以画圆为例
文件准备
-
myGraphics
- libgraphics //
存放解压后图形库文件 - simpleGUI
存放解压后的simpleGUI文件 - myDevProject
存放devc工程文件,临时文件包含其中 - mySource Files
存放自己编写的源代码
- libgraphics //
建立项目
- 打开DEV-C++
- 文件 -> 新建 -> 项目 新建一个Windows Application项目,C语言,重新命名为drawCircle,将生成的drawCircle.dev工程文件保存到myDevProject文件夹中
- 将默认的main.c保存到mySource Files文件夹(名字可改)由于本次使用第三方库编程,不需要模板代码,可将全部内容删去
- 项目管理->鼠标右键点“drawCircle”->添加文件夹libgraphics
- 继续鼠标右键点”libgraphics“,添加MyGraphics\libgraphics文件夹下的14个文件
- 选择菜单项目 -> 项目属性 -> 文件/目录 -> 包含文件目录,将MyGraphics\libgraphics完整路径加入
开始编写main.c
#include "graphics.h"
#include "extgraph.h"
#include "genlib.h"
#include "simpio.h"
#include "random.h"
#include "strlib.h"
#include "conio.h"
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
#include <windows.h>
#include <olectl.h>
#include <mmsystem.h>
#include <wingdi.h>
#include <ole2.h>
#include <ocidl.h>
#include <winuser.h>
/*包含图形库中所有可能用到的头文件所需的头文件*/static double cx,cy; /*圆心坐标*/
void DrawCircle(double x,double y,double r);/* 画圆函数声明*/void Main(){ /*程序入口函数,相当于控制台程序main函数*/InitGraphics();/*初始化得到空窗口*/cx=GetWindowWidth()/2;/*得到窗口宽度的一半*/cy=GetWindowHeight()/2;/*得到敞口高度的一半*/DrawCircle(cx,cy,1);/*在窗口中心画一个半径为1的圆*/
}
/*
画圆函数DrawCircle(double x, double y, double r)x为圆心横坐标y为圆心纵坐标r为圆半径
*/
void DrawCircle(double x,double y,double r){MovePen(x+r,y);/*移动画笔到圆的最右段*/DrawArc(r,0.0,360.0);/*从画笔位置开始,画一个0-360度半径为r的弧线*/
}
交互式GUI编程基础
回调函数
- 当事件发生时,调用我的函数
1.给将来会发生事件的地方注册一个回调函数.
2.当事件发生时,该回调函数被调用(执行).
-
回调函数经常用于事件处理( event handling ),譬如:当按下键盘、移动鼠标 等事件发生时,就调用相应的回调函数去 处理这些操作.
-
可在回调函数中实现对图形的交互。
-
注册函数已在系统中定义,直接调用即可。回调函数需要自己写
键盘消息回调函数
typedef void (*KeyboardEventCallback) (int key, int event);
/*key表示哪个键(键盘虚拟码)
event表示按下或松开等事件*///注册回调函数
void registerKeyboardEvent ( KeyboardEventCallback callback);registerKeyboardEvent(mykeyboard);
void mykeyboard(int key, int event)
{…. // 实现代码略
}
字符消息回调函数
typedef void (*CharEventCallback) (int char); void registerCharEvent ( CharEventCallback callback);registerCharEvent( mychar);
void mychar(int char)
{…. // 实现代码略
}
鼠标消息回调函数
typedef void (*MouseEventCallback) (int x, int y, int button, int event);
/*x,y 位置坐标,button鼠标键
Event是鼠标事件:按下、松开、移动*/void registerMouseEvent ( MouseEventCallback callback);registerMouseEvent( mymouse);
void mymouse(int x, int y, int button, int event )
{…. // 实现代码略
}
定时器消息回调函数
typedef void (*TimerEventCallback) (int timerID);void registerTimerEvent ( TimerEventCallback callback);registerTimerEvent( mytimer);
void mytimer(int timerID)
{…. // 实现代码略
}
启动定时器
void startTimer( int timerID, int timeinterval);
// timerID - 定时器的编号
// timeinterval - 定时间隔
关闭某个定时器
void cancelTimer( int timerID );
// timerID - 定时器的编号
chapter 8 SimpleGUI
去看imgui库
熟悉simpleGUI库,实现带button、菜单、文本框等控件的交互式图形程序
图形绘制是像素级,图形库里部分函数是以英寸为单位的
-
是一种简单的即时模式GUI
-
适合高刷新率的应用程序
-
屏幕总在实时刷新
-
目前只实现了三个控件
- button 鼠标按钮
- menulist 菜单列表
- textbox 编辑字符串
-
必须和libgraphics库一起使用
-
在程序中包含头文件
#include "imgui.h"
-
将imugui.c加入程序工程中,或者在某个C文件中包含它(不推荐)
-
在鼠标处理函数中调用simpleGUI函数
uiGetMouse 记录鼠标状态
void MouseEventProcess(int x,int y,int button,int event) {/*获取鼠标状态*/uiGetMouse(x,y,button,event);/*擦除屏幕*/DisplayClear();/*调用显示函数显示内容*/display();}
button控件
所有的控件的创建和响应都在 display函数中完成
调用button函数 创建一个按钮
根据返回值判断 用户是否点击了 该按钮,并进行 相应处理。
void display()
{double fH=GetFontHeight();//字体的高度double h=fH*2;double x=winwidth/2.5;double y=winheight/2-h;double w=winwidth/5;/*button(GenUIID(0),x,y,w,h,"OK");GenUIID(0) 创建一个id句柄x,y起始位置w宽度 h高度button信息*/button(GenUIID(0),x,y,w,h,"OK");button(GenUIID(0),x+=w,y,w,h,"Cancel");if(button(GenUIID(0),x+=w,y,w,h,"Quit"))exit(-1);
}
关于宏 GenUIID
#define GenUIID(N) ( ((__LINE__<<16) | ( N & 0xFFFF))^((long)&__FILE__) )
**GenUIID(k) **在编译时计算生成一个唯一号。计算时使用 :参数k,宏调用所在的 文件名,宏调用所在的 行号 ,宏调用时的参数 k
-
用法 1: GenUIID(0) 如果一行代码只产生一个唯 一ID
-
用法 2: GenUIID(k)
如果需要在一行代码产生多 个不同的唯一ID。
例如: 用for循环创建三个按钮,纵向排 列,标签为names[k]for( k = 0; k<3; k++ ) {button(GenUIID(k), x, y-k*40, w, h, names[k]); }
menulist控件
-
在display函数中完成menu控件的创建和响应
-
定义菜单选项字符串
```c
char * menuListFile[ ] = {"File",
"Open | Ctrl-O",
"Close",
"Exit | Ctrl-E" };
```
- 绘制和处理菜单
```c
selection = menuList(GenUIID(0), x, y, w, wsub, h,
menuListFile,sizeof(menuListFile)/sizeof(menuListFile[0]));
if( selection==3 ) // choose to the menu of exitexit(-1); // act on the selection
```
-
用户可以用鼠标选择菜单,也可以用快捷键
-
快捷键在选项字符串中给出
-
快捷键必须是Ctrl-X形式,而且位于字符串的结尾部分
-
为了使用快捷键,还需要调用simpleGUI的uiGetKeyboard 函数
-
参数说明
int menuList(int id,double x,double y, //x, y - 菜单左上角坐标double w, //w - 类别标签的显示宽度double wlist, //wlist – 菜单选项的显示宽度double h, //h – 菜单项的显示高度char *labels[],//labels[0]是菜单的类别名,labels[1……n-1]是该类别菜单选项标签,其中可以包含快捷键int n //– labels中标签字符串的个数);
text控件
- 在display函数中完成textbox控件的创建和编辑
static char str[80] = "Click and Edit";textbox(GenUIID(0), x, y, w, h, str, sizeof(str));
-
如果有多个textbox,用户可以用Tab和Shift+Tab在他们 之间轮转
-
还可以根据textbox返回值判断用户是否进行了编辑
必须定义为static,用于每个编辑框文本的存在,否则无法修改,每次都重新定义
控件颜色设置
- 调用下面的函数,使用预定义的颜色组合
void usePredefinedColors(int k);
void usePredefinedButtonColors(int k);
void usePredefinedMenuColors(int k);
void usePredefinedTexBoxColors(int k);
-
函数usePredefinedColors会对button/menu/textbox三 种类型全部进行设置
-
而其他的三个函数对button/menu/textbox分别进行设置
-
设置自定义的颜色组合
- 当某个参数字符串为空时,对应的颜色不做改变
- 颜色设置是状态变量,会影响之后绘制的控件
1. setButtonColors - 设置按钮颜色 2. setMenuColors - 设置菜单颜色 3. setTextBoxColors - 设置编辑框颜色 参数 1. frame/label - 控件框/文字标签的颜色 2. hotFrame/hotLabel - 鼠标划过时,控件框/文字标签的颜色 3. fillflag - 是否填充背景。0 - 不填充,1 - 填充void setButtonColors (char *frame, char*label, char *hotFrame, char *hotLabel, int fillflag); void setMenuColors (char *frame, char*label, char *hotFrame, char *hotLabel, int fillflag); void setTextBoxColors(char *frame, char*label, char *hotFrame, char *hotLabel, int fillflag);
其他辅助画图函数
画一个矩形 (x,y,w,h)
fillflag 是填充与否的标志
1 - 填充
0 - 不填充
void drawRectangle(double x, double y, double w, double h,int fillflag);
同时画矩形和标签字符串
xalignment – 指定标签和矩形的对齐方式'L' - 靠左'R' - 靠右其他- 居中
labelColor – 指定标签的颜色名void drawBox(double x, double y,double w, double h, int fillflag,char *label, char xalignment,char *labelColor);
如若内容造成侵权/违法违规/事实不符,请联系编程学习网邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
相关文章
- 如何解决IIS7多域名绑定同一物理目录,设置不同的默认文档的问题?
因为在一个物理目录下只有一个web.config,并且IIS7把默认文档设置写在这里,导致所有域名的默认文档设置共享,很多人对此束手无策,甚至有人说这是IIS7的bug。其实IIS7不会比IIS6落后的,这个问题也很好解决,下面是解决方案: 1、进入%windir%\system32\inetsrv\config目录(…...
2024/5/10 3:41:11 - 7.矩阵变换
1.使用OpenGL Mathematics,下载GLM后,将文件路径加入包含路径(不需要编译和链接)2.平移、旋转、缩放矩阵glm::vec4 vec(1.0f,0.0f,0.0f,1.0f); //默认是一个单位矩阵(9.9版本之后的GLM应改为glm::mat4 trans(1.0f);) glm::mat4 trans; //缩放 trans = glm::scale(trans,g…...
2024/5/10 3:41:09 - 抖音新人如何快速上热门涨粉,直播间怎么开通。
抖音上热门的好处,不用多说,应该都知道。增加曝光量,圈粉无数。除此之外,还能收获名气、金钱等等,可谓是名利双收。 所以,只要是玩抖音的,没有哪个是不想上热门,收获成千上万的赞、评论还有粉丝。但是,热门不是你想上,想上就能上。 根据抖音官方的要求,抖音如何上热…...
2024/5/10 3:41:10 - 全面解析抖音直播各类玩法;新人也能快速直播。
直播是引流和吸粉最强劲的渠道之一,作为短视频平台的领头羊,抖音在2020年将会大力推进直播板块的发展。 最近有粉丝询问猫哥抖音直播相关问题,猫哥留意到其中一些粉丝对抖音直播不太了解。这一期猫哥带大家全方位了解抖音直播。 一.如何开启抖音直播 抖音平台直播方式有视频…...
2024/5/10 2:58:53 - 适配IE11踩雷备忘录
最最重要的放最前面:import ‘babel-polyfill’ 自己下一个 ‘babel-polyfill’ npm install babel-polyfill --save-dev 同时webpack.base.conf.js里面要 entry: { app: [‘babel-polyfill’, ‘./src/main.js’] }, 1.日历,IE11不认2020-01-01,要2020/01/01,可以data.…...
2024/5/10 2:58:51 - 数列删除元素后取中心数
题目简介:将一个偶数个数列,遍历每个数,假设每个数被删除后,输出剩余数列的中位数 例: 输入:123456 输出:444333 (ps:大概是这个意思,具体的记不太清楚了) 构思注意点: 1、数列不一定递增或者递减,是没有规律的数列 2、数列中有可能会存在重复的情况 大致的想法: …...
2024/5/10 2:58:50 - JWT详细学习
JWT学习 B站编程不良人–JWT篇 一、什么是JWT JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and truste…...
2024/5/10 2:58:49 - 9.Ajax实例
https://www.runoob.com/ajax/ajax-examples.html...
2024/5/10 3:41:07 - Python主要工作岗位有哪些 它本身有哪些优势
Python工作岗位有哪些?它本身有哪些优势?Python在编程领域的占有率一直处于稳步上升之中,随着人工智能的发展,Python也变得越来越火爆。Python是一门比较好学的编程语言,非常适合入门。下面跟随小编一起来看看吧。Python工作岗位主要包括以下几种:Python开发工程师、Pyth…...
2024/5/10 3:41:06 - C++的继承知识点重温
派生类声明形式:class 派生类名: 继承方式 基类名1,继承方式 基类名2,...继承中的访问控制:公有继承:公用基类成员在派生类中的访问属性publicpublicprotectedprotectedprivate不可访问私有继承:私有基类成员在派生类中的访问属性publicprivateprotectedprivateprivate不…...
2024/5/10 3:41:05 - 每日一练之旅游路径
题目: 给你一趟旅行中所有的车票信息,请用程序找出旅行线路。比如有车票<大连,北京>, <哈尔滨,大连>, <北京,深圳>,则可以推测路线为<哈尔滨,大连,北京,深圳>。 #include <iostream> #include <vector> #include <unordered_m…...
2024/5/10 3:41:05 - 15天日出千刀!新品推广实战技巧全解析
随着跨境电商的崛起,亚马逊作为全球最大的电商平台,自然是受到广大卖家的追捧!在这个人人都想分得一杯羹的平台,卖家想要出头就得凭借过硬的运营和优质资源才行!正所谓万事开头难,而做亚马逊亦是如此!很多卖家在新品前期就做得不是很好,导致在后期的运营或者维护中十分…...
2024/5/10 3:41:03 - Ajax三级联动对比jQuery三级联动
Ajax三级联动 <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>三级联动</title> </h…...
2024/5/9 8:38:27 - 【BOLL趋势-EA】双剑合璧,月盈利45%左右,最大回撤10%左右
BOLL指标,即布林指标,又叫布林线指标。 BOLL指标是一种非常简单实用的技术分析指标,是研究市场中长期运动趋势的一种重要技术分析工具。BOLL指标由三条线组成,即上轨线,中轨线,下轨线组成。BOLL指标通过这三条线之间的关系再结合其它指标成为研判大盘趋势的有效工具。那么…...
2024/5/10 3:41:02 - windows系统怎样查看非本机系统的注册表信息
如果有一台电脑系统瘫痪了,而又急需原系统中注册表的某些信息该怎么办?第一步,找到注册表相关文件:把用户硬盘挂到一台正常电脑下,或者启动pe系统,复制出以下需要的文件系统注册表文件在c:\windows\system32\config下,例如system文件对应的注册表中HKEY_LOCAL_MACHINE下…...
2024/5/10 3:41:01 - centos7中没有安装ifconfig命令的解决方法
centos7中没有安装ifconfig命令的解决方法参考文章: (1)centos7中没有安装ifconfig命令的解决方法 (2)https://www.cnblogs.com/jtnote/p/6103754.html 备忘一下。...
2024/5/10 3:41:00 - wordExport导出word时关于echarts图表生成图片的解决方案
一、基本介绍 wordExport是一款基于前端处理生成word的处理方式 在对应页面引入FileSaver.js和jquery.wordexport.js使用:需生成word的部分.wordExport(文件名,文件样式)二、echarts相关 一般我们页面存在echarts图表导出word时通常时将其先生成为一张图片,再将其导出,在图表…...
2024/5/10 3:40:58 - 使用mybatis执行增删改查操作
步骤:首先在pom里导入依赖—>先写工具类—>环境准备resource里的mybatis-config.xml —>写实体类—>写接口—>写接口对应的xml配置文件—>写test文件 pom文件依赖: <?xml version="1.0" encoding="UTF-8"?> <project xmlns…...
2024/5/10 3:40:59 - webpack 解决Install fail! Error: EBUSY: resource busy or locked报错
如果使用的webpack 4+ 版本,还需要安装webpack - cli,因为webpack 4将 cli 分离出来了,我这里用的是cnpm安装的 cnpm install --save webpack-cli 安装的时候报如上错误,解决方案:关闭电脑上的杀毒软件,比如360。...
2024/5/10 3:40:57 - ES6学习笔记(九)之函数的扩展1
关于函数参数的默认值允许为函数的参数设置默认值,直接写在参数的定义的后面。 参数变量是默认声明的,不能用 let 或 const 再次声明。 使用参数默认值时,函数不能有同名参数。 参数默认值是惰性求值(每次都重新计算默认值表达式的值)。 参数默认值可与解构赋值的默认值结…...
2024/5/10 3:40:56
最新文章
- gif压缩大小但不改变画质怎么做?分享5个压缩GIF原理~
GIF(图形互换格式)是网络上广泛使用的一种图像格式,因其支持动画而备受欢迎。然而,随着动画越来越复杂和高分辨率,GIF 文件大小也随之增加,可能导致加载速度变慢和带宽消耗增加。在这篇文章中,我…...
2024/5/10 18:42:53 - 梯度消失和梯度爆炸的一些处理方法
在这里是记录一下梯度消失或梯度爆炸的一些处理技巧。全当学习总结了如有错误还请留言,在此感激不尽。 权重和梯度的更新公式如下: w w − η ⋅ ∇ w w w - \eta \cdot \nabla w ww−η⋅∇w 个人通俗的理解梯度消失就是网络模型在反向求导的时候出…...
2024/5/9 21:23:04 - 《c++》多态案例一.电脑组装
一.代码展示 #include <iostream> using namespace std; class CPU { public://抽象计算函数virtual void calculate() 0;};class CVideoCard { public://抽象显示函数virtual void display() 0;}; class Memory { public://抽象存储函数virtual void storage() 0;};…...
2024/5/10 2:15:55 - 6.9物联网RK3399项目开发实录-驱动开发之PWM的使用(wulianjishu666)
嵌入式实战开发例程,珍贵资料,开发必备: 链接:https://pan.baidu.com/s/1149x7q_Yg6Zb3HN6gBBAVA?pwdhs8b PWM 使用 前言 AIO-3399J 开发板上有 4 路 PWM 输出,分别为 PWM0 ~ PWM3,4 路 PWM 分别使用在…...
2024/5/10 10:04:29 - 416. 分割等和子集问题(动态规划)
题目 题解 class Solution:def canPartition(self, nums: List[int]) -> bool:# badcaseif not nums:return True# 不能被2整除if sum(nums) % 2 ! 0:return False# 状态定义:dp[i][j]表示当背包容量为j,用前i个物品是否正好可以将背包填满ÿ…...
2024/5/10 1:36:26 - 【Java】ExcelWriter自适应宽度工具类(支持中文)
工具类 import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet;/*** Excel工具类** author xiaoming* date 2023/11/17 10:40*/ public class ExcelUti…...
2024/5/10 16:45:57 - Spring cloud负载均衡@LoadBalanced LoadBalancerClient
LoadBalance vs Ribbon 由于Spring cloud2020之后移除了Ribbon,直接使用Spring Cloud LoadBalancer作为客户端负载均衡组件,我们讨论Spring负载均衡以Spring Cloud2020之后版本为主,学习Spring Cloud LoadBalance,暂不讨论Ribbon…...
2024/5/10 16:45:56 - TSINGSEE青犀AI智能分析+视频监控工业园区周界安全防范方案
一、背景需求分析 在工业产业园、化工园或生产制造园区中,周界防范意义重大,对园区的安全起到重要的作用。常规的安防方式是采用人员巡查,人力投入成本大而且效率低。周界一旦被破坏或入侵,会影响园区人员和资产安全,…...
2024/5/10 2:07:45 - VB.net WebBrowser网页元素抓取分析方法
在用WebBrowser编程实现网页操作自动化时,常要分析网页Html,例如网页在加载数据时,常会显示“系统处理中,请稍候..”,我们需要在数据加载完成后才能继续下一步操作,如何抓取这个信息的网页html元素变化&…...
2024/5/10 8:07:24 - 【Objective-C】Objective-C汇总
方法定义 参考:https://www.yiibai.com/objective_c/objective_c_functions.html Objective-C编程语言中方法定义的一般形式如下 - (return_type) method_name:( argumentType1 )argumentName1 joiningArgument2:( argumentType2 )argumentName2 ... joiningArgu…...
2024/5/10 16:45:52 - 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】
👨💻博客主页:花无缺 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 本文由 花无缺 原创 收录于专栏 【洛谷算法题】 文章目录 【洛谷算法题】P5713-洛谷团队系统【入门2分支结构】🌏题目描述🌏输入格…...
2024/5/10 8:16:30 - 【ES6.0】- 扩展运算符(...)
【ES6.0】- 扩展运算符... 文章目录 【ES6.0】- 扩展运算符...一、概述二、拷贝数组对象三、合并操作四、参数传递五、数组去重六、字符串转字符数组七、NodeList转数组八、解构变量九、打印日志十、总结 一、概述 **扩展运算符(...)**允许一个表达式在期望多个参数࿰…...
2024/5/10 2:07:43 - 摩根看好的前智能硬件头部品牌双11交易数据极度异常!——是模式创新还是饮鸩止渴?
文 | 螳螂观察 作者 | 李燃 双11狂欢已落下帷幕,各大品牌纷纷晒出优异的成绩单,摩根士丹利投资的智能硬件头部品牌凯迪仕也不例外。然而有爆料称,在自媒体平台发布霸榜各大榜单喜讯的凯迪仕智能锁,多个平台数据都表现出极度异常…...
2024/5/10 2:07:43 - Go语言常用命令详解(二)
文章目录 前言常用命令go bug示例参数说明 go doc示例参数说明 go env示例 go fix示例 go fmt示例 go generate示例 总结写在最后 前言 接着上一篇继续介绍Go语言的常用命令 常用命令 以下是一些常用的Go命令,这些命令可以帮助您在Go开发中进行编译、测试、运行和…...
2024/5/10 16:45:47 - 用欧拉路径判断图同构推出reverse合法性:1116T4
http://cplusoj.com/d/senior/p/SS231116D 假设我们要把 a a a 变成 b b b,我们在 a i a_i ai 和 a i 1 a_{i1} ai1 之间连边, b b b 同理,则 a a a 能变成 b b b 的充要条件是两图 A , B A,B A,B 同构。 必要性显然࿰…...
2024/5/10 16:45:46 - 【NGINX--1】基础知识
1、在 Debian/Ubuntu 上安装 NGINX 在 Debian 或 Ubuntu 机器上安装 NGINX 开源版。 更新已配置源的软件包信息,并安装一些有助于配置官方 NGINX 软件包仓库的软件包: apt-get update apt install -y curl gnupg2 ca-certificates lsb-release debian-…...
2024/5/9 19:47:07 - Hive默认分割符、存储格式与数据压缩
目录 1、Hive默认分割符2、Hive存储格式3、Hive数据压缩 1、Hive默认分割符 Hive创建表时指定的行受限(ROW FORMAT)配置标准HQL为: ... ROW FORMAT DELIMITED FIELDS TERMINATED BY \u0001 COLLECTION ITEMS TERMINATED BY , MAP KEYS TERMI…...
2024/5/10 10:17:11 - 【论文阅读】MAG:一种用于航天器遥测数据中有效异常检测的新方法
文章目录 摘要1 引言2 问题描述3 拟议框架4 所提出方法的细节A.数据预处理B.变量相关分析C.MAG模型D.异常分数 5 实验A.数据集和性能指标B.实验设置与平台C.结果和比较 6 结论 摘要 异常检测是保证航天器稳定性的关键。在航天器运行过程中,传感器和控制器产生大量周…...
2024/5/10 2:07:41 - --max-old-space-size=8192报错
vue项目运行时,如果经常运行慢,崩溃停止服务,报如下错误 FATAL ERROR: CALL_AND_RETRY_LAST Allocation failed - JavaScript heap out of memory 因为在 Node 中,通过JavaScript使用内存时只能使用部分内存(64位系统&…...
2024/5/10 16:37:19 - 基于深度学习的恶意软件检测
恶意软件是指恶意软件犯罪者用来感染个人计算机或整个组织的网络的软件。 它利用目标系统漏洞,例如可以被劫持的合法软件(例如浏览器或 Web 应用程序插件)中的错误。 恶意软件渗透可能会造成灾难性的后果,包括数据被盗、勒索或网…...
2024/5/10 15:01:36 - JS原型对象prototype
让我简单的为大家介绍一下原型对象prototype吧! 使用原型实现方法共享 1.构造函数通过原型分配的函数是所有对象所 共享的。 2.JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象,所以我们也称为原型对象…...
2024/5/9 16:54:42 - C++中只能有一个实例的单例类
C中只能有一个实例的单例类 前面讨论的 President 类很不错,但存在一个缺陷:无法禁止通过实例化多个对象来创建多名总统: President One, Two, Three; 由于复制构造函数是私有的,其中每个对象都是不可复制的,但您的目…...
2024/5/10 1:31:37 - python django 小程序图书借阅源码
开发工具: PyCharm,mysql5.7,微信开发者工具 技术说明: python django html 小程序 功能介绍: 用户端: 登录注册(含授权登录) 首页显示搜索图书,轮播图࿰…...
2024/5/10 9:24:29 - 电子学会C/C++编程等级考试2022年03月(一级)真题解析
C/C++等级考试(1~8级)全部真题・点这里 第1题:双精度浮点数的输入输出 输入一个双精度浮点数,保留8位小数,输出这个浮点数。 时间限制:1000 内存限制:65536输入 只有一行,一个双精度浮点数。输出 一行,保留8位小数的浮点数。样例输入 3.1415926535798932样例输出 3.1…...
2024/5/10 10:40:03 - 配置失败还原请勿关闭计算机,电脑开机屏幕上面显示,配置失败还原更改 请勿关闭计算机 开不了机 这个问题怎么办...
解析如下:1、长按电脑电源键直至关机,然后再按一次电源健重启电脑,按F8健进入安全模式2、安全模式下进入Windows系统桌面后,按住“winR”打开运行窗口,输入“services.msc”打开服务设置3、在服务界面,选中…...
2022/11/19 21:17:18 - 错误使用 reshape要执行 RESHAPE,请勿更改元素数目。
%读入6幅图像(每一幅图像的大小是564*564) f1 imread(WashingtonDC_Band1_564.tif); subplot(3,2,1),imshow(f1); f2 imread(WashingtonDC_Band2_564.tif); subplot(3,2,2),imshow(f2); f3 imread(WashingtonDC_Band3_564.tif); subplot(3,2,3),imsho…...
2022/11/19 21:17:16 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机...
win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”问题的解决方法在win7系统关机时如果有升级系统的或者其他需要会直接进入一个 等待界面,在等待界面中我们需要等待操作结束才能关机,虽然这比较麻烦,但是对系统进行配置和升级…...
2022/11/19 21:17:15 - 台式电脑显示配置100%请勿关闭计算机,“准备配置windows 请勿关闭计算机”的解决方法...
有不少用户在重装Win7系统或更新系统后会遇到“准备配置windows,请勿关闭计算机”的提示,要过很久才能进入系统,有的用户甚至几个小时也无法进入,下面就教大家这个问题的解决方法。第一种方法:我们首先在左下角的“开始…...
2022/11/19 21:17:14 - win7 正在配置 请勿关闭计算机,怎么办Win7开机显示正在配置Windows Update请勿关机...
置信有很多用户都跟小编一样遇到过这样的问题,电脑时发现开机屏幕显现“正在配置Windows Update,请勿关机”(如下图所示),而且还需求等大约5分钟才干进入系统。这是怎样回事呢?一切都是正常操作的,为什么开时机呈现“正…...
2022/11/19 21:17:13 - 准备配置windows 请勿关闭计算机 蓝屏,Win7开机总是出现提示“配置Windows请勿关机”...
Win7系统开机启动时总是出现“配置Windows请勿关机”的提示,没过几秒后电脑自动重启,每次开机都这样无法进入系统,此时碰到这种现象的用户就可以使用以下5种方法解决问题。方法一:开机按下F8,在出现的Windows高级启动选…...
2022/11/19 21:17:12 - 准备windows请勿关闭计算机要多久,windows10系统提示正在准备windows请勿关闭计算机怎么办...
有不少windows10系统用户反映说碰到这样一个情况,就是电脑提示正在准备windows请勿关闭计算机,碰到这样的问题该怎么解决呢,现在小编就给大家分享一下windows10系统提示正在准备windows请勿关闭计算机的具体第一种方法:1、2、依次…...
2022/11/19 21:17:11 - 配置 已完成 请勿关闭计算机,win7系统关机提示“配置Windows Update已完成30%请勿关闭计算机”的解决方法...
今天和大家分享一下win7系统重装了Win7旗舰版系统后,每次关机的时候桌面上都会显示一个“配置Windows Update的界面,提示请勿关闭计算机”,每次停留好几分钟才能正常关机,导致什么情况引起的呢?出现配置Windows Update…...
2022/11/19 21:17:10 - 电脑桌面一直是清理请关闭计算机,windows7一直卡在清理 请勿关闭计算机-win7清理请勿关机,win7配置更新35%不动...
只能是等着,别无他法。说是卡着如果你看硬盘灯应该在读写。如果从 Win 10 无法正常回滚,只能是考虑备份数据后重装系统了。解决来方案一:管理员运行cmd:net stop WuAuServcd %windir%ren SoftwareDistribution SDoldnet start WuA…...
2022/11/19 21:17:09 - 计算机配置更新不起,电脑提示“配置Windows Update请勿关闭计算机”怎么办?
原标题:电脑提示“配置Windows Update请勿关闭计算机”怎么办?win7系统中在开机与关闭的时候总是显示“配置windows update请勿关闭计算机”相信有不少朋友都曾遇到过一次两次还能忍但经常遇到就叫人感到心烦了遇到这种问题怎么办呢?一般的方…...
2022/11/19 21:17:08 - 计算机正在配置无法关机,关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机...
关机提示 windows7 正在配置windows 请勿关闭计算机 ,然后等了一晚上也没有关掉。现在电脑无法正常关机以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!关机提示 windows7 正在配…...
2022/11/19 21:17:05 - 钉钉提示请勿通过开发者调试模式_钉钉请勿通过开发者调试模式是真的吗好不好用...
钉钉请勿通过开发者调试模式是真的吗好不好用 更新时间:2020-04-20 22:24:19 浏览次数:729次 区域: 南阳 > 卧龙 列举网提醒您:为保障您的权益,请不要提前支付任何费用! 虚拟位置外设器!!轨迹模拟&虚拟位置外设神器 专业用于:钉钉,外勤365,红圈通,企业微信和…...
2022/11/19 21:17:05 - 配置失败还原请勿关闭计算机怎么办,win7系统出现“配置windows update失败 还原更改 请勿关闭计算机”,长时间没反应,无法进入系统的解决方案...
前几天班里有位学生电脑(windows 7系统)出问题了,具体表现是开机时一直停留在“配置windows update失败 还原更改 请勿关闭计算机”这个界面,长时间没反应,无法进入系统。这个问题原来帮其他同学也解决过,网上搜了不少资料&#x…...
2022/11/19 21:17:04 - 一个电脑无法关闭计算机你应该怎么办,电脑显示“清理请勿关闭计算机”怎么办?...
本文为你提供了3个有效解决电脑显示“清理请勿关闭计算机”问题的方法,并在最后教给你1种保护系统安全的好方法,一起来看看!电脑出现“清理请勿关闭计算机”在Windows 7(SP1)和Windows Server 2008 R2 SP1中,添加了1个新功能在“磁…...
2022/11/19 21:17:03 - 请勿关闭计算机还原更改要多久,电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机怎么办...
许多用户在长期不使用电脑的时候,开启电脑发现电脑显示:配置windows更新失败,正在还原更改,请勿关闭计算机。。.这要怎么办呢?下面小编就带着大家一起看看吧!如果能够正常进入系统,建议您暂时移…...
2022/11/19 21:17:02 - 还原更改请勿关闭计算机 要多久,配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以...
配置windows update失败 还原更改 请勿关闭计算机,电脑开机后一直显示以以下文字资料是由(历史新知网www.lishixinzhi.com)小编为大家搜集整理后发布的内容,让我们赶快一起来看一下吧!配置windows update失败 还原更改 请勿关闭计算机&#x…...
2022/11/19 21:17:01 - 电脑配置中请勿关闭计算机怎么办,准备配置windows请勿关闭计算机一直显示怎么办【图解】...
不知道大家有没有遇到过这样的一个问题,就是我们的win7系统在关机的时候,总是喜欢显示“准备配置windows,请勿关机”这样的一个页面,没有什么大碍,但是如果一直等着的话就要两个小时甚至更久都关不了机,非常…...
2022/11/19 21:17:00 - 正在准备配置请勿关闭计算机,正在准备配置windows请勿关闭计算机时间长了解决教程...
当电脑出现正在准备配置windows请勿关闭计算机时,一般是您正对windows进行升级,但是这个要是长时间没有反应,我们不能再傻等下去了。可能是电脑出了别的问题了,来看看教程的说法。正在准备配置windows请勿关闭计算机时间长了方法一…...
2022/11/19 21:16:59 - 配置失败还原请勿关闭计算机,配置Windows Update失败,还原更改请勿关闭计算机...
我们使用电脑的过程中有时会遇到这种情况,当我们打开电脑之后,发现一直停留在一个界面:“配置Windows Update失败,还原更改请勿关闭计算机”,等了许久还是无法进入系统。如果我们遇到此类问题应该如何解决呢࿰…...
2022/11/19 21:16:58 - 如何在iPhone上关闭“请勿打扰”
Apple’s “Do Not Disturb While Driving” is a potentially lifesaving iPhone feature, but it doesn’t always turn on automatically at the appropriate time. For example, you might be a passenger in a moving car, but your iPhone may think you’re the one dri…...
2022/11/19 21:16:57