C/C++程序员面试秘籍

1、函数返回的参数引用

#include "stdafx.h"
#include <iostream>
#include <set>
using namespace std;
float f;
const float pi=3.14f;
float f1(float r)
{
	f=r*r*pi;
	return f;
}
float& f2(float r)
{
	f=r*r*pi;
	return f;
}
int main()
{
	float f1(float=5);//相当于是函数执行了一遍,没有返回值,但是为什么形参可以这样写呢,还要加上float
	float& f2(float=5);
	float a=f1();//为什么不用参数也可以匹配到
	//float& b=f1();
	float c=f2();
	float& d=f2();
	d+=1.0f;
	cout<<a<<" "<<" "<<c<<" "<<d<<endl;

    return 0;
}

这里不明白其用法,需要好好看下书。

 2、指针与数组

int *a=new int[5]();//数组指针
int *c[5];//指针数组,一般作为函数指针
int (*b)[10]
以及二维动态数组的创建又忘了

3、华为题1

计算最大数字连串的问题

#include "stdafx.h"
#include  <stdio.h> 
#include<iostream>
using namespace std;
unsigned int Continumax(char** pOutputstr,  char* intputstr);
unsigned int Continumax(char** pOutputstr,  char* intputstr)
{
	char *pstart=NULL,*tempstart=NULL;//最好声明的时候初始化
	int count=0,tempcount=0;

	while((*intputstr))
	{
		if(isdigit(*intputstr))
		{
			tempcount++;
			if(tempcount==1)
				tempstart=intputstr;

		}
		else
		{
			if(tempcount)
			{
				if(tempcount>=count)
				{
					pstart=tempstart;
					count=tempcount;
				}
				tempcount=0;

			}
		}
		intputstr++;
	}

	if(tempcount>=count)
	{
		pstart=tempstart;
		count=tempcount;
	}
	*pOutputstr=new char[count+1];//若不返回空串,那么会出问题
	if(count)
	memcpy(*pOutputstr,pstart,count);
	(*pOutputstr)[count]='\0';//这个地方尤其要注意,有两个问题,一个是count置0,一个是*pOutputstr
	return count;
}

4、判断IP地址是否正确

#include "stdafx.h"
#include  <stdio.h> 
#include<iostream>
#include<string>
using namespace std;
bool isIPAddressValid(const char* pszIPAddr);
bool isIPAddressValid(const char* pszIPAddr)
{	
	string IPAddr=pszIPAddr;
	cout<<IPAddr<<endl;

	//提取4个字节
	string ip[4];
	int pos1=0,pos2=0;
	for(int i=0;i<3;i++)
	{
		pos2=IPAddr.find_first_of(".",pos1);
		if(pos2>0)
			ip[i]=IPAddr.substr(pos1,(pos2-pos1));
		else
			return false;
		pos1=pos2+1;
	}
	pos1=IPAddr.find_last_of(".");

	if(pos1!=pos2)
		return false;
	else
		ip[3]=IPAddr.substr(pos1+1,IPAddr.length()-pos1);
	
//判断空格
	if(ip[0][ip[0].length()-1]==' ')
		return false;

	if(ip[1][ip[1].length()-1]==' '||ip[1][0]==' ')
		return false;

	if(ip[2][ip[2].length()-1]==' '||ip[2][0]==' ')
		return false;

	if(ip[3][0]==' ')//是字符而不是字符串
		return false;
//0
for(int i=0;i<4;i++)
{	
	for(int j=0;j<ip[i].length();j++)
	{
		if(ip[i][j]!=' ')
		{
			if(ip[i][j]=='0')
			{
				if(j==(ip[i].length()-1))
					break;
				else if(ip[i][j+1]==' ')// =  and  ==
					break;
				else
				{
					//cout<<ip[i]<<endl;
					return false;
				}
					
			}
			else
				break;
		}
		if(ip[i][j]==' '&&j==(ip[i].length()-1))// all is ' '
			
		{
			//cout<<ip[i]<<endl;
			return false;
		}
	}
}

	//cout<<ip[0]<<ip[1]<<ip[2]<<ip[3]<<5<<endl;

		return true;
}

int main()
{ 
	//char* intputstr = "abcd12345ed125ss123456789" ;
	char* intputstr ="   01.0.2.00 ";
	isIPAddressValid(intputstr);
	return 0; 
}

4、找出最大连着数字的长度
// test1.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include  <stdio.h> 
#include<iostream>
#include<string>
using namespace std;
void arrange(string &input);
void arrange(string &input)
{
	int a=input.length();
	if(input.length()!=7)
	{
		cout<<"eoor input"<<endl;
		return;
	}
	else
	{
		for(int i=1;i<input.length()-1;i++)
		{
			int max=i;
			for(int j=i+1;j<input.length()-1;j++)
			{
				if(input[j]>input[max])
					max=j;
			}
			char temp=input[i];
			input[i]=input[max];
			input[max]=temp;
		}
	}
}

int main()
{ 
	//char* intputstr = "abcd12345ed125ss123456789" ;
//	char* inputstr=NULL;//CEAedca
	string inputstr;
	getline(cin,inputstr);
	arrange(inputstr);
	cout<<inputstr<<endl;
	return 0; 
}


9、统计单词出现的频率

<p#include "stdafx.h"
#include  <stdio.h> 
#include<iostream>
#include<string>
#include<vector>
#include<map>
using namespace std;
int main()
{ 
 string a;
 vector<string> v;
 map<string,int> word_map;
 getline(cin,a);
 for(int i=0;i<a.length();i++)
 {
  if(a[i]>'A'&&a[i]<'Z')
   a[i]=a[i]+('a'-'A');
 }
 //cout<<a;
 int p=0;
 //找出单词
 while(a[p]==' '||a[p]==','||a[p]=='.')
 {
  p++;
 }//避免开头的空格
 while(p<a.length())
 {
   int j=p;
   while(a[j]!=' '&& a[j]!=',' && a[j]!='.')
   {
     j++;
     if(j==a.length())
   break;
   }
   string temp=a.substr(p,j-p);
   ++word_map[temp];
   v.push_back(temp);
   if(j==a.length())
    break;
   p=j;
   while(a[p]==' '||a[p]==','||a[p]=='.')
   {
  p++;
   } 
 }
 int max=0;
 string maxstr;
 for(auto iter=word_map.begin();iter!=word_map.end();iter++)
 {
  if((*iter).second>max)
 {
  max=(*iter).second;
  maxstr=(*iter).first;
 }
 }
 int sec=0;
 string secstr;
  for(auto iter=word_map.begin();iter!=word_map.end();iter++)
 {
  if((*iter).second>sec &&(*iter).first!=maxstr)
  { 
   sec=(*iter).second;
   secstr=(*iter).first;
   }
 }
 //比较并记录
  /*
 int *sa=new int[v.size()]();
 int *sf=new int[v.size()]();
 for(int j=0;j<v.size();j++)
 {
   if(!sf[j])
   {
     for(int m=0;m<v.size();m++)
     {
    if(m!=j)
    {
      if(v.at(j).compare(v.at(m))==0)
      {
       sa[j]++;
       sf[m]++;
      }
    }
     }
   }
  
 }
 int first,second;
 for(int j=0;j<2;j++)
 {
   int max=j;
   for(int m=0;m<v.size();m++)
   {
     if(sa[m]>sa[max])
   max=m;
   }
   if(j==0)
   {
     first=max;
     sa[max]=0;
   } 
   else
    second=max; 
 }
 cout<<v.at(first)<<","<<v.at(second)<<endl;delete sa;
delete sf;*/
  cout<<maxstr<<","<<secstr<<endl;
 return 0; 
}

总结:

(1)strng 是没有结束符的,而对于char是有结束符的

(2)一定要注意遍历的时候的溢出问题,是这个题最纠结我的地方。i没有溢出,反而是子地方溢出了

(3)以后提交的时候一定要用vs软件来开发,用.net竟然出一些这样的问题。不解释了。

(4)只用string,一定要熟记string的一些函数,如substr compare length find

(5)这里我后来不用容器来存储,我用了一个map来统计,真的非常方便,以后要经常使用它。

10、奇数偶数交叉排序,输入10个数

#include<iostream>
#include<string>
using namespace std;


int main()
{ 
	int a[20]={0};
	int od[20]={0};
	int js[20]={0};
	for(int i=0;i<10;i++)
	{
		cin>>a[i];
	}
	for(int i=0;i<9;i++)
	{
		int min=i;
		for(int j=i+1;j<10;j++)
		{
			if(a[j]<a[min])
				min=j;
		}
		int temp=a[i];
		a[i]=a[min];
		a[min]=temp;
	}

	int po=0,pj=0;
	for(int i=0;i<10;i++)
	{
		if((a[i]%2)==0)
			od[po++]=a[i];
		else
			js[pj++]=a[i];
	}
	po=0;
	pj=0;
	int i=0;
	while(od[po]!=0 || js[pj]!=0)
	{
		a[i]=js[pj++];
		a[i+1]=od[po++];
		i+=2;
	}
	if(!a[i-1])
		i--;
	for(int j=0;j<i;j++)
		cout<<a[j]<<" ";
	return 0; 
}

11、字符串提取数字

#include "stdafx.h"
#include  <stdio.h> 
#include<iostream>
#include<string>
using namespace std;


int main()
{ 
	string a;
	getline(cin,a);
	int *s=new int[a.length()];
	int i=0,j=0;
	int pos1=0,pos2=0;
	while(i<a.length())//提取逗号之前的
	{
		
		pos2=a.find_first_of(',',pos1);
		if(pos2>0)
		{
		string temp=a.substr(pos1,pos2-pos1);
		s[j++]= atoi(temp.c_str());
		pos1=pos2+1;
		i=pos2;
		}
		i++;

	}
	string temp=a.substr(pos1,a.length()-pos1);//提取最后一个
	s[j]= atoi(temp.c_str());
	for(int m=0;m<=j;m++)
		cout<<s[m]<<" ";
	cout<<endl;
	delete s;
	return 0; 
}

方法二:

	int a[5];
	for(int i=0;i<5;i++)
	{		
		scanf("%d,",&a[i]);		
	}

思想:

(1)有时候换一种思想会轻松很多

12、动态二维数组

int main()
{ 

 int **arc;
 arc=new int*[10];
 for(int i=0;i<10;i++)
 {
	 arc[i]=new int[10];
 }

 arc[0][1]=1;
 cout<<arc[0][1];
 return 0; 
}

第二章

1、sizeof的问题

#include<iostream>
using namespace std;

class A
{
public:
	int num;
	char c1;
	char c2;
};	
class B
{
public:
	char c1;
	int num;
	char c2;
};	

int main()
{
	cout<<sizeof(A)<<" "<<sizeof(B)<<endl;
	system("pause");
	return 0;
}

输出:8 12

 


第七章

1、多重继承与虚拟继承

#include<iostream>
using namespace std;

class A
{
public:
	A():num(0){}
	A(int n):num(n){}
	int num;
};	
class B: public A
{
public:
	B(int n):A(n){}
};
class C: public A
{
public:
	C(int n):A(n){}
};
class D:public B,public C
{
public:
	D(int n):B(n),C(n+1){}
};
int main()
{
	D d(1);
	cout<<d.B::num<<d.C::num<<endl;
	system("pause");
	return 0;
}

输出:12

(1)多重继承会产生二义性,因此需要d.B::num这样来操作

(2)可以用虚拟继承来解决问题,但是那样只会调用基类的默认构造函数,也就是说在所有构造之前,先调用基类的默认构造函数如下:

#include<iostream>
using namespace std;

class A
{
public:
	A():num(0){}
	A(int n):num(n){}
	int num;
};	
class B: virtual public A
{
public:
	B(int n):A(n){}
};
class C: virtual public A
{
public:
	C(int n):A(n){}
};
class D:public B,public C
{
public:
	D(int n):B(n),C(n+1){}
};
int main()
{
	D d(1);
	cout<<d.B::num<<d.num<<endl;
	system("pause");
	return 0;
}

输出:00

1、static关键字的作用?

现分析,全局静态变量、局部静态变量、静态函数的作用。

(1)无论是静态变量还是静态函数都只能在当前模块中使用。

(2)全局静态变量相当于本地的全局变量。

(3)局部静态变量即定义在函数中,当函数调用完毕之后,依然存在,且保存上次运行的值。但是别的函数不能调用它。

(4)静态函数和全局函数的区别就是在内存中只有一份,普通函数在每次被调用中维持一份复制品。

相关代码如下:

a.cpp

#include <iostream>
using namespace std;
#pragma once
int a=1;
static int b=1;
static void StaticPrint()
{
	cout<<"static print function"<<endl;
}
void Print()
{
	static int c=1;//只能在当前函数中使用,但是生存期为整个源程序,函数退出时不消失,只是不能使用它
	c=c+1;
	cout<<" print function"<<c<<endl;
}
void Printb()
{
	cout<<b<<endl;
}
main.cpp

#include <iostream>
using namespace std;
extern void Print();
extern void StaticPrint();
extern int a;
extern int b;
int main()
{
	Print();
	//StaticPrint();//错,静态函数只能在定义模块中使用
	cout<<a<<endl;
	//cout<<b<<endl; //错,静态变量只能在定义模块内使用
	Print();
	system("pause");
	return 0;
}
输出结果为:

 print function2
1
 print function3
请按任意键继续. . .

显然,第二次调用时,局部静态变量值增加。

(5)在类中static关键字的作用

a、不受private的影响,不能在类内初始化。在类外初始化方式为 int A::a=1;

b、类的非静态成员不能在静态成员函数中使用。


2、erase与algorithm中的remove有什么区别?

(1)remove是删除所有指定的元素,但是后面的元素会用原来最后的元素填充。容量不变。
(2)真正迭代器位置的删除,后面的元素会自动前移,容量改变。
#include <iostream>
#include <vector>
#include<algorithm>
using namespace std;
void print(int a)
{
	cout<<a<<"";
}
int main()
{
	int a[4]={0,1,2,3};
	vector<int> v(a,a+4);
	remove(v.begin(),v.end(),1);//删除所有为1的元素,但是后面的元素会用原来最后的元素填充。容量不变。
	for_each(v.begin(),v.end(),print);//记住for_each的用法
	cout<<endl;

	auto iter=v.begin();
	iter=v.erase(iter);//真正删除,后面的元素会自动前移
	cout<<*iter<<endl;
	for_each(v.begin(),v.end(),print);

	system("pause");
	return 0;
}

3、反向迭代器的用法

int main()
{
	int a[4]={0,1,2,3};
	vector<int> v(a,a+4);
	auto iter=++(++v.begin());//指向2,小心++前和++后	
	vector<int>::reverse_iterator iter1(iter);//指向1
	vector<int>::reverse_iterator iter2(iter1);//还是指向1,同类迭代器不变。
	vector<int>::reverse_iterator iter3(iter);//不同迭代器,所以指向iter前一个,为1
	auto iter4(iter3);//此处默认为反向迭代器,正向迭代器是不支持这种构造函数的。所以一样。
	iter4--;
	iter3--;//后移一个,指向2
	cout<<*iter<<" "<<*iter1<<" "<<*iter2<<" "<<*iter3<<" "<<*iter4<<endl;
	system("pause");
	return 0;
}
输出:
2 1 1 2 2
请按任意键继续. . .

基于反向迭代器这样的性质,那么:
注释掉和没有注释掉的同样输出3210
int a[4]={0,1,2,3};
	vector<int> v(a,a+4);
	vector<int>::reverse_iterator riter(v.end());
	vector<int>::reverse_iterator eiter(v.begin());//不能用=赋值,只能这样构造

	/*for(auto iter=v.rbegin();iter!=v.rend();iter++)//这里auto是相当于反向迭代器,如果写成一般迭代器编译会出错
		cout<<*iter;
	cout<<endl;
	*/
	for(auto iter=riter;iter!=eiter;iter++)
		cout<<*iter;
	cout<<endl;


4、函数对象适配器binder1st 和binder2nd.
作用:通过固定其中一个参数,将二元函数转化一元函数,和函数对象一样,同样需要重载()操作符。
用法为:
binder1st<plus<int>> binder(plus<int>(),5);//这里直接调用构造函数
cout<<binder(5)<<endl;//结果为10
这里根据书上写一个函数适配器的类
template <class Operation ,class Param>
class my_binder1st
{
public:
	my_binder1st(){};
	my_binder1st(Operation op,Param para)
	{
		my_binder=op;
		first=para;
	}
	my_binder1st(my_binder1st<Operation,Param> &binder)
	{
		my_binder=binder.my_binder;
		first=binder.first;
	}
	Param operator ()(Param second);//重载()操作符
	my_binder1st<Operation,Param> &operator =(my_binder1st<Operation,Param> &binder);
	bool operator >(my_binder1st<Operation,Param> &binder);
	friend Param operator +(my_binder1st<Operation,Param> &binder1,my_binder1st<Operation,Param> &binder2);
	//my_binder1st<Operation,Param> mybinder(Operation,Param);
private:
	Operation my_binder;
	Param	first;
};
template <class Operation ,class Param>
my_binder1st<Operation,Param> mybinder(Operation op,Param para)
{
	return my_binder1st<Operation,Param>(op,para);
}
template <class Operation ,class Param>
Param my_binder1st<Operation,Param>::operator ()(Param second)
{
	return my_binder(first,second);
}
template <class Operation ,class Param>
Param my_binder1st<Operation,Param>::my(Param a)
{
	return a;
}
template <class Operation ,class Param>
my_binder1st<Operation,Param> &my_binder1st<Operation,Param>::operator =(my_binder1st<Operation,Param> &binder)
{
	my_binder=binder.my_binder;
	first=binder.first;
	return *this;
}
template <class Operation ,class Param>
bool my_binder1st<Operation,Param>::operator >(my_binder1st<Operation,Param> &binder)
{
	//my_binder1st<Operation,Param> temp;
	//temp.my_binder=binder1.my_binder;
	//temp.first=binder1.first+binder2.first;

	return binder.first>first?0:1;
}
template <class Operation ,class Param>
Param operator+(my_binder1st<Operation,Param> binder1,my_binder1st<Operation,Param> binder2)
 {
	my_binder1st<Operation,Param> temp;
	temp.my_binder=binder1.my_binder;
	temp.first=binder1.first+binder2.first;
	return binder1.first+binder2.first;
 }
int main()
{  
	
	my_binder1st<plus<int>,int> binder1=mybinder(plus<int>(),10); //这个mybinder函数为什么不用声明就可以直接定义??
	my_binder1st<plus<int>,int> binder2=mybinder(plus<int>(),15); 
	//my_binder1st<plus<int>,int> binder3=binder1binder2;
	if(binder1>binder2)cout<<"biger"<<endl;
	else
		cout<<"smaller"<<endl;
	binder1st<plus<int>> binder(plus<int>(),5);//直接调用构造函数非常方便
	cout<<binder(21)<<endl;
	
	//cout<<binder1+binder2<<endl;//+符号始终无法作为友元函数重载??
	system("pause");	
	return 0;
}
注意几点:
(1)友元类实现的时候不需要用 类名::
(2)模板类声明的时候要加上 template<类型>
(3)非友元函数重载的操作符一般用 &返回类对象的引用如return *this,而对于友元函数重载的操作符一般返回对象的值。
(4) 模板类对象声明的时候一定要加上类型。












 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值