-
为什么C++不像java需要jdk,而可以直接编译?
Java是运行在JVM中的,并且是编译成JVM可识别加载的.class,并不是完全编译成计算机直接可执行的程序,C++ 程序直接可在计算机中执行。
JDK除了提供基本的类库之外,还提供了编译java源文件成.class的工具。
C++在系统中运行时,也需要对应的运行库。 有一些没有封装在系统中,也需要C++运行库的支持,默认是没有安装在系统中的。 -
为什么浮点数不能直接计算?
先说结论:
在C++中不同精度浮点数直接比较大小精度是不一样的(比如float的0.1和double类型的0.1比较)
#include <iostream> #include <cmath> using namespace std; int main() { float a = (float)0.1; float b = (float)0.1; if(a == b) cout << "a == b" << endl; else cout << "a == b" << endl; float c = (float)0.1; double d = (double)0.1; if(c == d) cout << "c == d" << endl; else cout << "c != d" << endl; return 0; }
结果:
原因
按照博文计算机中基本类型float值表示和大小比较问题的说法:
即使在精度相同的情况下,比较也可能会出问题。因为在运算过程中会将内存(或高速缓存)中的值加载到CPU浮点寄存器(80 bit扩展精度)中,然后再进入CPU浮点计算单元进行计算,计算结果写回浮点寄存器,然后写回内存(或高速缓存)。从内存到浮点寄存器,浮点数的精度会扩展,从浮点寄存器到内存,浮点数的精度会降低(精度扩展通常没问题,但如果精度降低了,很可能值会发生变化,出现截断),而浮点运算的结果由于下面还要使用所以暂时保存在浮点寄存器中留待下次使用(没有及时写回内存,这是一种优化策略),从而导致数据并不是内存中和内存中的数据比较而是浮点寄存器中的值和内存中的值进行比较,而无论内存中是float类型还是double类型,其精度和浮点寄存器精度都不相同,从而导致比较结果是不相等。
解决方法:使用一个约定的精度比较
float e = (float)0.1; float f = (double)0.1; if(abs(e - f) < 0.0001) cout << "e == f" << endl; else cout << "e != f" << endl;
-
C++中fabs和abs函数的区别
abs和fabs,abs是对整数取绝对值,而fabs是对浮点数(double,float)取绝对值。
C++中有两个库可以调用abs函数,一个是cmath库,实测,abs(-3.4)就是3.4;一个是cstdlib库,abs(-3.4)会报错,只支持转换int类型值的绝对值. -
C++中struct写在主函数外面和里面有什么区别
作用域不一样(目前还没有进一步尝试)
-
for循环中的语句判断条件,i++和++i有什么区别?
在for循环的结果来看,两者是等价的。
但是从性能来看,++i好于i++。因为i++是先使用了该变量再加1,需要有一个临时变量转存;而++i则是直接+1,省去了对内存的操作,提升效率。 -
C++中string类型怎么切割成子字符串?
使用substr函数
string substr(pos,size)
string str = "abcd";
cout << str.substr(1,2);//从下标为1开始时,切割子串长度为2 bc
这个函数参数1是切割的起始下标位置,参数2是子字符串的长度(不写默认切到尾部),返回值是被切割的字符串。
7. C++中怎么查看变量类型?
出处
使用typeid(a).name() 注:需要引入 #include < typeinfo >
#include<iostream>
#include <typeinfo>
using namespace std;
int main(){
int a=0;
float b=1.0;
double c=2.3;
string d="haihong";
cout<<"a的类型是"<<typeid(a).name()<<endl;
cout<<"b的类型是"<<typeid(b).name()<<endl;
cout<<"c的类型是"<<typeid(c).name()<<endl;
cout<<"d的类型是"<<typeid(d).name()<<endl;
}
- C++中怎么判断两个string类型在变量字符上相同(而不是地址相同)?
string str1 = “123”;
string str2 = “1234”
if(str1 == str2)
就这么简单,因为内部重载了 == 操作符 调用了 strcmp函数比较两个字符串
- C++中string[i]是获取对应下标的字符类型
char类型,不是string类型。 - C++int类型怎么转换成string类型整数?
- 首先不可以像java中一样,直接int类型变量+""企图将int类型变量转换成string类型变量。
- 可以尝试to_string(int类型值) 将int类型转换成string类型
#include <string>
#include <iostream>
int a = 0;
string b = to_string(a);
cout << b <<endl;
if(b == "0"){
cout << "输出是0" ;
}
- 常见std库的数据结构使用API介绍
vector对象名称为vector,map对象名称为map,其他的数据结构以此类推。
– | 初始化 | 插入(增) | 查找 | 删除 | 遍历 | 转换 | 其他 | 排序 |
---|---|---|---|---|---|---|---|---|
vector (容器) | 1.vector< int> v1(100,9); 2.vector< int> v2; v2.resize(8); 3.vector< int> v3(8);v3[0]=1; 4.vector< int> v4 = {12,2,3,4} 注:vector会按照存入的顺序保存数据 | push_back()在末尾增添值 | 1.按照下标直接访问 vector[1] 访问vector的第二个元素 | 1.pop_back()删除vector对象的末尾元素(意味着此时v.size()也减一)2.v1.erase(v1.begin())删除起始(指定)位置的元素 | vecotr< int> vs; 遍历 for(int v :vs){ cout << v <<" " << endl ;} | vector转换成set vector< int> nums; unordered_set< int> nums_set = (nums.begin(),nums.end()); | 求长度:vector.size()能返回其对应长度 | #include<algorithm> vector<int> vec = {2,6,3,5,4,8,1,0,9,10}; sort(vec.begin(), vec.end()); |
set (容器) | set s; | s.insert(插入的值); | s.find(值) != s.end() | s.erase(需要删除元素的值); | for(auto it = s.begin();it != s.end();it++){ cout << *it << " ";} | set转化成为vector set< int> result_set; vector nums = (result_set.begin(),result_set.end()); | ||
map (容器) | map<string,int> m; 注:map会将存入键值对按照"键值",从小到大顺序保存数据(不是按照存入顺序保存数据) | 1. map[“键”] = 值; 2.map[“键”]++;值为数值类型,初始化时从0变成1 | 1.map[“键”] 通过下标去找(找不到返回值0) 2.map.find()找到返回iteration对象,找不到返回end() 所以 map.find(“键”) != map.end() 来判断map中是否存在该值 | 1.map.erase(“具体的键”)删除对应键的键值对 | 两种方式:1.for(auto it = m.begin() ;it != m.end(); it++){cout << it->first << " " << it -> second << endl;} , 2.for(auto n:mapNum){} | |||
string | string s; | 1.s.push_back(‘字符类型’); 2.s.append(“字符串类型”); 3.s = s + “字符串类型”;4.s = s + ‘字符类型’; | 1.通过下标获取对应字符类型的变量 s[下标] 2. 通过find函数找其中是否有对应的子串 s.if(find(“子串内容”) != string::npos) | 教程:C++中erase函数的三种用法 1.删除范围内的元素: s.erase(s.begin(),s.begin()+2); 这个是左闭右开,也就是删除第一个到第二个元素(删除到s.begin()+1这个元素为止,不删除s.begin()+2这个元素) 2.删除指定位置的值 s.erase(s.begin()+要删除的序号); (比如s.begin()是删除第一个,s.begin()+1 是删除第2个值) | for(auto it = s.begin();it != s.end();it++){cout << *it;} | 均是在#include< algorithm>头文件下的函数 1.反转字符串的内容 reverse(s.begin(),s.end());左闭右开,reverse实现的时间复杂度为O(n),2.sort(s.begin(),s.end()),左闭右开,函数时间复杂度为O(logn),具体思路见:C++ Sort函数详解 | ||
stack(容器适配器) | stack< int> st; | 1. st.push(插入元素) | 1.获取栈顶元素(元素弹出的方向) st.top(); (不能获取栈底元素) | 1.弹出栈顶元素(不能弹出队尾元素):st.pop(); | 不能遍历 | (特性:1.stack只能获取、弹出、加入栈顶的元素(st.top()获取队首元素(也就是队弹出元素的一端),s.pop()弹出栈顶元素,s.push()加入元素到栈顶); | ||
queue(容器适配器) | queue< int> q; | 1. q.push(插入元素) | 1.获取队首元素(元素弹出的方向) q.front(); 2.获取队尾元素 q.back(); | 1.弹出队首元素(不能弹出队尾元素):q.pop(); | 不能遍历 | (特性:1.queue可以获取队尾和队首的元素(que.front()获取队首元素(也就是队弹出元素的一端),q.back()获取队尾元素);但是只能对于队首一端的元素进行弹出操作(que.pop()弹出),队尾的一端加入元素(que.push()元素从队尾入队)) | ||
deque(容器,不是容器适配器) | deque< int> de; | 1. de.push_back(元素值); 在队尾插入元素) 2. de.push_front(元素值); 在队首插入元素) | 1.获取队首元素(元素弹出的方向) q.front(); 2.获取队尾元素 q.back(); | 1.弹出队首元素:de.pop_front(); 2.弹出队尾元素 de.pop_back() | 不能遍历 | (特性:deque不仅可以获取队首和队尾的元素(跟queue的API相同),而且可以对于队首队尾的元素进行弹出和加入操作(push_back()和pop_back()分别是在队尾加入和弹出元素操作,push_front()和pop_front()分别是在队首加入和弹出操作) | ||
priority_queue(容器适配器) | priority_queue< 数据类型,底层容器,函数对象(用来定义元素比较规则的)> pri_que; 举例: struct comparision{ bool operator() (const pair<int,int>&left,const pair<int,int>&right) {left > right};}; priority_queue<pair<int,int>,vector<pair<int,int>>,comparision>; | 1. de.push(元素值); 插入元素,并且插入后内部自动排序,排序时间复杂度为:O(logN),N是pri_que的元素长度 | 1.获取队首元素(元素弹出的方向) q.top(); 不能获取队尾元素,类似堆,只能获取堆顶元素 | 1.弹出队首元素:de.pop(); | 不能遍历 | (特性:1. priority_queue类似一个堆,只能访问其队首(也就是堆顶)元素,pri_que.top(); )2.头文件为#inlcude< queue> |