微软技术面试常问题——将一个字符串转换成整数
主要功能实现(未优化):
int StrToInt(char* string)
{
int number=0;
while(*string!=0)
{
number = number*10 + *string - '0';//直接从高位开始乘加即可,不用考虑字符串的长度
++string;
}
return number;
}
-
注意:在实现功能的同时考虑:特殊输入(如nullptr指针/空字符串/非数字字符串等)、正负号、边界条件(最大正整数与最小负整数溢出)、错误处理等。
-
正整数的最大值是0x7FFFFFFF,负数的最小值是0x80000000。
-
Tips:题目越简单,面试官的期望就越大。
改善之后的代码:
//把一个字符串转换为整数
#include<iostream>
using namespace std;
int string2int(char* string)
{
//1.考虑输入异常:输入为空或者没有输入(直接输入回车键结束)
if (*string=='\0'||string == NULL)
return -1;
int flag = 1;//用于判断输入的数字字符串正负号
int num = 0;
char *str = string;
//2.考虑到正负号(要是输入根本没有符号的情况下也是默认为正号)
if (*str == '+')
{
flag = 1;
++str;
}
else if (*str == '-')
{
++str;
flag = -1;
}
//输入有效则进行字符转换
while (*str)
{
//3.判断输入是否是数字字符串
if (*str >= '0' && *str <= '9')
{
num = num * 10 + flag*(*str - '0');
//4.判断数据是否溢出(大于正整数最大值小于负整数最小值)
if ((flag == 1 && num>0x7fffffff) || (flag == -1 && num < (int)0x80000000))
return -2; //溢出
}
else
{
//输入的字符串中不全是数字
return -1; //不合法
}
++str;
}
return num;
}
int main()
{
char* str = "-1234";
int n = string2int(str);
cout << n << endl;
system("pause");
return 0;
}
笔记:
- 要得到一串字符串方式:
C 中用char str[10];
+gets(str);
或者char str[10];
+scanf("%s", str);
;
C++ 中用char str[10];
+cin>>str;
。C++也兼容C的操作。
在存值时系统自动用'\0'
代替最后的换行符
。 - C++中指针为空的三种写法:NULL, 0, nullptr
关于sizeof的问题
问: 定义一个空的类型,里面没有任何成员变量和成员函数。对该类型求sizeof
,得到的结果是多少?
答: 结果为1。因为空类型中不包含任何信息,但再声明该类型的实例时,它必须在内存中占有一定的空间,否则无法使用这些实例。在VS中,每个空类型的实例占用1个字节的空间。
问: 若在该类型中添加一个构造函数和析构函数,在对该类型求sizeof
,得到的结果又是如何?
答: 还是1。调用这俩函数只需要知道函数的地址,而这些函数的地址只与类型相关,与类型的实例无关,因此这个类型实例的sizeof还是1。
问: 若把析构函数标记为虚函数呢?
答: 虚函数在C++的编译器中会生成虚函数表,并在该类型的每个实例中添加一个指向虚函数表的指针。32位机器上,一个指针占4字节空间,sizeof后得4;64位机器上,一个指针占8字节空间,sizeof后得8。
解释:
- 构造函数(constructor): 是用来处理对象的初始化,是一种特殊的成员函数,与其它成员函数不同,不需要用户去调用它,在建立兑现的时候就自动执行了。
- 析构函数: 也是一种特殊的成员函数,与构造函数作用相反,名字是类名前加上一个“~”符号,在C++中 “~”是取反运算符,从这也可看出与构造函数作用相反,当对象的生命周期结束时,会自动执行析构函数。
一个类可以有多个构造函数,但是只能有一种析构函数。 - 虚函数: 在函数前面加上一个
virtual
,就把类里的成员函数声明为了虚函数,其他部分不动。这样声明之后,用同一种调用形式可以调用同一类族中不同类的虚函数,这就是多态性。
选择题
代码如下:
class A
{
private:
int value;
public:
A(int n){value = n;}
A(A other){value = other.value;}
void Print(){std::cout<<value<<std::endl;}
};
int_tmain(int argc, _TCHAR* argv[])
{
A a=10;
A b=a;
b.Print();
return 0;
}
A.编译错误; B.编译成功,运行时程序崩溃; C.编译运行正常,输出10;
答: C++的标准不允许复制构造函数传值参数, 因为这样会形成永无休止的递归调用从而导致栈溢出。