c++软件研发校招参考
来源:互联网 发布:ssh改端口登录命令 编辑:程序博客网 时间:2024/05/16 05:45
以上是我当时校招写给身边同学的东西,都是平常我的笔记,准备的比较匆忙,囫囵吞枣似的放进来的,我主要是懒得整理了,见谅。不过大家一定要在自己看的基础上整理成自己的笔记,自己的知识。今天放到博客里,希望可以帮助以后校招的同学~ 2014.11.08 素流
楼主从今天起就离校招远去了~正是准备成为一个工作的人~
最后还是这句,整理成自己的知识很重要。
*******************************************************************************------------
---------------c++
关于malloc和new:
vmalloc和free是库函数,以字节为单位申请堆内存
vnew和delete是关键字,以类型为单位申请堆内存
vmalloc和free单纯的对内存进行申请与释放
v对于基本类型new关键字会对内存进行初始化
v对于类类型new和delete还负责构造函数和析构函数的调用
关于指针数组和数组指针:
数组指针(也称行指针)
定义 int (*p)[n];
()优先级高,首先说明p是一个指针,指向一个整型的一维数组,这个一维数组的长度是n,也可以说是p的步长。也就是说执行p+1时,p要跨过n个整型数据的长度。
如要将二维数组赋给一指针,应这样赋值:
int a[3][4];
int (*p)[4]; //该语句是定义一个数组指针,指向含4个元素的一维数组。
p=a; //将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]
p++; //该语句执行过后,也就是p=p+1;p跨过行a[0][]指向了行a[1][]
所以数组指针也称指向一维数组的指针,亦称行指针。
指针数组
定义 int *p[n];
[]优先级高,先与p结合成为一个数组,再由int*说明这是一个整型指针数组,它有n个指针类型的数组元素。这里执行p+1是错误的,这样赋值也是错误的:p=a;因为p是个不可知的表示,只存在p[0]、p[1]、p[2]...p[n-1],而且它们分别是指针变量可以用来存放变量地址。但可以这样 *p=a; 这里*p表示指针数组第一个元素的值,a的首地址的值。
如要将二维数组赋给一指针数组:
int *p[3];
int a[3][4];
for(i=0;i<3;i++)
p[i]=a[i];
这里int *p[3] 表示一个一维数组内存放着三个指针变量,分别是p[0]、p[1]、p[2]
所以要分别赋值。
这样两者的区别就豁然开朗了,数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。
还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
*(p[i]+j)、*(*(p+i)+j)、(*(p+i))[j]、p[i][j]
1.关于static:1.生存期是全局变量,作用域只在声明的函数中。
2.类似全局变量,但是在函数内部定义,且外部不能访问
2.关于面向对象:
封装:
对外不可见。
继承:
对模块的扩展。
多态:
重载-静(函数名相同,改变函数参数个数,或者类型)。
多态-动(virtual在不同的对象指针,调动不同的函数)。
3. c++不可重载的运算符
1.作用与操作符 : ::
2.条件操作符: ?:
3:点操作符: .
4.指向成员的指针操作符: ->/.
5.预处理操作符: #
4.多线程与多进程:
网络编程中设计并发服务器,使用多进程与多线程 ,请问有什么区别?
答案一:
1,进程:子进程是父进程的复制品。子进程获得父进程数据空间、堆和栈的复制品。
2,线程:相对与进程而言,线程是一个更加接近与执行体的概念,它可以与同进程的其他线程共享数据,但拥有自己的栈空间,拥有独立的执行序列。
两者都可以提高程序的并发度,提高程序运行效率和响应时间。
线程和进程在使用上各有优缺点:线程执行开销小,但不利于资源管理和保护;而进程正相反。同时,线程适合于在SMP机器上运行,而进程则可以跨机器迁移。
答案二:
根本区别就一点:用多进程每个进程有自己的地址空间(address space),线程则共享地址空间。所有其它区别都是由此而来的:
1。速度:线程产生的速度快,线程间的通讯快、切换快等,因为他们在同一个地址空间内。
2。资源利用率:线程的资源利用率比较好也是因为他们在同一个地址空间内。
3。同步问题:线程使用公共变量/内存时需要使用同步机制还是因为他们在同一个地址空间内
5.关于虚函数:
class Base
{
public:
virtual void func()
{
cout<<"Base::func()"<<endl;
}
};
class Child : public Base
{
public:
void func()
{
cout<<"Child::func()"<<endl;
}
};
int main()
{
Base* pb = new Base();
pb->func();
Child* pc = (Child*)pb;
pc->func();
delete pc;
pb = new Child();
pb->func();
pc = (Child*)pb;
pc->func();
}
如上面这个题,输出:
Base::func()
Base::func()
Child::func()
Child::func()
这个虚函数关键点在于:
总结一句,虚函数调用谁的函数体看这个实体是谁的。
通过虚函数表指针VPTR调用重写函数是在程序运行时进行的,因此需要通过寻址操作才能确定真正应该调用的函数。而普通成员函数是在编译时就确定了调用的函数。在效率上,虚函数的效率要低很多。
所以没必要将所有函数声明成虚函数
对象中的VPTR指针什么时候被初始化?
对象在创建的时候由编译器对VPTR指针进行初始化
只有当对象的构造完全结束后VPTR的指向才最终确定
父类对象的VPTR指向父类虚函数表
子类对象的VPTR指向子类虚函数表
结论:构造函数中调用虚函数无法实现多态。
面向对象中的抽象类:
v抽象类可用于表示现实世界中的抽象概念
v抽象类是一种只能定义类型,而不能产生对象的类
v抽象类只能被继承并重写相关函数
v抽象类的直接特征是纯虚函数
纯虚函数是只声明函数原型,而故意不定义函数体的虚函数。
v抽象类与纯虚函数
v抽象类不能用于定义对象
v抽象类只能用于定义指针和引用
v抽象中的纯虚函数必须被子类重写
深拷贝,浅拷贝:(一个图,记得上网找找具体代码,加深理解~)
*******************************************************************************
关于排序和链表的反转:(代码仅供参考)
选择排序:
每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。(e.g:5,6,4,6,7,5,2,4,7)
#include <iostream>
using namespace std;
template <int size>
void SelectSort(int(&b)[size])
{
for (int i = 0; i < size; i++)
{
int k = i;
for (int j = i+1; j < size; j++)
{
if (b[k]>b[j])
k= j;
}
swap(b[k], b[i]);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = { 1, 41, 6, 21, 4, 21, 6, 8, 43, 5 };
SelectSort(a);
for (int i = 0; i < 10; cout << a[i++] << " ");
return 0;
}
插入排序:
有一个已经有序的数据序列,要求在这个已经排好的数据序列中插入一个数,但要求插入后此数据序列仍然有序,这个时候就要用到一种新的排序方法——插入排序法,插入排序的基本操作就是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据,算法适用于少量数据的排序,时间复杂度为O(n^2)。是稳定的排序方法。插入算法把要排序的数组分成两部分:第一部分包含了这个数组的所有元素,但将最后一个元素除外,而第二部分就只包含这一个元素。在第一部分排序后,再把这个最后元素插入到此刻已是有序的第一部分里的位置
// InsertSort.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
template <int size>
void InsertSort(int(&m)[size])
{
int temp = 0;
int k = 0;
for (int i = 1; i < size; i++)
{
k = i;
temp = m[i];
for (int j = i-1; (j>=0) && (m[j] > temp); j--)
{
swap(m[j], m[j+1]);
k= j;
}
m[k] = temp;
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = { 23, 421, 52, 12, 53, 98, 5, 8, 6, 23 };
InsertSort(a);
for (int i = 0; i < 10; i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
冒泡:
冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法。
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。
这个算法的名字由来是因为越大的元素会经由交换慢慢“浮”到数列的顶端,故名。
由于冒泡排序简洁的特点,它通常被用来对于计算机程序设计入门的学生介绍算法的概念。
#include <iostream>
using namespace std;
template <int size>
void BubbleSort(int(&b)[size])
{
bool flag = true;
for (int i = 0; flag && (i < size); i++)
{
flag = false;
for (int j = 0; j < size - i - 1; j++)
{
if (b[j]>b[j + 1])
{
swap(b[j], b[j + 1]);
flag= true;
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = { 1, 41, 6, 21, 4, 21, 6, 8, 43, 5 };
BubbleSort(a);
for (int i = 0; i < 10; cout << a[i++] << " ");
return 0;
}
希尔排序:分组,然后插入排序
#include <iostream>
using namespace std;
template <int size>
void ShellSort(int(&b)[size])
{
int gap = size;
do
{
gap = gap / 3 + 1;
for (int i = gap; i < size; i += gap)
{
int k = i;
int temp = b[i];
for (int j = i - gap; (j >= 0) && (temp < b[j]); j -= gap)
{
b[j + gap] = b[j];
k= j;
}
b[k] = temp;
}
} while (gap > 1);
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = { 15, 3, 232, 5, 22, 44, 3, 5, 9, 7 };
ShellSort(a);
for (int i = 0; i < 10; cout << a[i++] << " ");
return 0;
}
快速排序:
取出第一个元素,前后两个指针,不停地进行比较,交换,然后最终让第一个元素放到数组中,左边都小于他,右边大于他。然后,左右递归。
自己写的:
// 快速排序.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
using namespace std;
void QuickSort(int b[],int size)
{
int a = b[0];
int low = 0;
int high = size - 1;
while (low < high)
{
while ((b[high] >= a)&&(low<high))
{
high--;
}
swap(b[low], b[high]);
while ((b[low] <= a) && (low<high))
{
low++;
}
swap(b[low], b[high]);
}
if (size > 1)
{
QuickSort(&b[0], low + 1);
QuickSort(&b[low + 1], size - low - 1);
}
}
int _tmain(int argc, _TCHAR* argv[])
{
int a[10] = { 15, 3, 251532, 5, 22, 44, 3, 5, 9, 7 };
QuickSort(a,10);
for (int i = 0; i < 10; cout << a[i++]<<" ");
return 0;
}
归并排序:
有三个地址,low,mid,high
一个辅助空间,low指针指向的和high指向的比较,谁小放入辅助空间,然后low—或者high++。直到其中一个到mid,另一个放入辅助空间。
// MergeSort.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
vector<int> Merge(vector<int> m, vector<int> n, vector<int> c, int size1, int size2)
{
int i = 0;
int low = 0, high = 0;
while ((low<size1) && (high<size2))
{
if (m[low] < n[high])
{
c[i++] = m[low++];
}
else
{
c[i++] = n[high++];
}
}
while ((low < size1))
{
c[i++] = m[low++];
}
while ((high < size2))
{
c[i++] = n[high++];
}
return c;
}
vector<int> MergeSort(vector<int> m, int size)
{
if (size != 1)
{
int i = 0;
vector<int> a(size>>1,0);
vector<int> b(size - (size >> 1), 0);
vector<int> c(size, 0);
for (int j = 0; j < (size >> 1); j++)
{
a[j] = m[i++];
}
for (int j = 0; j < (size-(size>>1)); j++)
{
b[j] = m[i++];
}
a = MergeSort(a,size>>1);
b = MergeSort(b,size-(size>>1));
m = Merge(a,b,c,size>>1,size-(size>>1));
}
return m;
}
int _tmain(int argc, _TCHAR* argv[])
{
vector<int> a(10,0);
for (int i = 0; i < 10; i++)
a[i] = 10 - i;
a = MergeSort(a,10);
for (int i = 0; i < 10; i++)
{
cout << a[i] << " ";
}
cout << endl;
return 0;
}
堆排序:
// 堆排序.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <vector>
#include <time.h>
#include <stdlib.h>
#include <algorithm>
using namespace std;
void init(int& i)
{
i = rand() % 100 + 1;
}
void printt(int elem)
{
cout << elem << " ";
}
class Heap
{
private:
vector<int> v;
int s;
public:
Heap();
void Heap_In(int k);
void Heap_Out();
void push(int elem);
void pop();
int top();
bool empty();
void print();
};
Heap::Heap()
{
s = 0;
}
void Heap::Heap_In(int k) //这里建立一个m个元素的小根堆,将(v[m - 1] < v[(m >> 1) - 1])中的<改成>就是建一个大根堆。
{
while (k > 1 && (v[k-1] > v[(k >> 1)-1]))
{
swap(v[k-1], v[(k >> 1)-1]);
k >>= 1;
}
}
void Heap::Heap_Out()//将建好的堆弹出顶元素
{
int p;
int k = 1;
while ((k << 1) <= s)
{
p = k << 1;
p += ( p < s && (v[p] > v[p-1]));
if ((v[p-1] > v[k-1]))
{
swap(v[p-1], v[k-1]);
k= p;
}
else
break;
}
}
void Heap::push(int elem)//在堆中放入元素
{
v.push_back(elem);
s++;
Heap_In(s);
}
void Heap::pop()//弹出元素
{
swap(v[0], v[s-1]);
s--;
Heap_Out();
}
int Heap::top()
{
return v.front();
}
bool Heap::empty()
{
return (s == 0) ? true : false;
}
void Heap::print()
{
if (s != 0)
for_each(v.begin(), v.end(), printt);
else
cout << "Heap is empty!" << endl;
}
int main()
{
Heap h;
vector<int> vec(10);
srand((int)time(NULL));
for_each(vec.begin(), vec.end(), init);
for (int i = 0; i < vec.size(); i++)
{
h.push(vec[i]);
}
for (int i = 0; i < vec.size(); i++)
{
cout << h.top()<<" ";
h.pop();
}
cout << endl;
return 0;
}
链表的反转:
1.迭代循环
next = head->next;
head->next = prev;
prev = head;
head = next;
2.递归
newHead = ReverseLink2(head->next); /*递归部分*/ head->next->next = head; /*回朔部分*/
head->next = NULL;
自己写的:
void List::LinkList_reverses() //链表的反转--------迭代循环
{
ListNode* next = NULL;
ListNode* prev = NULL;
while (list->header != NULL)
{
next = list->header->node;
list->header->node = prev;
prev = list->header;
list->header = next;
}
list->header = prev;
}
ListNode* List::LinkList_reverses2(ListNode* head) //链表的反转------------------------------------------------------递归
{
ListNode* newHead = NULL;
if ((head == NULL) || (head->node == NULL))
return head;
newHead = LinkList_reverses2(head->node); /*递归部分*/
head->node->node = head; /*回朔部分*/
head->node = NULL;
return newHead;
}
字符串的反转:
设置一个begin,一个end。如果begin != end,就swap()。
***************************************************************************
——————linux
进程三态:就绪,执行,阻塞
进程同步:按一定顺序执行进程
互斥:都用一个资源,但是同一时间只允许同一个资源使用。
该线程访问的资源叫做临界资源。
调度算法:
1.先来先服务
2.短进程优先
3.高优先级先调度(linux中-20-19,数字越小,优先级越高。Windows中想反)
4.时间片轮转法
死锁:A有一要二,B有二要一
(IPC)进程间通信:目的:1.发数据。2.共享资源。3.通知事件。4.进程控制
方式:
1. 管道(fd【1】写入,在尾部。Fd【0】,读出,在头部。)
无名管道:pipe()父子之间
有名管道:FIFO()任意进程间
Pipe()要记得在fork()之前完成,不然父子间有两个无名管道。
2. OSI七层 TCP/IP
应用层 应用层
表示层
会话层
传输层 传输层
网络层 网络层
数据链路层 网络接口层
物理层
3.网络上用的是big endian(大端模式),所以有时候小端的计算机要字节序转换。
4. Socket:
服务器: 客户端:
1.创建socket() 1. .创建socket()
2.bind()绑定IP、端口号到socket 2.设置IP,端口号
3.设置允许最大连接 listen() 3.connect()连接服务器
4.等待连接请求 accept() 4.收发数据 write(),read()
5. 收发数据 read(),write() 5.关闭网络连接
6.关闭网络连接
5. 关于线程:比进程更节俭,轻量级:代码段,数据段都共享
通信简单。接口:pthread 头文件:pthread.h库文件libpthread.a
创建线程:pthread_create(tidp线程id,attr线程属性(一般NULL),start_rtn线程执行的函数,arg start_rtn的参数)
编译时候加上-lpthread gcc 文件名 –lpthread
线程的终止:
*1.返回(return),2.被另外一个进程终止。3.pthread_exit(不可用exit,不然终止整个进程)
*等待:pthread_join(线程id,线程的返回值)
*线程清除(不可预料的错误,终止退出。)pthread_cleanup_push//和pop
是一个压栈的操作。
6.linux下进程间通信的几种主要手段简介:
管道(Pipe)及有名管道(named pipe):管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信;
信号(Signal):信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本 身;linux除了支持Unix早期信号语义函数sigal外,还支持语义符合Posix.1标准的信号函数sigaction(实际上,该函数是基于 BSD的,BSD为了实现可靠信号机制,又能够统一对外接口,用sigaction函数重新实现了signal函数);
消息(Message)队列(消息队列):消息队列是消息的链接表,包括Posix消息队列system V消息队列。有足够权限的进程可以向队列中添加消息,被赋予读权限的进程则可以读走队列中的消息。消息队列克服了信号承载信息量少,管道只能承载无格式字 节流以及缓冲区大小受限等缺点。
共享内存:使得多个进程可以访问同一块内存空间,是最快的可用IPC形式。是针对其他通信机制运行效率较低而设计的。往往与其它通信机制,如信号量结合使用,来达到进程间的同步及互斥。
信号量(semaphore):主要作为进程间以及同一进程不同线程之间的同步手段。
套接字(Socket):更为一般的进程间通信机制,可用于不同机器之间的进程间通信。起初是由Unix系统的BSD分支开发出来的,但现在一般可以移植到其它类Unix系统上:Linux和System V的变种都支持套接字。
********************************************************************
数据库mysql(这里不理解的建议上网找)
1. 登陆:
Mysql –u用户名 –p密码
2. 可以输入?查看命令
3. 创建/删除数据库
Show database Drop database
4. 使用数据库:
Use 数据库名
5. 创建数据库表
Create table 表名称
(字段名称1 字段类型 属性(约束)
字段名称n。。。。。。。。。。);
6. 删除数据库表: drop table
7. 查看表: DECS table;
8. 查看全部数据库:show databases
9. 产看数据库中的表: show tables
10. Mysql是DDL的数据库,用于定义数据的结构 ,如创建、修改、删除数据库对象
11. 创建脚本,要加入的话用Insert into表名称(字段1……..字段n)VALUES(值1…….值n)
12. 删除数据:Delete From 表名称 条件(例如:where id = 1;)
13. 更新数据:update 表名称 SET 字段1 = 值1…….字段n = 值n 条件。
14. 查询语句:查询全部:select * from 表名称
一般查询:select (*或者某个字段名称)from 表名称 条件。
二分查找
int binery_search(int* a, int low, int high, int key)
{
int ret = -1;
while (low < high)
{
int mid = (low + high) / 2;
if (key == a[mid])
{
ret = mid;
break;
}
else if (key <a[mid])
high = mid - 1;
else
low = mid + 1;
}
return ret;
}
-***********************************************************************---
-----------关于stl:
字符串的初始化:
string str("12345678");
char ch[] = "abcdefgh";
string a; //定义一个空字符串
string str_1(str);
string str_2(str, 2, 5); //从str第二个到第五个复制到str_2
string str_3(ch, 5); //复制ch前五个
string str_4(5, 'X');
string str_5(str.begin(), str.end());
cout << str << endl;
cout << a << endl;
cout << str_1 << endl;
cout << str_2 << endl;
cout << str_3 << endl;
cout << str_4 << endl;
cout << str_5 << endl;
输出:
12345678
12345678
34567
abcde
XXXXX
12345678
字符串的比较:compare():大于返回正数,等于返回0,小于返回负数
string A("aBcdef");
string B("AbcdEf");
string C("123456");
string D("123dfg");
int m = A.compare(B);
int n = A.compare(1, 5, B);
int p = A.compare(1, 5, B, 4, 2); //Bcdef 和 Ef 比较。
int q = C.compare(0, 3, D, 0, 3);
cout << "m=" << m << ", n=" << n << ", p=" << p << ", q=" << q << endl;
cin.get();
return 0;
输出:
1,1,-1,0
string的整体应用代码:
// STL练习.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include <iostream>
#include <algorithm>
#include <vector>
#include <string>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
string str1("123456");
string str2("abcdefghijklmn");
string str;
str.assign(str1);
cout << str << endl;
str.assign(str1, 3, 3);
cout << str << endl;
str.assign(str1, 2, str1.npos);
cout << str << endl;
str.assign(5, 'X');
cout << str << endl;
string::iterator itB;
string::iterator itE;
itB = str1.begin();
itE = str1.end();
str.assign(itB, (--itE));
cout << str << endl;
//////////////////////////
str = str1;
cout << str << endl;
/////////////////////////
str.erase(3);
cout << str << endl;
str.erase(str.begin(), str.end());
cout << ":" << str << ":" << endl;
/////////////////////////
str.swap(str2);
cout << str << endl;
/////////////////////////
string A("ello");
string B("H");
B.insert(1, A);
cout << B << endl;
///.............
A = "ello";
B = "H";
B.insert(1, "yanchy ", 3);
cout << "插入: " << B << endl;
///.............
A = "ello";
B = "H";
B.insert(1, A, 2, 2);
cout << "插入: " << B << endl;
///..............
A = "ello";
B = "H";
B.insert(1, 5, 'C');
cout << "插入: " << B << endl;
///..............
A = "ello";
B = "H";
string::iterator it = B.begin() + 1;
const string::iterator itF = A.begin();
const string::iterator itG = A.end();
B.insert(it, itF, itG);
cout << "插入:" << B << endl;
///..............
A = "ello";
B = "H";
cout << "A= " << A << ", B= " << B << endl;
B.append(A);
cout << "追加:" << B << endl;
//...............
A = "ello";
B = "H";
cout << "A= " << A << ", B= " << B << endl;
B.append("12345", 2);
cout << "追加:" << B << endl;
//................
A = "ello";
B = "H";
cout << "A= " << A << ", B= " << B << endl;
B.append("12345", 2, 3);
cout << "追加:" << B << endl;
//................
A = "ello";
B = "H";
cout << "A= " << A << ", B= " << B << endl;
B.append(10, 'a');
cout << "追加:" << B << endl;
//................
A = "ello";
B = "H";
cout << "A= " << A << ", B= " << B << endl;
B.append(A.begin(), A.end());
cout << "追加:" << B << endl;
return 0;
}
输出:
string的替换: replace()
- #include <iostream>
- #include <string>
- using namespace std;
- void main()
- {
- stringvar("abcdefghijklmn");
- const string dest("1234");
- stringdest2("567891234");
- var.replace(3,3,dest);
- cout<<"1: "<<var<<endl;
- //.....................
- var="abcdefghijklmn";
- var.replace(3,1,dest.c_str(),1,3);
- cout<<"2: "<<var<<endl;
- //.....................
- var="abcdefghijklmn";
- var.replace(3,1,5,'x');
- cout<<"3: "<<var<<endl;
- //.....................
- string::iterator itA,itB;
- string::iterator itC,itD;
- itA=var.begin();
- itB=var.end();
- var="abcdefghijklmn";
- var.replace(itA,itB,dest);
- cout<<"4: "<<var<<endl;
- //.....................
- itA=var.begin();
- itB=var.end();
- itC=dest2.begin()+1;
- itD=dest2.end();
- var="abcdefghijklmn";
- var.replace(itA,itB,itC,itD);
- cout<<"5: "<<var<<endl;
- //.....................
- var="abcdefghijklmn";
- var.replace(3,1,dest.c_str(),4);
- cout<<"6: "<<var<<endl;
- //.....................
- cin.get();
- }
字符串的连接直接用:+
字符串的io操作:
- #include <iostream>
- #include <string>
- using namespace std;
- void main()
- {
- strings1,s2;
- getline(cin,s1);
- getline(cin, s2,' '); //这里设置读到‘ ’就停止。
- cout<<"You inputed chars are: "<<s1<<endl;
- cout<<"You inputed chars are: "<<s2<<endl;
- }
字符串的查找,搜索:
1.#include <iostream>
2.#include <string>
3.using namespace std;
4.void main()
5.{
- stringstr_ch("for");
- stringstr("Hi, Peter, I'm sick. Please boughtsome drugs for me.");
- string::size_type m= str.find('P',5); //查找
- string::size_type rm= str.rfind('P',5); //逆向查找
- cout<<"Example-find(): The position(forward)of 'P' is: "<<(int)m<<endl;
- cout<<"Example-rfind(): Theposition(reverse) of 'P' is: "<<(int)rm<<endl;
- string::size_type n= str.find("some",0);
- string::size_type rn= str.rfind("some",0);
- cout<<"Example-find(): The position(forward)of 'some' is: "<<(int)n<<endl;
- cout<<"Example-rfind(): The position(reverse)of 'some' is: "<<(int)rn<<endl;
- string::size_type mo= str.find("drugs",0,5);
- string::size_type rmo= str.rfind("drugs",0,5);
- cout<<"Example-find(): The position(forward)of 'drugs' is: "<<(int)mo<<endl;
- cout<<"Example-rfind(): The position(reverse)of 'drugs' is: "<<(int)rmo<<endl;
- string::size_type no= str.find(str_ch,0);
- string::size_type rno= str.rfind(str_ch,0);
- cout<<"Example-find(): The position of 'for'is: "<<(int)no<<endl;
- cout<<"Example-rfind(): The position of'for' is: "<<(int)rno<<endl;
- cin.get();
- }
- 结果:
*******************************************************************************
-------vector
1.初始化:
vector<type> name;
vector<type> name(n);//初始化一个type类型,最大容量n的数组
vector<type> name(n,m);//初始化一个type类型,有n个m的数组
用push_back(),等初始化
*初始化容器的时候,不一定只能用同样的容器,只要装的数据类型一样,就可以初始化。
例如:
vector<int> myvt(10,0);
deque<int> d(myvt.begin(), myvt.end());
用insert初始化数组
int a[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
vector<int> v;
v.insert(v.begin(),a[0],a[9]);
c++11新特性里面有新的初始化方法:
vector<int> v{ 1 , 2 , 3 , 4 , 5 };
2.容量和大小:
reserve()预先设定容量大小,resize()可以改变容量。
v.reserve(10);
v.resize(20);
3.各种函数:
size(); resize(); reserve(); capacity();
clear(); empty(); Origin();(初始化函数)
find(); find_if();(第一个大于n的数字下标)
insert(); pop_back(); erase(); clear(); remove();
swap();对象交换(e.g c1.swap(c2); )
4.vector<bool>:
特殊的情况:
专门为bool设计的,使用时候注意强制转换
e.g:
int x【5】 = {0,1,0,1,1};
vector<bool> v;
v.push_back(bool(x[i]));
**************************************************************************
-----list
1.迭代器可以反着定义:list<type>::reverse_iterator iter;
2.*初始化容器的时候,不一定只能用同样的容器,只要装的数据类型一样,就可以初始化。
例如:
vector<int>myvt(10,0);
deque<int>d(myvt.begin(), myvt.end());
3.仿函数,例如greater()等VS中都放在<functional>中。
4.
int randgener()
{
return (rand() % 100);
}
generate(a.begin(),a.end(),randgener);
能够给容器赋随机数初值。同时也可以将a,begin(), a.end()换成指针,例如一个二维数组a【x】【y】
generate(a,a+x*y,randgener);也可以初始化二维数组。
与之相同的还有fill函数
e.g:
bool B[N*M];
fill(B,B+N*M,false);
5.string可以用cout输出,前提是加上string头文件
*********************************************************************************
stl中的算法:
1. 遍历:for_each(b,e,函数)(见笔记)
2. 元素计数:count(),count_if()
最大值最小值:
min_element(begin,end,op(仿函数));
max_element(begin,end,op);
3. 查找:find() find_if(b,e,op):op为条件
search_n(b,e,int m,intn,greater<int>());m个连续大于n的起始位置。//没有greater的话就是m个连续等于n的起始位置。
search(b,e,b',e');搜索子串。
vector<int>::iteratorpos1;
pos1=search(myvector.begin(),myvector.end(),subvector.begin(),subvector.end());
if(pos1!=myvector.end())
{
cout<<"子串在原串中的位置"<<distance(myvector.begin(),pos1)+1<<endl;
}
else
{
cout<<"没有搜索到需要的子串"<<endl;
}
vector<int>::iterator pos2;
pos2=search(myvector.begin(),myvector.end(),checkEvenArg,checkEvenArg+3,checkEven);
cout<<"满足'偶,奇,偶'顺序的子串起始位置:"<<distance(myvector.begin(),pos2)+1<<endl;
4. 比较:equal() mismatch() lexicographical_compare()
5. 复制:copy() copy_backward()
6. 转换:transform()
7. 互换:swap()
8. 赋值:fill(),fill_n(),generate(),generate_n()
9. 替换:replace()
10. 逆转:recerse(),recerse_copy()
11. 旋转:rotate(),rotate_copy()
12. 排列:next_permutation() :用到了函数重载:(升序,降序,均匀分布。。。。)
Sort(),stable_sort()
13. Heap()堆,make_heap(),push_heap(),pop_heap(),sort_heap()
14. 归并排序:merge()
15. 搜索:binary_search(),low_bound(),upper_bound(),equal_range()
第一个大于 打一个大于等于 返回一个pair,前两个之和
16. 移除:remove(),remove_if()
**********************************************************************
关于大小端(概念就不说了)
一、如何判断CPU是大端还是小端?
明白大端和小端的区别,实现起来就非常简单:
#include <stdio.h>
int main()
{
union ut{
short s;
char c[2];
}u;
if(sizeof(short) == 2)
{
u.s = 0x0102;
if(u.c[0] == 1 && u.c[1] == 2)
{
printf("big enidan ");
}else if(u.c[0] == 2 && u.c[1] == 1)
{
printf("little endian. ");
}
return 0;
}
}
二、大端与小端相互转换
#include <stdio.h>
typdedef unsigned int u_32;
typedef unsigned short u_16;
#define BSWAP_16(x)
(u16) ( ((((u16)(x)) & 0x00ff) << 8 ) |
((((u16)(x)) & 0xff00) >> 8 )
)
#define BSWAP_32(x)
(u32) ( (( ((u32)(x)) & 0xff000000 ) >> 24)|
(( ((u32)(x)) & 0x00ff0000 ) >> 8 ) |
(( ((u32)(x)) & 0x0000ff00 ) << 8 ) |
(( ((u32)(x)) & 0x000000ff ) << 24)
)
u16 bswap16(u16 x)
{
return (x & 0x00ff) << 8 |
(x & 0xff00) >> 8
;
}
u32 bswap32(u32 x)
{
return ( x & 0xff000000 )>>24 |
( x & 0x00ff0000 ) >>8 |
( x & 0x0000ff00 ) <<8 |
( x & 0x000000ff ) << 24
;
}
int main(void)
{
//关键是要能对错误进行处理,给一个0x123490照样能得出 0x9034的值,而且, 占内存要小的
printf("macro conversion:%#x ",BSWAP_16(0x123490 ));//要能正确转换
printf("macro conversion:%#x ", BSWAP_32(0x1234567890)); //要能正确转换
printf("----------------- ");
printf("function conversion:%#x ",bswap16(0x123490));
printf("function conversion:%#x ",bswap32(0x1234567890));
return 0;
}
******************************************************************
一些比较杂的东西,看完消化成自己的
不要在构造函数中抛出异常
#在构造函数可能申请系统资源而在构造函数中抛出异常会导致对象构造不完全
#不完全对象的析构函数是不会被调用的因此可能造成资源泄漏
解决办法:在catch中自己手动delete,不要靠析构函数
不要在构造函数中重写函数(多态),因为虚函数表还没生成
########################################################
函数重载与重写(虚函数)
v函数重载
v必须在同一个类中进行
v子类无法重载父类的函数,父类同名函数将被覆盖
v重载是在编译期间根据参数类型和个数决定调用函数
v函数重写
v必须发生于父类与子类之间
v并且父类与子类中的函数必须有完全相同的原型
v使用virtual声明之后能够产生多态
v多态是在运行期间根据具体对象的类型决定调用函数
####################################################
v当子类成员变量与父类成员变量同名时
v子类依然从父类继承同名成员
v在子类中通过作用域分别符::进行同名成员区分
v同名成员存储在内存中的不同位置
############################################################
########################################################
赋值兼容性原则:
#子类对象可以当作父类对象使用
#子类对象可以直接赋值给父类对象
#子类对象可以直接初始化父类对象
#父类指针可以直接指向子类对象
#父类引用可以直接引用子类对象
########################################################
类的静态成员
v静态成员函数与普通成员函数的区别
v静态成员函数不包含指向具体对象的指针
v普通成员函数包含一个指向具体对象的指针
v从命名空间的角度
v类的静态成员只是类这个命名空间中的全局变量和全局函数
v不同之处只是,类可以对静态成员进行访问权限的限制,而命名空间不行
v从面向对象的角度
v类的静态成员属于类概念本身
v类的所有对象共享相同的静态成员
#########################################################
在类中,const成员是不会放入符号表的,会给分配内存,只是一个只读变量。
什么是符号表?
符号表存储在程序中的哪个地方?
v符号表是编译器在编译过程中产生的关于源程序中语法符号的数据结构
v如常量表、变量名表、数组名表、函数名表等等
v符号表是编译器自用的内部数据结构
v符号表不会进入最终产生的可执行程序中
v只有用字面量初始化的const常量才会进入符号表
ü对const常量进行引用会导致编译器为其分配空间
ü虽然const常量被分配了空间,但是这个空间中的值不会被使用
ü使用其它变量初始化的const常量仍然是只读变量
v被volatile修饰的const常量不会进入符号表
ü退化为只读变量,每次访问都从内存中取值
vconst引用的类型与初始化变量的类型
ü相同:使初始化变量成为只读变量
ü不同:生成一个新的只读变量,其初始值与初始化变量相同
###################################################################
double print(int a, int b, int , int c = 0)
{
double d = 3.14;
cout << a << " " << b << " " << c << endl;
return d;
}
int print(int a, int b)
{
cout << a << " " << b << endl;
return a;
}
int main()
{
cout << print(1, 2, 3) << endl;;
}
包含的知识:
#函数的重载和函数名,参数有关,和返回值无关
#参数的占位。目的:
为以后程序的扩展留下线索
兼容C语言程序中可能出现的不规范写法
#默认参数
最重要的一点:大家要学会总结,学会笔记。对自己不会的或者感觉有明显亮点以及平常做错的题目,注意记上笔记,推荐用为知笔记这个软件(这里我不是打广告哦~)
我这里所写的是我所能理解的,望大家在自己理解的基础上,将本内容转成自己的笔记,自己消化理解~
- c++软件研发校招参考
- 德拓DATATOM校招C/C++软件研发笔试题
- 百度校招软件研发工程师要求
- 2015校招 面试(软件研发)
- 百度2014校招 深圳软件研发岗
- 2014百度【软件研发】校招一面面经
- 软件研发人员的考核参考
- 去哪儿网2015校招软件研发笔试题(杭州站)
- 2016腾讯春招软件研发实习笔试
- 2016届 阿里巴巴校招研发工程师C/C++笔试题--2015.08.23
- 百度研发类2013校招笔试
- 百度2013校招研发面经
- 阿里巴巴 2014校招 研发工程师 笔试
- 【2014校招】阿里研发笔试
- 【2014校招】阿里研发面试
- 百度校招研发工程师笔试题
- 阿里校招-java研发 题目
- 2016腾讯校招研发笔试(三)
- 第十三周项目五字符串的操作(2)将str1和str2连接起来,仍存放在str1中
- 第十三周项目一(1):字符统计
- C++中拷贝构造函数
- java面试之内部类
- iOS—如何使用TestFlight进行Beta测试
- c++软件研发校招参考
- php的二进制安全
- IOS-UIButton和UIImageView中Image拉伸效果的实现
- 第十三周 项目3:成绩处理函数版
- 让我们如此享受的慢性毒药
- int main(int argc, char *argv[])的理解,运用其获取文件名
- justinmind破解方法
- spring mvc web.xml
- JS下拉列表交换数据,互相选择代码