一、阅读陷阱题
1. 用基类指针或者引用去调用派生类对象,发生多态的前提是,函数一模一样
#include <iostream>
using namespace std;
class A{
public:
virtual void print(){
cout << "A::print()\n";
}
};
class B : public A{
public:
void print(int i = 0){
cout << "B::print()\n";
}
};
int main(){
A *ptr = nullptr;
B b;
ptr = &b;
ptr->print();
b.print();
b.print(1);
b.A::print();
return 0;
}
我们发现当用基类的指针ptr去调用虚函数print()时,并没有和预想的一样动态绑定到派生类的print()函数。那么这是为什么呢?
事实上,虚函数要求的是基类与派生类完全相同的两个函数,在上面这个例子中,编译器把print()与print(int i = 0)看作两个不相关的函数,也自然不会有所谓“多态性”了。
补充一句,就算你想在派生类的print(int i = 0)后加上override也是不可行的
2. 里面有纯虚函数 virtual void xxx() = 0 的叫抽象类,不能实例化
3. 模板函数一定要先声明 template< typename T>
以及成员函数前
template <typename T>
T Compare<T>::min()
{
return(x<y)?x:y;
}
4. 类内的静态成员赋值,必须 class1 :: data1 = 1.0;必需要有声明符
5. 对传引用的理解,在传引用的时候成员函数定义为 voidswap(int&a,int&b) ,调用方法swap(a,b),调用的时候传的是对象。
一些考题里会在调用的时候写成swap(&a,&b)
6. const 对象不能随便赋值,或者引用。
2010
1. 想要用cin、cout就必须先
using namespace std;
2. 析构函数记得=default,它和想要实现多态的函数设置为virtual
3. +的运算符重载:作为成员函数接受1个参数,作为友元函数接受2个参数
Polynominal Polynominal::operator+(const Polynominal& rp) ;
friend Polynominal operator+(const Polynominal& lp,const Polynominal& rp);
4.输出运算符的重载
ostream& operator<<(ostream& os, const Polynominal& p) //输出,不改变p
{
int i = 0;
os << p.a[i];
for (i = 1; i < p.a.size(); i++)
{
if (p.a[i] == 0) {
continue;
}
os << " +" << p.a[i] << '*' << "x";
if (i > 1)
{
os << '^' << i;
}
}
}
5. 按文件读取数据和按文件输出数据
ofstream:该数据类型表示输出文件流,用于创建文件并向文件写入信息。
ifstream:该数据类型表示输入文件流,用于从文件读取信息。
fstream:该数据类型通常表示文件流,且同时具有 ofstream 和 ifstream 两种功能,
这意味着它可以创建文件,向文件写入信息,从文件读取信息
以写入模式打开文件,并希望截断文件,以防文件已存在,那么您可以使用下面的语法:
main()
{
ofstream outfile;
outfile.open("text.txt", ofstream::out);
if (!outfile) {
cout << "open error" << endl;
return -1;
}
transfer(p, outfile);
}
void transfer(int p,ofstream& out)
{
if (p) {
transfer(p / 2, out);
out << p % 2;
cout << p % 2 <<endl;
}
}
类似地,您如果想要打开一个文件用于读,按行读取,可以使用下面的语法:
#include <string>
#include <iostream>
using namespace std;
int main()
{
ifstream in("1.txt", ios::in); //读取
ofstream out("2.txt", ios::out);//输出
string filename;
string line;
if(in) // 有该文件
{
while (getline (in, line)) // line中不包括每行的换行符
{
cout << line << endl;
out << line << endl; // 输入到2.txt中
}
}
else //
}
ios::out 文件的原有内容被删除
ios::app 在文件原有内容之后新增内容
2011
1. 固定小数点后的位数
#include <iomanip>
cout << fixed << setprecision(10) << 数字;
必须得按这个顺序来
cout << setprecision(10) << y;
//如果没有fixed的话,就是浮点数记数法了,那么它控制的应该就是有效数字的位数(包括小数点前的)!!!!!
cout << fixed << setprecision(10) << y;
2. 实现二维数组
#ifndef _HQC_Array_
#define _HQC_Array_
/*自定义数组二维数组operator()访问,对于一个数组 Array 类的 chess 对象通过调用运算符重载函数(),实现 chess(row,column)代替 chess[row][column]。
请完成:
(1)Array 类的基本定义,包括构造函数、析构函数、拷贝构造函数和基本数据成员;
(2)运算符重载函数()的定义。*/
using namespace std;
#include <iostream>
class Array {
friend ostream& operator<<(ostream& os, const Array& A) {
for (int i = 0; i < A.row; i++) {
for (int j = 0; j < A.colume; j++) {
os << *(A.ptr + i * A.colume + j) << " ";
}
os << endl;
}
return os;
}
public:
Array(int x, int y);
~Array() = default;
//拷贝构造函数
Array(const Array& a);
int& operator()(int x, int y) {
cout << "here " << " x:"<<x << " y:"<< y << endl;
cout << " row:" << row << " colume:" << colume << endl;
if (x>=row||y>=colume) {
cout << "errow!";
}
else {
return *(ptr + x * colume + y);
||返回一块地址?
//ptr是数组指针指向[0][0];
//有3行4列,那么访问[1][2],实际已经是第二行的第三个
}
}
private:
int row, colume;
int* ptr; //数组指针
};
//实现
Array::Array(int x, int y) {
row = x;
colume = y;
if (row * colume == 0) ptr = nullptr;
else {
ptr = new int[row * colume]();
}
}
//拷贝构造函数
Array::Array(const Array& a) {
row = a.row;
colume = a.colume;
ptr = new int[row * colume]();
for (int i = 0; i < row; i++) {
for (int j = 0; j < colume; j++)
{
*(ptr + i * colume + j) = *(a.ptr + i * a.colume + j); //注意这里是i*列+行
}
}
}
#endif
2012
1. 从 黑窗 里 读入 几行文本
/*编写程序,读入几行文本,并打印一个表格,显示每个不同单词在文本中出现的次数。
不是从文件,是从输入里*/
#include <iostream>
#include <string>
#include <sstream>
#include <map>
using namespace std;
bool isPunctuation(char c) {
if (c == ',' || c == '.' || c == '?' || c == '!') return true;
else return false;
}
int main() {
string r;
map<string, int> strMap;//统计结果
while (getline(cin, r)) {
for (string::iterator it = r.begin(); it != r.end(); ++it) {
if (isPunctuation(*it))
*it = ' ';
*it = (isupper(*it) ? tolower(*it) : *it); //修改大小写
}
istringstream strStream(r); // 将读入的字符串转换成字符串流,再逐个提取其中的单词
string temp;
while (strStream >> temp)
strMap[temp]+=1; // 单词计数
}
for (pair<string, int> items:strMap) {
cout << items.first << ": " << items.second << endl;
}
return 0;
}
2013
1. 每10个输出一行的方法
#include <vector>
vector<int> v;
v.pushback(...);
for (int i = 0; i < v.size(); i++) {
cout << v[i]<< ',';
if ((i + 1) % 10 == 0) cout << endl;
}
2. 字符处理:
(1) 标准库是 #include <cstring>
判断是否为小写islower,计算长度strlen
参数为char * ,传入char[]
#include <cstring>
char str[20];
cin >> str;
void extry(char* str){
for(int i =0; i<strlen(str); i++)
{
islower(str[i]);
}
}
(2)
#include <string>
string s
cin >> s;
//替换成
getline( cin , s);
for(int i = 0; i < s.size(); i++)
{
s.substr(0,3) //无结果
}
3. 用迭代器array
array<int, 4> arr = { 1, 3, 2, 4 };
arr.size(); //大小
arr.at(i); //返回在第i处存储的数
4. 输出成表格形式就是用 iomanip 的 setw (几个字符)
#include <iomanip>
cout << setw(4) << x << setw(4)....
5. 进制转换简便算法
hex,Hexadecimal ,十六
dec,Decimal ,十
oct,Octal ,八
bin,Binary,二
//16进制转换成10进制
#include <bits/stdc++.h>
using namespace std;
int a;
int main() {
while (cin >> hex >> a)
cout << setw(6) << static_cast<char>(i);
|强制类型转换ascill编码
cout << dec << a << endl;
return 0;
}
6.
第一次调用strtok(),传入的参数str是要被分割的字符串{aaa - bbb -ccc},而成功后返回的是第一个子字符串{aaa};
而第二次调用strtok的时候,传入的参数应该为NULL,使得该函数默认使用上一次未分割完的字符串继续分割 ,就从上一次分割的位置{aaa-}作为本次分割的起始位置,直到分割结束。
2014
1. string 与 char *
(1)概念上 string 是字符串, char*是指针【存放地址】
char* b = "acd";
char* a = "abc";
char* a1= "abc";
char* c = a;判断 a==a1? 不等于! 因为存放的是地址
(2)string 转化为 char*
string s;
char* ch = (char*) s.data(); //1
const char* ch = s.data(); //2
string str="hmmm"; //3
char p[50];
str.copy(p, 5, 0); //3个参数分别是: 指针,5:复制几个字符,0开始位置,
*(p+5)=‘\0’; //注意手动加结束符!!!
(3)string 判断是否为 int : isdigit ( str[0] )
(4)char* 转化为 string :赋值
string s;
char* p = "hello";
p = s;
2. 构造函数和析构函数,如果没有参数,就加上 () = default;
类的.h 和.cpp可以分开实现
2015
字符串string 的函数总结
(1) 匹配函数 strstr
strstr函数是在字符串str1中查找是否含有字符串str2。如果存在,返回str2在str1中第一次出现的地址;否则返回NULL。
#include <cstring>
#include <string>
const char findStr[] = "i;
const char replaceStr[] = "you";
int len1 = strlen(findStr);
int len2 = strlen(replaceStr);
char* p = strstr(str, findStr);
(2)字符串相加
string s1("abc");
string s2("def");
//结果相同
cout << s1.append(s2) << endl;
s1 += s2;
cout << s1 << endl;
(3)大小写转换:tolower()、toupper()
string ss3("abcdefg");
for (int i = 0; i < ss3.size(); i++)
{
ss3[i] = tolower(ss3[i]);
}
2018、2017
1. int 转成字符串string
#include <string>
int i = 33;
cout << to_string( i );
2. 读入的string 转化成 int
#include <string> //substr函数,getline函数
#include <cstring> //stoi函数
string s;
getline(cin,s);
int x = stoi(s.substr(0,2)); //string类型转化成int
2. int 转化为ASCill码
int i = 33;
cout << static_cast<char> (i);
2019
1. 随机生成数字
#include <ctime>
srand((unsigned int)time(NULL));
int num = rand() % n +a;
//其中的a是起始值,n - 1 + a是终止值,n是整数的范围。
2.递归注意
2. 析构函数注意