编程的时候通常会用到的基本代码、知识
注意事项一:确保程序的时间复杂度,尽量提升程序的速度,这也要求了不同程序使用不同的算法.
注意事项二:确保程序的简洁性,注重程序中注释的使用。
基本知识
一、数学知识
1、素数
素数是指除1以外,只能被自身整除的数
注意:1不是素数,素数的反例是质数
2、阶乘 Factorial
C n m = n ! m ! ( n − m ) ! C_n^m=\frac{n!}{m!(n-m)!} Cnm=m!(n−m)!n!
A n m = n ! ( n − m ) ! = n ∗ ( n − 1 ) ∗ . . . ∗ ( n − m + 1 ) A_n^m=\frac{n!}{(n-m)!}=n*(n-1)*...*(n-m+1) Anm=(n−m)!n!=n∗(n−1)∗...∗(n−m+1)
MAX值:int型对应12!,long long对应20!
1! = 1
2! = 2
3! = 6
4! = 24
5! = 120
6! = 720
7! = 5040
8! = 40320
9! = 362880
10! = 3628800
11! = 39916800
12! = 479001600 //MAX int
13! = 6227020800
14! = 87178291200
15! = 1307674368000
16! = 20922789888000
17! = 355687428096000
18! = 6402373705728000
19! = 121645100408832000
20! = 2432902008176640000
1234567890123456789 //MAX long long int
3、斐波那契数列
一般递推式:
F(1)=1 F(2)=1 F(n)=F(n-1)+F(n-2)
一般会用到其变式~
数列值的另一种求法:
F
n
=
[
(
1
+
5
2
)
n
]
Fn=[(\frac{1+\sqrt{5}}{2})^n]
Fn=[(21+5)n]
其中[x]表示取距离x最近的整数。
应用一:台阶
有一段楼梯有10级台阶,规定每一步只能跨一级或两级,要登上第 10 级台阶有几种不同的走法?
这就是一个斐波那契数列:登上第一级台阶有一种登法;登上两级台阶,有两种登法;登上三级台阶,有三种登法;登上四级台阶,有五种登法……
应用二:兔子繁殖
一般而言,兔子在出生两个月后,就有繁殖能力,一对兔子每个月能生出一对小兔子来。如果所有兔子都不死,那么一年以后可以繁殖多少对兔子?
1 1 2 3 5 8…
4、矩阵的幂
矩阵的0次幂
除了矩阵的对角线上的元素值为1外,其他元素全部为0
二、计算机知识
各种类型的范围及输入输出关键字
Tips:C语言中整性最大精度为long long:9223372036854775807; 共19位
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
9 2 2 3 3 7 2 0 3 6 8 5 4 7 7 5 8 0 7
类型 | 最小值 | 最大值 | 输入关键字 | 输出关键字 | 字节数/byte | 二进制 |
---|---|---|---|---|---|---|
char | -128 | 128 | %c | %c | 1 | 27 |
short | -32767 | 32768 | %hd | - | 2 | 215 |
unsigned short | 0 | 65536 | %hu | - | 2 | 216 |
int | -2147483648 | 2147483647 | %d | %d | 4 | 231 |
unsigned int | 0 | 4294967295 | %u | %u | 4 | 232 |
long long | -9223372036854775808 | 9223372036854775807 | %l64d | - | 8 | 263 |
unsigned long long | 0 | 264 | %lld | - | 8 | 264 |
float | -3.40282e+038 | 3.40282e+038 | %f | %f | 8 | |
double | -1.7×10308 | 1.7×10308 | %lf | %f | 8 |
ASCII码表
三、日常知识
1、国际象棋布局
横:a b c d e f g h 共8行
纵:1 2 3 4 5 6 7 8 共8列
编程基本知识
1. 输出随机数的四种方式
前提:头文件包含stdlib.h
第一种:输出0~RAND_MAX之间的随机数
magic = rand();
第二种:输出num1~num2之间的随机数 num1、num2可以输入或者随机指定
int num1=100,num2=0; magic = rand()%num1+num2;
第三种:通过输入关键字来决定输出num1~num2之间的随机数
int seed=...; srand(seed); magic = rand()%num1+num2;
第四种:通过时间来控制输出num1~num2之间的随机数
srand(time(NULL)); magic rand()%num1~num2;
注意:头文件必须包含time.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
//这三个头文件必不可少
int main()
{
printf("Three means of outputing a random number.\n");
//随机数函数: rand()
int magic = 0, seed = 0;
//输出0~RAND_MAX之间的随机数
magic = rand();
printf("num_1: 0~RAND_MAX——%d\n", magic);
//输出num1~num2之间的随机数
int num1 = 0, num2 = 100;
magic = rand() % num2 + num1;
printf("num_2: num1(%d)~num2(%d)——%d\n", num1, num2, magic);
//通过键入关键字seed,输出0~100之间的随机数
printf("enter a number(seed): ");
scanf_s("%d", &seed);
srand(seed);
magic = rand() % 100 + 0;
printf("num_3: seed = %d , 0~100——%d\n", seed, magic);
//通过时间来控制输出随机数
srand(time(NULL));
magic = rand() % 100 + 0;
printf("num_4: time control 0~100——%d\n", magic);
return 1;
}
2. 浮点数存储的具体数值
1、凡是可以直接转换为int型的float型而不丢失信息的数据,都是以整数存储。
但是存在小数的浮点数,存储的时候会发生误差。
2、如果想要判断两个浮点数是否相等,则应预定义一个很小的数,用是否在某个数为中心的区间内来判断两个数是否相等。
int FloatNumber(void)
{
double f1 = 0.1, f2 = 0.0, f3 = 0, f4 = 1.0;
printf("%.20f %.20f %.20f %.20f\n", f1,f2,f3,f4);
return 1;
}
输出为:
3. switch case 的语法:
switch(表达式)
{
case 值1:
表达式的值和值1匹配上了,需要执行的代码;
break;
case 值2:
表达式的值和值2匹配上了,需要执行的代码;
break;
case 值3:
表达式的值和值3匹配上了,需要执行的代码;
break;
default:
如果表达式的值和以上的case后面的值都没有匹配上,那么就执行这里的代码。
break;
}
break
的作用是阻值下面的case的继续运算,妙用break
可以事半功倍!
4. realloc的用法:
前提:需要有一个指针,如void* p;
p=(void*)malloc(sizeof(void*)*initial_size);
——对指针p申请sizeof(void*)*initial_size
大小空间;
在指针p的空间基础上,从指针p的开始位置申请大小为sizeof(void*)new_size
的空间
p=(void*)realloc(p,sizeof(void*)new_size);
当new_size=0
; realloc
的作用相当与free
当0<new_size<intial_size
时,realloc
将会将原来的数据域的部分数据删除,造成数据流失
当new_size=intial_size
时,没有变化
当new_size>initial_size
时,将会在原先的空间的基础上,多申请new_size-initial_size
的空间
注:malloc/calloc/realloc用法
5. 宏定义使用
宏即是在程序中无条件的用后面替换前面
示例1:交换两个数
#include<stdio.h>
#define change(a,b) t=a;a=b;b=t;
int main()
{
int a,b,t;
scanf("%d%d", &a,&b);
change(a,b);
printf("%d %d", a,b);
return 0;
}
change(a,b)
后面的“;”可加可不加,因为宏定义的替换语句中,最后加上了“;”,如果宏定义中有加上分号,则在主函数中必须加上“;”。
注意:因为宏定义是无条件替换,所以在进行运算或者编译检查的过程中,要进行替代,检查出其中可能存在的错误,避免造成不必要的错误。
示例2:在三个实数中求出最大的那个数
#include<stdio.h>
#define Max(a,b,c) (a>b?a:b<c?c:a>b?a:b)
int main()
{
float a,b,c;
scanf("%f%f%f", &a,&b,&c);
printf("%.3f\n", Max(a,b,c));
return 0;
}
上述代码并没有编译报错。
编译报错的错误代码是:#define Max(a,b,c) (a>b?a:a=b>c?a:c)
报错的地方是赋值的那一句,报错原因为lvalue required as left operand of assignment,即左操作数需要赋值
但是我不知道到底是什么原因编译器报错,暂且就这么理解:宏定义不能将两个参数进行赋值
6. 快速排序 Quick Sort
快速排序的用法:
头文件:stdlib.h
函数:void qsort(void *base, size_t nitems, size_t size, int (*compare)(const void *, const void*))
base-- 指向要排序的数组的第一个元素的指针。
nitems-- 由 base 指向的数组中元素的个数。
size-- 数组中每个元素的大小,以字节为单位。
compare-- 用来比较两个元素的函数,即函数指针(回调函数)
对于函数compare
的两种排序方式:递增,递减(非)
//from small to large
int compare(const void* a,const void* b)
{
return *(int *)a-*(int *)b;
}
//from large to small
int compare(const void* a,const void* b)
{
return *(int *)b-*(int *)a;
}
//application
qsort(array_base, n, sizeof(array_base), compare);
array_base-->array
sizeof(array_base)-->the size of array array_base
7. scanf
返回值
读取成功任何一个元素,返回值从零自增一。
全部读取失败:返回值为-1;
文件结束:返回值为-1;
8. 去除数组中相同的元素
1、使用冒泡排序法,将相同的元素用最后一个元素覆盖,位置不变,元素数量减一。
#include <stdio.h>
int main()
{
int i,j,t,a[N];
for(i=0;i<k;i++){
for(j=0;j<N-i-1;j++){
if(a[j]>a[j+1]){
t=a[j];
a[j]=a[j+1];
a[j+1]=t;
j--;
}
if(a[j]==a[j+1]){
a[j+1]=a[N-1];
j--;
N--;
}
}
}
}
9. scanf
对字符串的读取
1、对字符串读取的时候,%s
和%d
类似,读取缓冲区的内容,如果遇到空格或者换行符,跳过继续读取,直到非空格或着换行符才存取,直到空格或者换行符结束。
2、对%c
来说,非常特殊,' '
(space)和\n
(回车)都是字符,所以在读取的时候,会将缓冲区中之前或者当前的空格或回车读取。
3、如果想要使用%s
和%c
读取除了回车或者空格外的字符,则应在%c
前面加上。
如scanf(" %c", &c);
#include<stdio.h>
#include<string.h>
/**测试scanf对字符串读取后缓冲区的情况**/
int main()
{
char s[10],c;
//scanf("%s%c", s,&c);
//scanf(" %s%c", s,&c);
scanf(" %s %c", s,&c);
printf("s=%s c=:%c:", s,c);
return 0;
}
/*****测试结果*****
scanf格式:scanf("%s%c", s,&c);
样例一:
读取:123 4
输出:s=123 c=: :
样例二:
读取: 123 4
输出:s=123 c=: :
scanf格式:scanf(" %s%c", s,&c);
样例一:
读取:123 4
输出:s=123 c=: :
样例二:
读取: 123 4
输出:s=123 c=: :
scanf格式:scanf("%s %c", s,&c);
样例一:
读取:123 4
输出:s=123 c=:4:
样例二:
读取: 123 4
输出:s=123 c=:4:
********************/
10、字符串
string.h中相关的函数
一个变量类型
size_t
:无符号整型(unsigned int
),是sizeof
操作符返回的结果类型,在64位系统中为long unsigned int
。
一个宏
NULL
:空指针常量的值
以str开头的函数
☆size_t strlen(const char *str)
计算字符串str的长度,直到空结束字符",不包括空结束字符。
☆char*strcpy(char *dest,const char *src)
把src所指向的字符串复制到 dest。
☆char*strncpy(char *dest,const char *src,size_t n)
同上,把src所指向的字符串的前n个字符复制到dest。
☆char*strcat(char *dest,const char*src)
把src所指向的字符串追加到dest所指向的字符串的结尾,实现字符串的连接。
☆char*strncat(char*dest,const char*src,size_t n)
同上,把src所指字符串的前n个字符添加到dest所指字符串的结尾处,并覆盖dest所指字符串结尾的",实现字符串的连接。
☆char*strchr(const char*str,int c)
在参数str所指向的字符串中搜索第一次出现字符C(无符号字符)的位置,如果5tr中没有c,则返回NULL。
char*strrchr(const char *str,int c)
在参数str所指向的字符串中搜索最后一次出现字符C(无符号字符)的位置,如果str中没有c,则返回NULL。
☆int strcmp(const char *str1,const char *str2)
把str1所指向的字符串和str2所指向的字符串进行比较,当str1<str2时,返回一个负数;当str1==str2时,返回零;当str1>str2时,返回一个正数。
☆int strncmp(const char *str1,const char *str2,size_t n)
同上,把str1所指字符串的前n个字符和str2进行比较。
以mem开头的函数
void*memcpy(void*dest,const void*src,size_t n)
从src复制n个字符到dest。
int memcmp(const void *str1,const void *str2,size_t n)
把str1和str2的前n个字节进行比较,其返回值与strcmp相同。
void*memset(void *str,int c,size_t n)
复制字符c(无符号字符)到参数str所指向的字符串的前n个字符。
void*memchr(const void *str,int c,size_t n)
在参数str所指向的字符串的前n个字节中搜索第一次出现字符C(无符号字符)的位置。
11、 转化为二进制(含负数补码)
转化为32为二进制(负数补码)
void Binary(int n,int a[])
{
int i=0, j, t=n, flag=1;
if(n<0) n*=-1;
while( n ){
a[++i] = n%2;
n/=2;
}//读入数组
//对负数进行补码处理
if(t<0){
for(i=1;i<=31;i++)
a[i]=a[i]? 0:1;//取反
a[32]=1;
a[1]+=1;
for(i=1;i<33;i++)
if(a[i]>1){
a[i]-=1;
a[i+1]+=1;
}
}
}