📄 c.txt
字号:
6.1 数字与字符串的转化
应聘时经常出现数字与字符串之间转化的问题,面试官通过这类题目来考察应聘者能力,例如是否熟悉常用的库函数,是否了解ASCII码以及是否了解字符串的存储格式等。
6.1.1 数字转化为字符串
面试例题1:使用库函数将数字转换为字符串。
考点:C库函数中数字转换为字符串的使用。
出现频率:★★★
解析
C语言提供了几个标准库函数,可以将任意类型(整型、长整型、浮点型等)的数字转换为字符串,下面列举了各函数的方法及其说明。
q itoa():将整型值转换为字符串。
q ltoa():将长整型值转换为字符串。
q ultoa():将无符号长整型值转换为字符串。
q gcvt():将浮点型数转换为字符串,取四舍五入。
q ecvt():将双精度浮点型值转换为字符串,转换结果中不包含十进制小数点。
q fcvt():指定位数为转换精度,其余同ecvt()。
还可以使用sprintf系列函数把数字转换成字符串,其比itoa()系列函数运行速度慢。下列程序演示了如何使用itoa()函数和gcvt()函数:
1 # include <stdio.h>
2 # include <stdlib.h>
3
4 int main ()
5 {
6 int num_int = 435;
7 double num_double = 435.10f;
8 char str_int[30];
9 char str_double[30];
10
11 itoa(num_int, str_int, 10); //把整数num_int转成字符串str_int
12 gcvt(num_double, 8, str_double); //把浮点数num_double转成字符串str_double
13
14 printf("str_int: %s\n", str_int);
15 printf("str_double: %s\n", str_double);
16
17 return 0;
18 }
程序输出结果:
1 str_int: 435
2 str_double: 435.10001
q 代码第11行中的参数10表示按十进制类型进行转换,转换后的结果是“435”,如果按二进制类型进行转换,则结果为“1101110011”。
q 代码第12行中的参数8表示精确位数,这里得到的结果是“435.10001”。
答案
可以使用atoi系列函数把数字转换成字符串。
面试例题2:不使用库函数将整数转换为字符串。
考点:数字转换为字符串,理解相关ASCII码。
出现频率:★★★★
解析
如果不使用atoi或sprintf等库函数,可以通过把整数的各位上的数字加“0”转换成char类型并存到字符数组中。但是要注意,需要采用字符串逆序的方法。如以下程序所示:
1 #include <iostream>
2 using namespace std;
3
4 void int2str(int n, char *str)
5 {
6 char buf[10] = "";
7 int i = 0;
8 int len = 0;
9 int temp = n < 0 ? -n: n; // temp为n的绝对值
10
11 if (str == NULL)
12 {
13 return;
14 }
15 while(temp)
16 {
17 buf[i++] = (temp % 10) + '0'; //把temp的每一位上的数存入buf
18 temp = temp / 10;
19 }
20
21 len = n < 0 ? ++i: i; //如果n是负数,则多需要一位来存储负号
22 str[i] = 0; //末尾是结束符0
23 while(1)
24 {
25 i--;
26 if (buf[len-i-1] ==0)
27 {
28 break;
29 }
30 str[i] = buf[len-i-1]; //把buf数组里的字符拷到字符串
31 }
32 if (i == 0 )
33 {
34 str[i] = '-'; //如果是负数,添加一个负号
35 }
36 }
37
38 int main()
39 {
40 int nNum;
41 char p[10];
42
43 cout << "Please input an integer:";
44 cin >> nNum;
45 cout << "output: " ;
46 int2str(nNum, p); //整型转换成字符串
47 cout<< p << endl;
48
49 return 0;
50 }
程序中的int2str函数完成了int类型到字符串类型的转换。在代码第46行对int2str函数做了测试。程序的执行结果如下所示:
Please input an integer: 1234
Output: 1234
如果输入的是个负数,程序执行结果如下所示:
Please input an integer: -1234
Output: -1234
接下来对int2str函数的实现进行分析。
q 代码第9行,把参数n的绝对值赋给temp,以后在计算各个位的整数时用temp,这样保证在负数情况下取余不会出现问题。
q 代码第11~第14行判断str的有效性,str不为NULL。
q 代码第15~第19行的while循环中,将n的各个位存放到局部数组buf中,存放的顺序与整数顺序相反。例如n为整数123 456,while循环结束后buf应为“654 321”。
q 代码第21行计算转换后字符串的长度len,如果是负数,长度应该再加1。
q 代码第22~第31行把数组buf中的非0元素逆向复制到参数str指向的内存中,如果n是负数,则str指向的第一个内存存放负号。
6.1.2 字符串转化为数字
面试例题3:使用库函数将字符串转换为数字。
考点:C库函数中字符串转换为数字的使用。
出现频率:★★★★
解析
与上节数字转换为字符串类似,C/C++语言提供了几个标准库函数,可以将字符串转换为任意类型(整型、长整型、浮点型等)。以下列举了各函数的方法及其说明。
q atof():将字符串转换为双精度浮点型值。
q atoi():将字符串转换为整型值。
q atol():将字符串转换为长整型值。
q strtod():将字符串转换为双精度浮点型值,并报告不能被转换的所有剩余数字。
q strtol():将字符串转换为长整值,并报告不能被转换的所有剩余数字。
q strtoul():将字符串转换为无符号长整型值,并报告不能被转换的所有剩余数字。
以下程序演示如何使用atoi ()函数和atof ()函数。
1 # include <stdio.h>
2 # include <stdlib.h>
3
4 int main ()
5 {
6 int num_int;
7 double num_double;
8 char str_int[30] = "435"; //将要被转换为整型的字符串
9 char str_double[30] = "436.55"; //将要被转换为浮点型的字符串
10
11 num_int = atoi(str_int); //转换为整型值
12 num_double = atof(str_double); //转换为浮点型值
13
14 printf("num_int: %d\n", num_int);
15 printf("num_double: %lf\n", num_double);
16
17 return 0;
18 }
输出结果:
num_int: 435
num_double: 436.550000
面试例题4:不使用库函数将字符串转换为数字。
考点:字符串转换为数字时,对相关ASCII码的理解。
出现频率:★★★★
解析
程序代码如下:
1 #include <iostream>
2 using namespace std;
3
4 int str2int(const char *str)
5 {
6 int temp = 0;
7 const char *ptr = str; //ptr保存str字符串开头
8
9 if (*str == '-' || *str == '+') //如果第一个字符是正负号,
10 { //则移到下一个字符
11 str++;
12 }
13 while(*str != 0)
14 {
15 if ((*str < '0') || (*str > '9')) //如果当前字符不是数字
16 { //则退出循环
17 break;
18 }
19 temp = temp * 10 + (*str - '0'); //如果当前字符是数字则计算数值
20 str++; //移到下一个字符
21 }
22 if (*ptr == '-') //如果字符串是以“-”开头,则转换成其相反数
23 {
24 temp = -temp;
25 }
26
27 return temp;
28 }
29
30 int main()
31 {
32 int n = 0;
33 char p[10] = "";
34
35 cin.getline(p, 20); //从终端获取一个字符串
36 n = str2int(p); //把字符串转换成整型数
37
38 cout << n << endl;
39
40 return 0;
41 }
程序执行结果:
输入:1234
输出:1234
输入:-1234
输出:-1234
输入:+1234
输出:1234
程序中的str2int函数作用是将字符串转换成整数。这个函数的转换过程与例题2中的int2str函数相比更加简单,它只需要做一次while循环(代码第13行)就能把数值大小计算出来,如果结果是负数,就加一个负号。
6.2 字符串与数组
字符串一般是用字符数组的方式存储,例如下面的str定义:
char str[] = “123456”;
这里str是一个字符数组,它存放了一个字符串“123456”,由于字符串还有一个结束符“\0”,所以此数组的长度为7而不是6。
6.2.1 strcpy函数与memcpy函数
strcpy和memcpy都是标准C库函数,它们有下面的特点。
q strcpy提供了字符串的复制。即strcpy只用于字符串复制,并且它不仅复制字符串内容之外,还会复制字符串的结束符。
q memcpy提供了一般内存的复制。即memcpy对于需要复制的内容没有限制,因此用途更广。
面试例题5:编程实现strcpy函数。
考点:字符串复制的实现。
出现频率:★★★★
已知strcpy函数的原型是:
char * strcpy(char * strDest,const char * strSrc);
要求如下。
(1)不调用库函数,实现strcpy函数;
(2)解释为什么要返回char *。
解析
程序代码如下:
1 #include <stdio.h>
2
3 char * strcpy(char * strDest, const char * strSrc) // 实现strSrc到strDest的复制
4 {
5 if ((strDest == NULL) || (strSrc == NULL)) //判断参数strDest和strSrc的有效性
6 {
7 return NULL;
8 }
9 char *strDestCopy = strDest; //保存目标字符串的首地址
10 while ((*strDest++ = *strSrc++)!='\0'); //把strSrc字符串的内容复制到strDest下
11
12 return strDestCopy;
13 }
14
15 int getStrLen(const char *strSrc) //实现获取strSrc字符串的长度
16 {
17 int len = 0; //保存长度
18 while(*strSrc++ != '\0') //循环直到遇见结束符'\0'为止
19 {
20 len++;
21 }
22
23 return len;
24 };
25
26 int main()
27 {
28 char strSrc[] = "Hello World!"; //要被复制的源字符串
29 char strDest[20]; //要复制到的目的字符数组
30 int len = 0; //保存目的字符数组中字符串的长度
31
32 len = getStrLen(strcpy(strDest, strSrc)); //链式表达式,先复制后计算长度
33 printf("strDest: %s\n", strDest);
34 printf("Length of strDest: %d\n", len);
35
36 return 0;
37 }
(1)strcpy函数的实现说明。
q 代码第5~第7行判断传入的参数strDest和strSrc是否为NULL,如果是则返回NULL。
q 代码第9行把strDest的值保存到strDestCopy指针中。
q 代码第10行对strSrc和strDest两个指针进行循环移动,并不断复制strSrc内存的值到strDest内存中。
q 由于已经保存了strDest指针的值,因此这里只需返回strDestCopy的值,而函数调用完后返回的就是strDest的值。
(2)strcpy函数返回char *类型的原因是为了能使用链式表达式。首先调用strcpy使得strDest指针复制strSrc的内存数据,然后调用getStrLen函数获取strDest字符串的长度。这样不仅调用方便,而且程序结构简洁明了。程序的输出结果如下:
strDest: Hello World!
Length of strDest: 12
面试例题6:编程实现memcpy函数。
考点:内存复制的实现。
出现频率:★★★★
答案
程序代码如下所示:
1 #include <stdio.h>
2 #include <assert.h>
3
4 void *memcpy2(void *memTo, const void *memFrom, size_t size)
5 {
6 assert((memTo != NULL) && (memFrom != NULL)); //memTo和memFrom必须有效
7 char *tempFrom = (char *)memFrom; //保存memFrom首地址
8 char *tempTo = (char *)memTo; //保存memTo首地址
9
10 while(size -- > 0) //循环size次,复制memFrom的值到memTo中
11 *tempTo++ = *tempFrom++ ;
12
13 return memTo;
14 }
15
16 int main()
17 {
18 char strSrc[] = "Hello World!"; //将被复制的字符数组
19 char strDest[20]; //目的字符数组
20
21 memcpy2(strDest, strSrc, 4); //复制strSrc的前4个字符到strDest中
22 strDest[4] = '\0'; //把strDest的第5个元素赋为结束符'\0'
23 printf("strDest: %s\n", strDest);
24
25 return 0;
26 }
memcpy的实现如下。
与strcpy不同,memcpy用参数size决定复制多少个字符(strcpy遇到结束符“\0”结束)。由于在主程序中只复制了strSrc的前4个字符(代码第22行),程序输出如下:
strDest: Hell
面试例题7:strcpy与memcpy的区别。
考点:字符串复制与内存复制之间的区别。
出现频率:★★★★
解析
strcpy和memcpy主要有以下3方面的区别。
q 复制的内容不同。strcpy只能复制字符串,而memcpy可以复制任意内容,例如字符数组、整型、结构体、类等。
q 复制的方法不同。strcpy不需要指定长度,它遇到字符串结束符“\0”便结束。memcpy则是根据其第3个参数决定复制的长度。
q 用途不同。通常在复制字符串时用strcpy,而需要复制其他类型数据时则一般用memcpy。
6.2.2 数组越界
C++不会自动检查数组越界,也就是说如果数组越界,程序编译时不会报错,从而在执行时产生非法操作或者得不到正确的结果。因此在使用数组时,一定要在编程中判断是否越界以保证程序的正确性。
面试例题8:改错——数组越界。
考点:数组越界出现的问题。
出现频率:★★★★
题(1)
1 void test1()
2 {
3 char string[10];
4 char* str1 = "0123456789";
5 strcpy(string, str1);
6 }
题(2)
1 void test2()
2 {
3 char string[10], str1[10];
4 int i;
5 for(i=0; i<10; i++)
6 {
7 str1[i] = 'a';
8 }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -