一、指针的指针的使用
//指针的赋值初始化
1)char *str[3]={"good","thing”,"have"};
(2) char **p,*str[6],str1[6][max];
for (i=0;i<5;i++)
{
str[i]=str1[i];
}
//这是赋值的常用的两种方式
指针的指针的输入(一定要先开辟内存)
char *s[55];
for (i=0;i<55;i++)
{
s[i]=(char *)malloc(sizeof (char)*6);//开辟内存
}
for (i=0;i<55;i++)
{
scanf(“%s”,s[i]);
}
二、如何想要把你想要的文字对齐
一个汉字/中文输入法的所有字符除数字之外,一个汉字或字符占两个字节。而英文输入法中的英文一个字母或字符占一个字节。‘孔’在英文状态下可以顶替两个字符‘ko‘。所以掌握这两个知识,想要的对齐效果自行设计
三、c语言取模
取模就是取余数,m模n (c语言表示 m%n ) 就是取用m除以n得到的余数。
四、时间的计算
如 通过692s来计算几时几分几秒
(以秒为单位)如time=546s;
1. hour=time/3600 被计算出了小时数据
2. min=time%3600/60 被计算得到的分钟
3. sec=time%60 被计算得到的秒数
(1)对2的解释以546s为例,546%3600,得到的是除了小时以外所剩下的秒数,所剩下的秒数在除于60,就是所得到该时间经过小时后余下的分钟数
(2)对3进行解释,546%60,得到的是经过小时和分钟的计算后余下的秒数
经过1、2、3就得到了692s可以表示的几时几分几秒;
五、c语言整数的四舍五入计算
int a; float c1, c2;
a = (c1 - c2 + 0.5)
a得到的值就是经四舍五入变换后得到精确值
如c1=2.3,c2=4.0;c2-c1=1.7
因为a为整数
要直接让a=c1-c2; 得到的值就是1,但是a=(c2-c1+0.5)=2,从而队整数达到四舍五入的效果。
但是对于 double 或 float 型变量 只保留整数,就相当于四舍五入。这是c语言的内在规定。
六、整数的输出格式
printf(“%02d”,hour); 其中,02表达的意思是,如果输出的整形不足两位,左侧就用0补齐,够两位,就不用补。同理%03d表达的就是够三位就不用补,不够三位的就用0补齐
七、输入行数的四舍五入
输出的行数实际上是列数的 50%(四舍五入取整)。
int t =N/2 + N%2;(N是列数),t表示行数(行数是列数的50%,且还得四舍五入取整,)。
1. N如果是偶数的话,t 行数就是列数N的一半,
2. N 如果是奇数的话,t 行数需要四舍五入处理,首先N/2,让输入的行数减少0.5,但是后面的N%2 的操作就让补上了那失去的0.5,让0.5变成1,从而达到四舍五入的效果
八、long long 的有效位数
他是 long long int 的缩写,int 和 long int 的有效位数是10位, long long / long long int 是19位
九、参数传递时常见的错误
int c (int a,long b);
int c ( int a, long long int b)
{
}
主函数在调用c函数时,参数的类型必须要一致,且在主函数定义相应的实参变量时,也一定要类型一致,如,在主函数定义b变量时,要这样定义 long b;而不是 long int b;虽然long 时long int 的缩写,但是,类型确是不一样的。(这样的后果是,把定义的函数c 变成了没有实际作用,发挥不了功能的函数,编译器也不会报错)
十、c语言小数输出时的四舍五入
c语言中,小数的输出会自动的四舍五入
比如 1.2345
1. 如果是%.2f 那么是1.23
2. 如果是%.3f 就是1.235了
3. 有些平台不是简单的四舍五入 而是用的四舍六入五成双(更精确的保留数据)
十一、对于scanf的深入理解
1. scanf("%c-%c",&A,&B);%c于%c之间,是什么就会被输出什么,如果是逗号,就用逗号隔开,空格就用空格隔开,且最后的%c后面也可以有空格,只不过在输入数据的时候,也要相应的输入空格
2. scanf("\n") == getchar();//这两个表示一样的意思
什么时候读取数据用到scanf(“\n”) / getchar()
在只读取 1 2 3 4
2 3 4 5 像这样的只有数字的时候,每一行循环不用读入getchar();后面的是读取数据,不是读取字符,所以不会读取“\n“,
但是像这样的数据(2 a c) (2 b d) (2 a c) (3 a b e)
(2 a c) (2 b d) (2 a c) (3 a b e)
在每一行循环,scanf 函数读取的是字符,‘(’,所以胡读取到换行符,从而导致出错。所以要加上scanf(“\n”) / getchar(); 才不会出错。
但是有时候scanf("\n");也会出错,最好用 getchar();保险
十二、c/c++常变量作为数组的长度
const int max = 100010 ;
struct preson
{
int ans;
char name [15] ;
}p[max];
在C++中可用const修饰的变量作为数组的长度。但是c语言中不可以那么做,这样在c语言中是不允许的
十三、布尔型变量的常见操作
1、布尔型变量作为函数返回值
bool型变量的值只有 真 (true) 和假 (false)。bool可用于定义函数类型为布尔型,函数里可以有 return true; return false 之类的语句。就算返回值不是true,false 返回的是一条语句,那也是将那一条语句当成0/1来输出
2、布尔型变量作为运算条件返回值
bool b =2; //执行此行后,b=true(整型2转为bool型后结果为true)
if(b)
cout << "ok!" << endl;
b = b-1; //执行此行后,b=false(bool型数据true参与算术运算时会转为int值1,减1后结果为0,赋值给b时会转换为bool值false)
if(b)
cout << "error!" <<endl;
十四、利用Ascall码值让字符数字变成整数数字
如c = ‘2‘,要想让c变成整数2 就得让
c = c – ’0‘;这样所得的c就是整数2(利用ascall值的原理)。
1. 同理也可以用字母相减,c = ‘b’; c = c – ‘a’; 此时在ascall的角度讲,c是1,代表数字1,用处可大了
2. char a[27]; a数组用来储存26的英文字母,的个数,0代表a, 25代表z ,这样当前字符减‘a’,加转化成对应的数值,也可以通过特定的下标输出某个字符
C= 2, c= ‘a’+ c; 此时在字符的角度讲c此时为‘c’
十五、if语句的美观误区
//错误的if使用方式
if ( amax < awin[i]) amax = awin[i]; A = i;
错误原因:if语句后面有语句,封号就表示if语句结束了,A= i执行不了
if ( amax < awin[i]) amax = awin[i], A = i;
错误原因:逗号就是还得执行if 里所有的语句
正确的引用方式
if (amax < awin[i])
{
Amax = awin[i];
A = i;
}
if (amax < awin) {amax = awin[i] , A = i};
十六、c++中cout,cin的局限性
在c++中,cin, cout 的输入输出的速度比较慢,所以会造成运行超时的结果,(在某些特定的时候,不全是),但是scanf和printf的输入输出,却比cin,cout快很多(大约10~100倍左右)。所以在用c++输入输出的时候,数据超过10^6就都乖乖的用scanf和printf函数就好。避免运行超时
但是也有优点
方便好用;
关于cin不用getchar()来匹配换行符
十七、交错求和思想
交错求和,即计算 *n*1−*n*2+*n*3−*n*4⋯;利用(-1)的n次方* (n)的个数据之和
十八、getline / get
pat现在不允许使用gets()函数,所以要用 getline ()
对于c++ 而言 getlne (cin , a); (对于string容器而言)
对于c++普通字符串而言 cin.getline (a, 100); //表示只能输入100各字符
gets(a + 1);//表示从下标1开始读入,这样字符串时从a[1]开始存入字符的这样的有效长度是 lena = strlen(a + 1),读入是从下标1开始,因此读取长度也是从+1开始
十九、string容器注意事项
1、只输入一个字符时,并引用
string a;
get(a); //此时输入 ‘#’
if (a == '#') //像这样的判断条件是错误的,因为a时祖父串,只能这样用
if (a == "#");
//或者这样用
if (a[0] == '#')
2、函数c_str()
string a = "19293";
scanf("%s",a.c_str());如果不这样使用的话,时输出不了字符串a的
3、关于 append()函数的使用
1,向string 后面加字符串
string s = “hello “; const char *c = “out here “;
s.append(c); // 把c类型字符串s连接到当前字符串结尾
s = “hello out here”;
2、向string后面加字符串的一部分
string s=”hello “;const char *c = “out here “;
s.append(c,3); // 把c类型字符串的前n个字符,连接到当前字符串s的结尾中
s = “hello out”;
3、向string后面加入多个字符
string s1 = “hello “;
s1.append(4,’!’); //在当前字符串结尾添加4个字符!
s1 = “hello !!!!”;
4、stoll函数的使用
就是字符串转为long long类型
5、string字符串赋空语句
string num = “”;
6、string的构造函数的形式
string str:生成空字符串
string s(str):生成字符串为str的复制品(s就等于字符串str)
string s(str, strbegin,strlen):将字符串str中从下标strbegin开始、长度为strlen的部分作为字符串s初值
string s(cstr, char_len):字符串s等于字符串cstr的前char_len长度的字符
string s(num ,c):生成num个c字符 的 字符串
string s(str, stridx):将字符串str中 从下标stridx开始 到 字符串结束 的位置 作为字符串初值
//eg:
string str1; //生成空字符串
string str2("123456789"); //生成"1234456789"的复制品
string str3("12345", 0, 3);//结果为"123"
string str4("0123456", 5); //结果为"01234"
string str5(5, '1'); //结果为"11111"
string str6(str2, 2); //结果为"3456789"
7、c++中to_string(int val);的用法
功能:将数值转化为字符串并返回对应的字符串
8、c++中substr的使用(截取字符串)
substr有2种用法:
假设:string s = "0123456789";
string sub1 = s.substr(5); //只有一个数字5表示从下标为5开始一直到结尾:sub1 = "56789"
string sub2 = s.substr(5, 3);//从下标为5开始截取长度为3位:sub2 = "567"
9、用string函数的find函数来判断一段字符是否独立
判断字母独立的方法:当用find函数找到该位置时,如果该字符串的初始位置是0,就是开头,或者在字符串的开头不是字符(除了字母和数字以外,标点符号就表示该字母独立)并且,在该字符串结尾的地方,不是让该字符串结尾的位置是等于整个字符串的长度,就是让让该字符串结尾的地方不是字母或数字(要外之意就是,标点符号,或者是空格)
for (int beg = 0; ; beg++)
{
beg = s.find("could you",beg);
if (beg == -1) break;
if (!beg || !isalnum(s[beg - 1]) && (beg + 9) == s.size() || !isalnum(s[beg+ 9]))
{
s.replace(beg,9,"A could")
}
}
1. 对于同一个字符来说,有些字符能改,有些字符不能改,我们的做法是,能该的字换成一个比较抽象的字符,该后在对这个抽象的字符进行改动。
2. s.find(“字符串”,位置);表示从该位置处,去寻找满足条件的子串,并返回该字符的第一个位置。
3. 如果找不到的话就是等于 string::nops , 他的整型变量的值是 -1,当数值等于-1时,意味着,没有找到该字符串要找的字串。
4. 用一个for没有循环条件的for循环,让每次的beg的值加一的原因是,从找到该字符字串的下一个位置,开始算起,在去寻找新的字符字串。
10、string 类型结构体用printf输出错误
错误例子
printf("%s %d %d %d %d\n", ans[i].num, ans[i].gp, ans[i].gm, ans[i].gf, ans[i].g);
正确例子
printf("%s %d %d %d %d\n", ans[i].num.c_str(), ans[i].gp, ans[i].gm, ans[i].gf, ans[i].g);
11、关于c++处理字符串string.find()与string::npos
查找字符串a是否包含子串b用的是,
strA.find(strB) != string::npos表示能在a中发现b,并返回其位置,
strA.find("chi1 huo3 guo1") != string::npos;//在字符串strA中可以发现字串“chi1 huo3 guo1”,并返回其中的位置。
题中要是提到,找某字串,就用此函数,非常好用
12、replace()函数
1、s.replace(index,7,"iqls"); //将s字符串下标为index的地方,去七个字符,换成字符串“iqls”
二十、1的二进制
00000001
因为 1 / 2 = 1就看成上面的,且没有余数
二十一、(n & 1 )是什么意思
因为在 1 的二进制时 00000001 , 又是 按位与 运算 ,所以只关心 随后一位数字就可以了
当n为 奇数时, n的二进制最后一位是 1, 当 n 为偶数是, n 的二进制最后一位 是 0 ;
所以可以判断 n 的积偶性
(n & 1) 等效于 (n % 2 == 0)
二十二、左移/右移的好处
int x = 200;
x>>1; //相当于 x /= 2
x<<1; //相当于 x *= 2, 等效于2^n;
x>>2; // x /= 4
x<<2; // x *= 4
x>>3; // x /= 8
x<<3; // x *= 8
以他为例
int i = 1;
i = i << 2;
//把i里的值左移2位,1的2进制是000...0001,左移2位之后变成 000...0100,也就是10进制的4,所以说左移1位相当于乘以2,那么左移n位就是乘以2的n次方了
//好处:在C中,左移是逻辑/算术左移(两者完全相同),右移是算术右移,会保持符号位不变.实际应用中可以根据情况用左/右移做快速的乘/除运算,这样会比循环效率高很多.
二十三、c++关于引用(&)
void insert (int & Root, int a)
int main ()
{
int root = 0;
insert (root, 1);
return 0;
}
关于引用的解释:对于在main函数里面,把root,的值传给了Root, 但是又有 &,的符号,所以,该变Root,就相当于改变了,root,的值,
但是在c语言里面,必须通过指针才能达到这样的效果
void insert (int * Root, int a)
如果要是传入的数据本身就是一个指针的话,要想达到这样的效果,必须用二级指针例如
//c++中是这样的
void insert (int* & Root, int a)
int main ()
{
int * root = 0;
insert (root, 1);
return 0;
}
//在c语言中是这样的
void insert (int ** Root, int a)
int main ()
{
int * root = 0;
insert (root, 1);
return 0;
}
二十四、输入/输出数据(01)的处理方式
对于数组,要输出两位数,在输出 01 这种数据,要通过,a[0] * 10 + a[1]来达到输入这挨着的两位数的效果
同时也对 01 做了处理,相当于输入了 1
二十五、关于如何把字符串反序存储
int x = 1234;
int num[100];
while (x > 0)
{
num[++ sum] = x % 10; //存储,个位数,4, 3, 2, 1
x /= 10; //分别让其变成123, 12, 1, 0
}
//这是反序存储,也可以变成正序
int j = 0;
for (int i = sum, i > 0; i--)
{
b[++j] = num[i];
}
二十六、把数组开在函数里面的弊端
int main()
{
int n, m,x;
scanf("%d %d", &n, &m); //学生个数,询问次数
int a[2000010];
for (int i = 1; i <= n; i++)
{
scanf("%d", &a[i]);
}
return 0;
}
以上的程序,是会报错的,因为在主函数里面数组能开的范围是 1乘以10的3~4次方而已,超过10的4次方,最好在全局变量处设值,否则会报错
二十七、关于map函数的使用误区
如果用map函数,来当数组使用,且,这个隐形的数组,数据范围不能太大,只能是1e3左右,太大的话,在自己的程序中不会超时,但是在网络编译器,中会超时的,最好还是是使用数组,
map的时间主要花费在自动排序中了。所以尽量数据大的情况下,不要使用它。
二十八、关于memcpy函数的使用
//头文件 #include <string.h>
const int N = 19;
int num[N], cpy[N];
memcpy(num, cpy, sizeof (cpy)); //将memcpy中的cpy数据复制给 num数组
二十九、关于int num[] []的使用&& 二维map的使用
关于二维数组,不能这样开
const int maxn = 100010;
int num[maxn][maxn] ;
对于这样用二维数组maxn的最大值,也就是 1e4, 当maxn= 1e 5,就会报错。
此时适合用二位map来作
//二维map容器的用法
map<int, map>num;
num[count1][count2] = k;这样就不会报错了
map < int, map<int, int> > num;
只是它的定义方式,
用途,可以用来,存出第i个柜子,第j个格子的物品是什么,这类似的问题。
三十、对于用数组对学生的学号和分数排名(主:分数,次:学号)
int num[maxn], score[maxn], index[maxn]; //学号,分数,下标,
bool cmp (int a, int b)
{
if (score[a] != score[b]) return score[a] > score[b] ;
else return num[a] < num[b] ;
}
int main()
{
for(i=1;i<=n;i++)cin>>num[index[i]=i]>>s[i];输入编号和成绩,同时初始化下标
sort(sub+1,sub+n+1,cmp);对下标排序 //注意,美国人喜欢区间 左闭右开,这一点要注意。
}
//通过这种方式,(通过对下标的排序,从而实现对分数的排序,和学好的排序)
注意的问题:既然要用下标排序,那么不管对分数 还是对学号,这些数组里的一系列操作,都因该用下标index来在它们的数组里面表示。,
三十一、c++中resize()和rerserve()函数用法
resize(),设置大小;
reserve(),设置容量;
resize()是分配容器的内存大小,而reserve()只是设置容器容量大小,但并没有真正分配内存。
resize()可以传递两个参数,分别是大小和初始值,初始值默认为0,reserve()只能传递一个参数,不能设置初始值,其初始值为系统随机生成。
vector<int>m;
vector<int>n;
vector<int>s;
m.resize(10);
n.reserve(10);
s.resize(10, 6);
m: 0 0 0 0 0 0 0 0 0 0
n: 12999640 12979904 0 0 0 0 0 0 0 0
s: 6 6 6 6 6 6 6 6 6 6
三十二、c++中for (auto count : counts )的使用
#include<iostream>
#include<vector>
using namespace std;
int main() {
int a[] = { 1,2,3,5,2,0 };
vector<int>counts(a,a+6);
for (auto count : counts)
cout<< count<< " ";
cout << endl;
return 0;
}
//运行效果是 1 2 3 5 2 0
//意思是将 counts 容器中的每一个元素从前往后枚举出来,并用 count 来表示,
//如果在 count 之前加入 &符号,表示,count 容器的数值可改。
三十三、pow()函数丢精度的问题
pow函数存在严重的精度缺失问题
像 int x = pow(n, 1 / m) 这样是不行的,1 / m, 得到是整数,会自动向下取整,然后又通过,~n~1/m 就会造成精度再一次丢失,解决办法是,将m 强制类型转化为 浮点型,从而增加精度。
int x = pow(n, 1/ (double)(m) :首先m变成浮点型变量,会增加精度
在经历用 pow()函数时,一定要把 带分式的内容,全部强制转化为浮点型,在作运算,否则会出错的。
那么关于单个整形的变量,不用 转化为浮点型变量。
三十四、当定义全局变量,在函数中说没定义时
比如定义 hash [] [] ,这样是肯定不行的,因为系统存在这样的函数,你需要把它换成别的,或者时加下划线
类似的还有 index
三十五、fill()函数的使用
1. 作用 给数组初始化任意值
2. 一位数组初始化 fill (a , a + maxn, number);
3. 二维数组初始化 fill (a[0], a[0] + maxn *maxn , number);
4. 头文件 #include <algorighm>
三十六、node里面套了一个node,原因
struct node
{
int x, y;
node(int xx, int yy):x(xx),y(yy) {};
};
在函数中运用的方法
int main()
{
node next (3, 4);
return 0;
}
//此时,next 就相当于一个结构体,next.x = 3, next.y = 4;
//node next (,); 就是一个内置函数
上述做的目的是,
面比如说我创建一个queue <node> q;
然后入队的时候就可以直接q.push(node(a,b));
这样子就很方便
不需要再 node k;
k.x=a;k.y=b;q.push(k);
三十七、关于 unordered_set 函数的使用(哈希表)
1、无序集是一种容器,它以不特定的顺序存储惟一的元素,并允许根据元素的值快速检索单个元素。
2、在unordered_set中,元素的值同时是唯一标识它的键。键是不可变的,只可增删,不可修改
3、在内部,unordered_set中的元素没有按照任何特定的顺序排序,而是根据它们的散列值组织成桶,从而允许通过它们的值直接快速访问单个元素(平均时间复杂度为常数)。
4、unordered_set容器比set容器更快地通过它们的键访问单个元素,尽管它们在元素子集的范围迭代中通常效率较低。
5、容器中的迭代器至少是前向迭代器
以下是几种赋值的方式
#include <unordered_set> //头文件
int main()
{
string a = "1234665";
unordered_set<string> mp = {"1234", "345", "34"};
//方式二
unordered_set<string> mp(a.begin(), a.end());//此时就有a里面所有的字符串
return 0;
}
//a可以是包含多个字符串的变量
三十八、处理行末行首不含任何多余的空格
for (int i = 1; i <= N; i++ )
{
if (num[i] == Max)
{
if (flag) cout << " ";
cout << i;
flag = 1;
}
}
三十九、字符串 中 重复的字符必须被剔除
//原理:
int hash_1[127] = {0};
for (int i = 0; i < c.size(); i++ )
{
if (hash_1[c[i]] == 0)
{
cout << c[i];
hash_1[c[i]] = 1;
}
}
//英文单词:acall的值只有 0 ~ 127 之间。
//散列思想。
四十、解决题解不为1的方法
//如果解不唯一,则以甲的最大解为准进行判断;如果解不存在,则输出 No Solution。
解决的方式为,在从大到小排完序后,找到对应的值,就return 0;
for (int i = 99; i >= 10; i -- )
{
o = i;
p = (o % 10) * 10 + o / 10;
q = abs(o - p) * 1.0 / x;
if (p == q * y)
{
cout << o << " ";
judge (m, o);
cout << " ";
judge (m, p);
cout << " ";
judge (m, q);
return 0;
}
}
cout << "No Solution";
像这样,满足情况的,就弄完最大值后,就return0;
不满足情况,就 输出 No Solution.
四十一、结构体/类,成员变量不可以初始化
这会造成有些数据出错
只有static const声明的整型成员能在类内部初始化,并且初始化值必须是常量表达式。这些限制确保了初始化操作可以在编译时期进行
四十二、利用全排列函数去除先导0
int a[15] = {0, 1, 2, 3, 4, 7 ,4};
while (a[0] == 0)
{
next_permutation(a,a+ 7 );
} //就已经把所有的先导0的情况给 排除掉了,剩下的就直接用即可,下面的就是没有先导为0的全排列所有函数。
do
{
for (int i = 0; i < 7; i++ )
{
cout << a[i] << " ";
}
cout << endl;
} while (next_permutation(a,a + 7));
四十三、函数stoi()函数和atoi()函数
stoi函数默认要求输入的参数字符串是符合int范围的[-2147483648, 2147483647],否则会runtime error。
atoi函数则不做范围检查,若超过int范围,则显示-2147483648(溢出下界)或者2147483647(溢出上界)。
stoi头文件:<string>,c++函数
atoi头文件:<cstdlib>,c函数
atoi()的参数是 const char* ,因此对于一个字符串str我们必须调用 c_str()的方法把这个string转换成 const char*类型的,
而stoi()的参数是const string*,不需要转化为 const char*
但是在c++中string 运用 atoi()函数时的转换
string a; atoi(a.c_str());即可。
四十四、c语言多行打字法
printf(
" ********\n"
" ************\n"
" ####....#.\n");
四十五、分数的误差问题
一定要 对分式加上小数点。否则会让精度有误差
四十六、关于输入0的异常操作
函数的某些定义域不能为0
当除数 ans / count ; 当count = 0 时,也就是分母为0时,就会出现输出异常,包括在中段输入的时候,就会出现不能正常往下进行。
像不能0的函数,结果却,而所进行的结果确实0,就会造成输入异常像lnx,当x = 0,时就会发生异常
四十七、超时问题
当输入的数超过了定义变量的本身的时候
当用cin函数的时候
当算法太过复杂化的时候
当给出的数据是,2^31时候,
我在用
bool isprime(int a)
{
if (a == 1) return false;
for (int i = 2; i * i <= a; i++)
{
if (i % 2 == 0) return false;
}
return true;
}
这样就会造成超时问题,因为
i * i 会爆掉
所以养成的编程习惯是
bool isprime (int a)
{
int b = sqrt(a);
if (a == 1) return false;
for (int i = 2; i < b; i++)
{
if (a % i == 0) return false;
}
return true;
}
四十八、#include <process.h>
单进程,单线程,必须干完一件事情后干另一件事情,f防止多个窗口同时弹出
四十九、c++中vector用法(深度)
1. vector<int>a(5); 定义了5个整形元素的向量,没给出处置,其这五个元素的处置不确定
2. vector<int>a(5, 1);定义了5个整形向量的元素,其初值为1。
3. vector<int> a(b); //用b向量来创建a向量,整体复制性赋值
4. vector<int> a(b.begin(),b.begin+3); //定义了a值为b中第0个到第2个(共3个)元素
5. int b[7]={1,2,3,4,5,9,8};
vector<int> a(b,b+7); //从数组中获得初值
6. vector< vector<int> > v(m, vector<int>(n) );,定义容量问题。
定义了一个二位数组,这个二维数组是这样的,有m个一位数组,且这个一位数组的容量为n,最终表达式是
v[m][n]
五十、equal函数的用法
equal()算法比较简单,它的作用是比较两个容器是否相等然后返回布尔值
vector<int> a{ 1,2,3 }, b{ 1,2,3,4 };
cout << "以a为比较范围,判断a,b是否相同:" << equal(a.begin(),a.end(),b.begin()) << endl;
cout << "要求容器相同,判断a,b是否相同:" << equal(a.begin(), a.end(), b.begin(), b.end()) << endl;
//也可以这样
int a[n],b[m];
equal(a,a + n, b); //以数组a为范围,来判断数组a和数组b是否相同
五十一、关于递归+初始化超时问题
当我的递归层数比较少,还有数组在初始化的时候,会出现超市的问题,因为在初始化的过程中,也会消耗时间,关于初始化费时间的比对 没出始化数组 < memset初始化数组 < 定以初始化数组
memset会在初始化数组时,优化,会比用定义初始化的方式费时间少,但是没初始化最不费时间。
当你的递归层数比较少,而且还初始化数组,就会造成超时问题,最好,不初始化为好。
五十二、nth_element函数
主要是用来,将数组元素中第k小的整数排出来并在数组中就位,随时调用,可谓十分实用
格式:nth_element(数组名,数组名+第k小元素,数组名+元素个数)
五十三、STL容器在插入到时候注意事项
vector<int> c;
for(int i = 0; i < 5; i++)
{
c[i] = i;
}
//以上是错误的案例,因为想这样的插入,必须定义c的容器大小,否则会直接报错,告诉你非法访问内存
//改正方式 一、
vector<int> c(100);
for(int i = 0; i < 5; i++)
{
c[i] = i;
}
//改正方式 二、
vector<int> c;
for(int i = 0; i < 5; i++)
{
c.push_back(i);
}
五十四、0x7fffffff表示
可以算一下 0x7FFFFFFF 是多少
每个十六进制数4bit,因此8位16进制是4个字节,刚好是一个int整型
F的二进制码为 1111
7的二进制码为 0111
这样一来,整个整数 0x7FFFFFFF 的二进制表示就是除了首位是 0,其余都是1
就是说,这是最大的整型数 int(因为第一位是符号位,0 表示他是正数)但是当两个数相加是会超int范围,所以最好用
0x3fffffff;
五十五、优先队列
priority_queue<int>q;
//优先队列,实质是大顶堆或小顶堆,这样可以无论输入什么值,出去的都是所有元素的最大值或最小值
一般情况下是大顶堆,
priority_queue<int>q;
也可以设置调整;
priority_queue<int,vector<int>,less<int> >q;
//这里多了两个参数,vector<int>用来承载数据结构的堆的容器,而less<int>是表示数字越大优先级越大,即大顶堆
priority_queue<int,vector<int>,greater<int> >q;
//数字越小优先级越大
注意点,less<int> >q;两个括号之间要有空格
此时再点出第一个数据时,不是使用q.front();而是使用q.top();
五十六、vector的数组直接赋值
vector<int> path,tempPath;
当给temppath一定的数值后,可以直接把数据给到path,而不用for循环挨个元素赋值
path = tempPath;即可。
//vevtor容器中的数组名是可以直接通过数组名看判断两个数组中的数据是否相等的
五十七、while黑盒子误区
while (scanf("%s %s",a + 1, b + 1) )//这样不会超出内存限制,不断输出没有结束点
因此只能这样
while (scanf("%s %s",a + 1, b + 1) != EOF)
while (~scanf("%d%d",&n,&m))等效于 while (scanf("%d%d",&n,&m)!=EOF)
~是按位取反
scanf的返回值是输入值的个数
如果没有输入值就是返回-1
-1按位取反结果是0
while(~scanf("%d", &n))就是当没有输入的时候退出循环
五十八、新函数
- 判断首字符,是数字字符还是字母字符函数
一、判断字符是字母字符,还是数字字符的函数
头文件<ctype.h>
(1)判断是字母字符:isalpha(a) a必须是字符,如下面的实例;
1、函数:isalpha
2、头文件:# include <ctype.h>
3、参数: 单个字符
4、返回值: false 和ture(相应的返回这个值都是做判断的)
5、 作用:判断是否字母字符
6、实例:
char str[] = "C++ Java C#";
if (isalpha(str[i])) {
printf("%c is alphabetic\n", str[i]);
}
7、试用语言:c/c++
isalpha(c)用来检查c是否为字母,如果是字母,则返回1;否则返回0
(2)判断是数字字符:isgidit(a)函数a必须是单个字符
1、函数:isgidit
2、头文件:# include <ctype.h>
3、参数: 单个字符
4、返回值: false 和ture(相应的返回这个值都是做判断的)
5、 作用:判断是否数字字符
6、实例:
char str[50] = { "123456789" };
while(str[i]++){
if (isdigit(str[i])) {
n++;
}
}
7、试用语言:c/c++
isdigit(c)用来检查c是否为数字(0~9),如果是数字,则返回1;否则返回0。
- 将字符转换成大小写函数
toupper(c)用来将c字符转换为大写字母,返回c对应的大写字母。
tolower(c)用来将c字符转换为小写字母,返回c对应的小写字母。
他们的头文件都是 #include <ctype.h>
- 将字符串里的数据转换成整形里的数据
(且数据的值都一样如:字符串型数据"123"就被转换成整形数据123)
1、函数 atoi
2、返回值 int型数值
3、参数 字符串
4、适用语言 C/C++
5、头文件 #include <stdlib.h>
6、作用:将字符串里的数据转换成整形里的数据
7、实例 char *str = "12345.67";
n = atoi(str);
printf("n=%d\n",n);
n=12345
在c++中 string a;用的话,一定要用c_str()函数转换
如:atoi(a.c_str());
- 判断输入的字符是否为字母/数字(两者皆可判断)
1.头文件:#include<ctype.h>
2.返回值:如果 c 是一个数字或一个字母,则该函数返回非零值,否则返回 0。
3、参数:c—这里是要检查的字符。
4.声明:int isalnum(int c);
- 将数据做运算并转换成字符串函数
1、函数: sprintf函数
2、头文件:# include < stdio.h>
3、参数: int sprintf(char *str, const char *format, ...)
①str -- 这是指向一个字符数组的指针,该数组存储了 C 字符串。
②format -- 这是字符串,包含了要被写入到字符串 str 的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化。format 标签属性是 %d/%f/%c/%s/……等等,看后面附加参数了
③附加参数 -- 根据不同的 format 字符串,函数可能需要一系列的附加参数,每个参数包含了一个要被插入的值,替换了 format 参数中指定的每个 % 标签。参数的个数应与 % 标签的个数相同。就本题而言,相当于c,d,(c+d)
如果format是%d的格式,那么在附加参数的变量就是对应的类型变量int 型的
4、返回值: 返回值
如果成功,则返回写入的字符串,不包括字符串追加在字符串末尾的空字符。如果失败,则返回一个负数。
5、实例:char s[100];//s存储最终的字符串
sprintf(s,"%d+%d=%d",c,d,c+d);//将c+d=(c+d)转换成整%d +%d =%d的格式,在将其变成字符串储存到s里面
cout<<s<<endl<<strlen(s)<<endl;//输出字符串和字符串长度{如果c=3,d=4;那么s字符串里的就是“3+4=7”,其长度为5}
7、试用语言:c/c++
8、特别注意;sprintf/sscanf 函数中,以 int temp = 0;
Char a[50], b[50]; getline (cin, a);//假如,a[50] = “aa213”;
则;sscanf(a,”%lf”,&temp); sprintf(b,”%lf”,temp); 此时a[i] !=b[i];
虽然a字符数组的数据按找“%lf”的形式传给了temp,但是temp接受的是可以转化为实型数据的数据如(213),但是像字符型的数据(aa),就不可以被temp按找”%lf”的形式接受。所以综上,字符a数组是“aa213”,字符b数组是”123”;所以 b于a数组必定不一样。
sscanf() – 从一个字符串中读进到指定格式相符的数据
sprintf() – 字符串格式化命令,主要功能是把格式化的数据写入某个字符串中 。
- 读取数据到程序中的函数
freopen("in.txt", "r", stdin);
freopen("out.txt","w", stdout);
freopen("debug\\in.txt","r",stdin)的作用就是把标准输入流stdin重定向到debug\\in.txt文件中,
这样在用scanf或是用cin输入时便不会从标准输入流读取数据,而是从in.txt文件中获取输入。
只要把输入数据事先粘贴到in.txt,调试时就方便多了。
类似的,freopen("debug\\out.txt","w",stdout)的作用就是把stdout重定向到debug\\out.txt文件中,这样输出结果需要打开out.txt文件查看。
需要说明的是: 1. 在freopen("debug\\in.txt","r",stdin)中,将输入文件in.txt放在文件夹debug中,文件夹debug是在VC中建立工程文件时自动生成的调试文件夹。如果改成freopen("in.txt","r",stdin),则in.txt文件将放在所建立的工程文件夹下。
在dev c++ 中,文件最好与源文件放在同一个位置) 最好指定路径像 freopen ("E:\c语言习\in,txt" ,“r”,stdin); in.txt文件也可以放在其他的文件夹下,所在路径写正确即可。
2. 可以不使用输出重定向,仍然在控制台查看输出。
3. 程序调试成功后,提交到oj时不要忘记把与重定向有关的语句删除。(提交时要删除语句,否则译器是不会通过的。);
五十九、关于程序中XoY坐标轴的表示
关于在程序中的直角坐标系看的话,首先用正常的坐标弄出上下左右,然后看的时候,把x周弄到下面去,y轴弄平,这样看