本系列博客基于董山海的<C和C++程序员面试秘笈>,旨在记录,欢迎交流,可联系 zywang@shu.edu.cn !
第四章:字符串
文章目录
1、面试题1
使用库函数将数字转成字符串
itoa(): 将整型值转换为字符串;
ltoa(): 将长整型值转换成字符串;
ultoa(): 将无符号长整型转换为字符串;
gcvt(): 将浮点型数转化为字符串,取四舍五入;
ecvt(): 将双精度浮点型值转化为字符串;
fcvt(): 以指定位数为转换精度,其余同ecvt();
2、面试题2
不使用库函数将整数转化为字符串
#include <iostream>
using namespace std;
//
void int2str(int n, char *str) { //这边n表示整数
char buf[10] = "";
int i = 0;
int len = 0;
int temp = n < 0 ? -n : n; //temp为n的绝对值
if (str == NULL) {
return;
}
//
while (temp) {
buf[i++] = (temp % 10) + '0'; //把temp的每一位上的数存入buf
temp = temp / 10;
}
//
len = n < 0 ? ++i : i; //如果n为负数,则多一位来存储负号
str[i] = 0; //末尾是结束符0
while (1) {
i--;
if (buf[len - i - 1] == 0) {
break;
}
str[i] = buf[len - i - 1]; //把buff数组里的字符拷到字符串
}
if (i == 0) {
str[i] = '-'; //如果是负数,添加负号
}
}
int main() {
int nNum;
char p[10];
cout << "Please input an integer:";
cin >> nNum;
cout << "output: ";
int2str(nNum, p);
cout << p << endl;
system("pause");
return 0;
}
3、面试题3
使用库函数将字符串转化为数字
atof():将字符串转化为双精度浮点型值;
atoi():将字符串转换为整型值;
atol():将字符串转换为长整型值;
strtod():将字符串转化为双精度浮点型值;
strtol():将字符串转换成长整型值;
strtoul():将字符串转换成无符号长整型值;
4、面试题4
不使用库函数将字符串转化为数字
#include <iostream>
using namespace std;
//将字符串转换为整数
int str2int(const char *str) {
int temp = 0;
const char *ptr = str; //ptr保存str字符串开头
//
if (*str == '-' || *str == '+') { //如果第一个字符是正负号,则移到下一个字符
str++;
}
while (*str != 0) {
if ((*str < '0') || (*str > '9')) { //如果当前字符不是数字,则退出循环
break;
}
temp = temp * 10 + (*str - '0'); //如果当前字符是数字,则计算数值,
str++;
}
if (*ptr == '-') { //如果字符串以'-'开头,则换成相反数
temp = -temp;
}
return temp;
}
int main() {
int n = 0;
char p[10] = "";
//
cin.getline(p, 20);
n = str2int(p);
cout << n << endl;
system("pause");
}
5、面试题5
编程实现strcpy函数
strcpy函数的原型是:
c
h
a
r
∗
s
t
r
c
p
y
(
c
h
a
r
∗
s
t
r
D
e
s
t
,
c
o
n
s
t
c
h
a
r
∗
s
t
r
S
r
c
)
char *strcpy(char * strDest,const char *strSrc)
char∗strcpy(char∗strDest,constchar∗strSrc)
#include <stdio.h>
#include <iostream>
//实现strSrc到strDest的复制
char *strcpy(char *strDest, const char * strSrc) {
//判断参数strDest和strSrc有效性,是否为空
if ((strDest == NULL) || (strSrc == NULL)) {
return NULL;
}
//保存目标字符串的首地址
char *strDestCopy = strDest;
//把strSrc字符串的内容复制到strDest下
while ((*strDest++ = *strSrc++) != '\0')
;
return strDestCopy;
}
//
int getStrLen(const char *strSrc) {
int len = 0;
while (*strSrc++ != '\0') {
len++;
}
return len;
}
int main() {
char strSrc[] = "Hello World";
char strDest[20];
int len = 0;
len = getStrLen(strcpy(strDest, strSrc));//链式表达式,先复制再计算长度
printf("strDest:%s\n", strDest);
printf("Length of strDest:%d\n", len);
system("pause");
return 0;
}
为什么要返回 cha r*类型呢? 目的:为了能够使用链式表达式。
6、面试题6
编程实现memcpy函数:
#include <stdio.h>
#include <iostream>
#include <assert.h>
void *memcpy2(void *memTo, const void *memFrom, size_t size) {
//memTo和memFrom必须有效
assert((memTo != NULL) && (memFrom != NULL));
//保存memFrom的首地址
char *tempFrom = (char *)memFrom;
//保存memTo的首地址
char *tempTo = (char *)memTo;
//循环size次,复制memFrom的值到memTo中
while (size-- > 0) {
*tempTo++ = *tempFrom++;
}
return memTo;
}
//
int main() {
char strSrc[] = "Hello World"; //将被复制的字符数组
char strDest[20]; //目的字符数组
memcpy2(strDest, strSrc, 4); //复制strSrc的前4个字符到strDest中
strDest[4] = '\0';
printf("strDest:%s\n", strDest);
system("pause");
return 0;
}
与strcpy函数不同,memcpy以参数size决定复制多少个字符(strcpy是遇见结束符’\0’),如:memcpy复制前四个
strcpy与memcpy的区别
①复制的内容不同;strcpy只能复制字符串,而memcpy可以复制任何内容,如字符数组、整型、结构体、类等;
②复制的方法不同:strcpy不需要指定长度,遇到’\0’就截止,而memcpy是根据其在第三个参数决定复制长度;
③用途不一样:一般字符串复制用strcpy;若需要复制其他类型数据,则一般用memcpy
7、面试题7
编程实现计算字符串的长度
//编程实现计算字符串的长度
#include <stdio.h>
#include <assert.h>
#include <iostream>
int strlen1(const char* src) {
assert(NULL != src); //src必须有效
int len = 0; //保持src首地址
while (*src++ != '\0') //遇到结束符'\0'时退出循环
len++; //每循坏一次,len+1
return len;
}
int strlen2(const char* src) {
assert(NULL != src);
const char *temp = src;
while (*src++ != '\0')
;
return (src - temp - 1); //返回尾部指针与头指针之差,及程度
}
int main() {
char p[] = "Hello World";
printf("strlen1 len:%d\n", strlen1(p));
printf("strlen2 len:%d\n", strlen2(p));
system("pause");
return 0;
}
strlen2比strlen1效率更高,strlen2是指针之间的位置差。
8、面试题8
编程实现字符串中子串的查找:实现一个函数strtstr,即从一个字符串中,查找另一个字符串的位置,如strstr(“12345”,“34”),返回是2,在2号位置找到字符串34。
#include <stdio.h>
#include <iostream>
#include <assert.h>
const char *strstr(const char* src, const char* sub) {
const char *bp;
const char *sp;
//判断src与sub的有效性
if (src == NULL || sub == NULL ) {
return src;
}
//遍历src字符串,也就是src的子串挨个与sub比较
while (*src) {
bp = src; //用于src的遍历
sp = sub; //用于sub的遍历
//遍历sub字符串
do { //如果到了sub字符串结束符位置,表示找到了sub字符串,退出
if (!*sp)
return src;
} while (*bp++ == *sp++);
src += 1;
}
return NULL;
}
int main() {
char p[] = "12345";
char q[] = "34";
char *r = strstr(p, q);
printf("r:%s\n", r);
system("pause");
return 0;
}
9、面试题9
编程实现字符串中各单词的翻转:将句子中的单词位置倒置,而不改变单词内部的结构。
#include <iostream>
using namespace std;
//
void RevStr(char *src) {
char *start = src;
char *end = src;
char *ptr = src;
//
while (*ptr++ != '\0') { //遍历字符串
if (*ptr == ' ' || *ptr == '\0') { //找到一个单词
end = ptr - 1; //end指向单词末尾
//把单词的字母逆置
while (start < end)
swap(*start++, *end--);
//指向下一个单词开头,单词之间间隔是空格不是'\0'
start = end = ptr + 1;
}
}
start = src; //start指向字符串开头
end = ptr - 2; //end指向字符串末尾
//把整个字符串逆置
while (start < end) {
swap(*start++, *end--);
}
}
int main() {
char src[] = "I am from Shanghai";
cout << src << "\n";
RevStr(src);
cout << src << "\n";
system("pause");
return 0;
}
10、面试题10
**编程判断字符串是否是回文字符串 **。
#include <iostream>
using namespace std;
//
int IsRevStr(char *str) {
int i, len;
int found = 1;
//
if (str == NULL) {
return -1;
}
//
len = strlen(str); //获取字符串长度
for (int i = 0; i < len / 2; i++) {
if (*(str + i) != *(str + len - i - 1)) { //遍历中如果发现相应的头尾字符不等,则字符串不是回文字符串
found = 0;
break;
}
}
return found;
}
int main() {
char str1[10] = "1234321";
char str2[10] = "1234221";
//
int test1 = IsRevStr(str1);
int test2 = IsRevStr(str2);
//
cout << "str1 is " << (test1 == 1 ? "" : " not") << " reverse string." << endl;
cout << "str2 is " << (test2 == 1 ? "" : " not") << " reverse string." << endl;
system("pause");
return 0;
}
11、面试题11
编程实现stcmp库函数。对于两个字符串str1和str2,若相等,则返回0;若str1大于str2,则返回-1。
#include <iostream>
using namespace std;
//
int mystrcmp(const char *src, const char *dst) {
int ret = 0;
//循环比较两个字符是否相等,如果不等或者到了dst字符的末尾,则退出循环
while (!(ret = *(unsigned char *)src - *(unsigned char *)dst) && *dst) {
++src;
++dst;
}
//
if (ret < 0) {
ret = -1;
}
else if (ret > 0) {
ret = 1;
}
return ret;
}
int main() {
char str[10] = "1234567";
char str1[10] = "1234567"; //str1==str
char str2[10] = "12345678"; //str2 > str1
char str3[10] = "1234566"; //str3 < str
//测试
int test1 = mystrcmp(str, str1);
int test2 = mystrcmp(str, str2);
int test3 = mystrcmp(str, str3);
cout << "test1= " << test1 << endl;
cout << "test2= " << test2 << endl;
cout << "test3= " << test3 << endl;
system("pause");
return 0;
}
mystrcmp()函数对两个字符串同时进行一次遍历,当它们存在不同值时候就停止循环,最后根据他们最后一个字符的大小,返回相应的结果。
12、面试题12
编程查找两个字符串的最大公共子串:对于两个字符串A和B,如果A="“aocdfe”,B=“pmcdfa”,则输出"cdf"。
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
using namespace std;
char *commonstring(char *str1, char *str2) {
int i, j;
char *shortstr, *longstr;
char *substr;
//判断两个字符的有效性
if (str1 == NULL || str2 == NULL) {
return NULL;
}
//两个指针分别指向较短和较长的字符串
if (strlen(str1) <= strlen(str2)) {
shortstr = str1;
longstr = str2;
}
else {
shortstr = str2;
longstr = str1;
}
//如果在较长的字符串中找到较小的字符串,则返回短字符串
if (strstr(longstr, shortstr) != NULL) {
return shortstr;
}
//申请 堆内存 存放返回结果
substr = (char *)malloc(sizeof(char)*(strlen(shortstr) + 1));
//循环取短串的子串放入堆内存,调用strstr函数检查长串中是否包含这个子串,如果有,则返回堆内存。这个短串长度不断减少的
for (i = strlen(shortstr) - 1; i > 0; i--) {
for (j = 0; j <= strlen(shortstr) - i; j++) {
//将短字符串的一部分复制到substr中
memcpy(substr, &shortstr[j], i);
substr[i] = '\0';
//如果在较长的字符串中找到较小的字符串,则返回短字符串
if (strstr(longstr, substr) != NULL) {
return substr;
}
}
return NULL;
}
}
//
int main(){
char *str1 = (char *)malloc(256);
char *str2 = (char *)malloc(256);
char *common = NULL;
gets_s(str1,20);
gets_s(str2,20);
common = commonstring(str2, str1);
printf("the longest common string is:%s\n", common);
system("pause");
return 0;
}
13、面试题13
不使用printf,将十进制以二进制和十六进制的形式输出。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//
char *get2String(long num) { //得到二进制形式的字符串
int i = 0;
char *buffer;
char* temp;
//long型整数是4个字节,每个8位,一共32位。申请了33个字节(包括'\0')的堆内存存放结果
buffer = (char*)malloc(33);
temp = buffer; //temp
//给数组的32个元素赋值0或者1
for (i = 0; i < 32; i++) {
temp[i] = num&(1 << (31 - i));
temp[i] = temp[i] >> (31 - i);
temp[i] = (temp[i] == 0) ? '0' : '1';
}
buffer[32] = '\0'; //字符串结束符
return buffer;
}
char *get16String(long num) {
int i = 0;
char *buffer = (char*)malloc(11); //这边申请了11个字节,包括'0','x','\0'
char *temp;
buffer[0] = '0';
buffer[1] = 'x';
buffer[10] = '\0';
temp = buffer + 2;
//
for (i = 0; i < 8; i++) {
temp[i] = (char)(num << 4 * i >> 28);
temp[i] = temp[i] >= 0 ? temp[i] : temp[i] + 16;
temp[i] = temp[i] < 10 ? temp[i] + 48 : temp[i] + 55;
}
return buffer;
}
int main() {
char *p = NULL;
char *q = NULL;
int num = 0;
printf("input num:"); //输入整数
scanf_s("%d", &num);
p = get16String(num); //得到十六进制的字符串
q = get2String(num); //得到二进制形式的字符串
printf("%s\n", p);
printf("%s\n", q);
system("pause");
return 0;
}
14、面试题14
编程实现转换字符串、插入字符的个数:例如字符串 aaab,插入字符个数就变成 aaa3b1:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXCOUNT 2*100
char *transformation(char *str) {
int len = strlen(str);
char *buf = new char[len + 1]; //申请llen(str)+1个堆内存来存放字符串数字相关的信息
//
char *p = str;
char *q = p + 1;
int count = 1;
//这个str到结束符为止
while (*q) {
//如果前一个和后一个相等,指针后移,计数增加
if (*p == *q) {
count++;
p++;
q++;
}
else { //如果不等
itoa(count, buf, 10); //把整数转成字符串
int nbits = strlen(buf);
strcat(buf, q); //buf里面保存3b
*q = 0;
strcat(str, buf); //str里面保存aaa
q = q + nbits;
p = q;
q = p + 1;
count = 1;
}
}
itoa(count, buf, 10);
strcat(str, buf);
//释放堆内存
delete[]buf;
buf = NULL;
return str;
}
int main() {
char str[MAXCOUNT];
printf("please input a string:");
scanf_s("%s", &str);
printf("before transformation:%s\n", str);
char *pstr = transformation(str);
printf("after transformation:%s\n", pstr);
system("pause");
return 0;
}
遍历aaab,直到找到不同的字符,然后在buf中保存3b,把str变成aaa(字符‘b’的位置内存设为0)。然后执行strcat(str,buf),此时str变成aaa3b,计数设为1.如果退出循环,则将最后一个字符个数存入buf,此时str中为aaa3b,并且调用strcat,结果strbiancheng aaa3b1。
15、面试题15
字符串编码例题:把一个小于20的字符串 遵循三个规则:
- 把字符串中的字母替换成它的第4个字母,例如:a->e,A->E,X->b,y->c,z->d。
- 如果字符不是字母,则忽略替换;
- 翻转整个字符串;
#include <iostream>
using namespace std;
char LowerCaseAlphabets[] = {
'a','b','c','d','e','f','g','h',
'i','j','k','l','m','n','o','p',
'q','r','s','t','u','v','w','x','y','z'};
char UpperCaseAlphabets[] = {
'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X','Y','Z'};
char GetFourthChar(char chrSource, char alphabets[]) {
for (int i = 0; i < 26; i++) {
if (alphabets[i] == chrSource) {
int index = (i + 4) % 26;
return alphabets[index];
}
}
return '\0';
}
void ReplaceChars(char chars[], int len) {
for (int i = 0; i < len; i++) {
if ('a' <= chars[i] && chars[i] <= 'z') {
chars[i] = GetFourthChar(chars[i], LowerCaseAlphabets);
}
else if('A' <= chars[i] && chars[i] <= 'Z'){
chars[i] = GetFourthChar(chars[i], UpperCaseAlphabets);
}
}
};
//翻转整个字符串
void ReverseString(char str[], int len) {
int begin = 0;
int end = len - 1;
//
if (str[end] == '\0') {
end--;
}
//
char hold;
while (begin < end) {
hold = str[begin];
str[begin] = str[end];
str[end] = hold;
//
begin++;
end--;
}
};
void EncodeString(char str[], int len) {
ReplaceChars(str, len); //替代字符
ReverseString(str, len); //翻转整个字符串
}
int main() {
char hello[] = "hasd11H";
EncodeString(hello, strlen(hello));
cout << hello << endl;
system("pause");
return 0;
}
16、面试题16
反转字符串,但其指定的字符串的子串:给定一个字符串和一个子串,将第一个字符串反转,但保留子串的顺序 :
- 扫描一遍第一个字符串,然后用stack把它反转,同时记录下子串出现的位置;
- 扫描一遍把记录下来的子串再用stack反转;
- 将堆栈里面的字符弹出,这样子串又恢复了原来的顺序;
#include <iostream>
#include <cassert>
#include <stack>
using namespace std;
const char* reverse1(const char* s1, const char* token) { //这边s1是字符串,token是字符串的子串
stack<char> stack1; //这边建立一个堆
const char* ptoken = token, *head = s1, *rear = s1;
assert(s1 && token);
//
while (*head != '\0') { //表示该字符串没有到头
//
while (*head != '\0'&&*ptoken == *head) { //表示字符串里面与子串相等
ptoken++;
head++;
}
//这边表示子串已经走到最后了,走到最后则将它倒过来压入堆栈
if (*ptoken == '\0') {
const char* p;
for (p = head - 1; p >= rear; p--) {
stack1.push(*p);
}
ptoken = token;
rear = head;
} //否则直接压入堆栈
else {
stack1.push(*rear++);
head = rear;
ptoken = token;
}
}
char *pReturn = new char[strlen(s1) + 1];
int i = 0;
while (!stack1.empty()) {
pReturn[i++] = stack1.top();
stack1.pop();
}
pReturn[i] = '\0';
return pReturn;
}
int main(int argc, char* argv[]) {
char welcome[] = "Welcome you, my friend"; //字符串
char token[] = "you"; //字符串的子串
const char *pRev = reverse1(welcome, token);
cout << "before reverse:" << endl;
cout << welcome << endl;
cout << "after reverse:" << endl;
cout << pRev << endl;
system("pause");
return 0;
}
17、面试题17
编写字符串反转函数strrev。
//解法1:第一个和最后一个交换,依次
#include <string>
char* strrev1(const char* str) {
int len = strlen(str);
char* tmp = new char[len + 1];
//
strcpy(tmp, str);
for (int i = 0; i < len / 2; ++i) {
char c = tmp[i];
tmp[i] = tmp[len - i - 1];
tmp[len - i - 1] = c;
}
return tmp;
}
//解法2:指针形式
char* strrev2(const char* str) {
char* tmp = new char[strlen(str) + 1];
strcpy(tmp,str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp) {
char t = *tmp;
*tmp = *p;
*p = t;
--p;
--tmp;
}
return ret;
}
//解法3,优化,使用异或优化
char* strrev3(const char* str) {
char* tmp = new char[strlen(str) + 1];
strcpy(tmp, str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp) {
*p ^= *tmp;
*tmp ^= *p;
*p ^= *tmp;
--p;
++tmp;
}
return ret;
}
//解法4
char* strrev4(const char* str) {
char* tmp = new char[strlen(str) + 1];
strcpy(tmp, str);
char* ret = tmp;
char* p = tmp + strlen(str) - 1;
while (p > tmp) {
*p = *p + *tmp;
*tmp = *p - *tmp;
*p = *p - *tmp;
--p;
++tmp;
}
return ret;
}
//解法5:使用递归
char* reverse5(char* str, int len) {
if (len <= 1) {
return str;
}
//
char t = *str;
*str = *(str + len - 1);
*(str + len - 1) = t;
return (reverse5(str + 1, len - 2) - 1);
}
18、面试题18
编程实现任意长度的两个正整数相加。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
char* addBigInt(char* num1, char* num2) {
//c为进位,开始最低进位为0;
//i指向第一个加数的最低位
//j指向第二个加数的最低位
int c = 0, i = strlen(num1) - 1, j = strlen(num2) - 1;
//两个数中较大数的位数
int maxLength = strlen(num1) >= strlen(num2) ? strlen(num1) + 1 : strlen(num2) + 1;
//保留结果
char* rst = (char*)malloc(maxLength + 1);
//这边判断申请的内存是否成功
if (rst == NULL) {
printf("malloc error!\n");
exit(1);
}
//字符串最后一位为'\0'
rst[maxLength] = '\0';
//指向结果数组的最低位
int k;
k = strlen(rst) - 1;
//
while ((i >= 0) && (j >= 0)) {
rst[k] = ((num1[i] - '0') + (num2[j] - '0') + c) % 10 + '0';
c = ((num1[i] - '0') + (num2[j] - '0') + c) / 10;
--i;
--j;
--k;
}
//这边是个弥补
while (i >= 0) {
rst[k] = ((num1[i] - '0') + c) % 10 + '0';
c = ((num1[i] - '0') + c) / 10;
--i;
--k;
}
//这边是个弥补
while (j >= 0) {
rst[k] = ((num1[j] - '0') + c) % 10 + '0';
c = ((num2[j] - '0') + c) / 10;
--j;
--k;
}
//
rst[0] = c + '0';
//如果结果最高位不等于0,则输出结果
if (rst[0] != '0') {
return rst;
}
else {
return rst + 1;
}
}
int main() {
char num1[] = "123456789323";
char num2[] = "45671254563123";
char *result = NULL;
result = addBigInt(num1, num2);
printf("%s + %s = %s\n", num1, num2, result);
system("pause");
return 0;
}
19、面试题19
编程实现字符串的循环右移:编写函数把一个char组成的字符串循环右移n个。如:abdcefghi,若年,则为hiabcdefg:首先计算字符串尾部移到头部的字符个数,然后分配一个相同大小的堆内存来临时保存这些字符,最后做两次循环分别把头部字符移位到尾部,以及把堆内存中的内容复制到字符串头部。
#include <stdio.h>
#include <stdlib.h>
void loopMove(char *str, int n) {
int i = 0;
char *temp = NULL;
int strLen = 0;
char *head = str; //指向字符串头
//这边str走到字符串末尾了
while (*str++)
;
//计算字符串长度
strLen = str - head - 1;
//计算字符串尾部移到头部的字符
n = n % strLen;
//分配内存
temp = (char *)malloc(n);
//
for (i = 0; i < n; i++) {
temp[i] = head[strLen - n + i];
}
//
for (i = strLen - 1; i >= n; i--) {
head[i] = head[i - n];
}
//
for (i = 0; i < n; i++) {
head[i] = temp[i];
}
//消逝内存
free(temp);
}
int main() {
char string[] = "123456789";
int steps = 0;
printf("string:%s\n", string);
printf("input step:");
scanf_s("%d", &steps);
loopMove(string, steps);
printf("after loopMove %d:%s\n", steps, string);
system("pause");
return 0;
}
20、面试题20
删除指定长度的字符。
#include <stdio.h>
#include <iostream>
#include <string.h>
//str:字符串 pos:从该位置开始 len:删除的长度
char *deleteChars(char *str, int pos, int len) {
char *p = str + pos - 1; //找到开始的位置
int tt = strlen(str); //字符串的长度
if ((pos < 1) || (p - str) > tt) {
return str;
}
//
if ((p + len - str) > tt) {
*p = '\0';
return str;
}
//删除len个字符
while (*p & &*(p + len)) {
*p = *(p + len);
p++;
}
*p = '\0';
return str;
}
int main() {
char string[] = "abcdefg";
int pos = 0;
int len = 0;
int steps = 0;
printf("string:%s\n", string);
printf("input pos:");
scanf_s("%d", &pos);
printf("input len:");
scanf_s("%d", &len);
deleteChars(string, pos, len);
printf("after delete %d chars behind pos %d:%s\n", len, pos, string);
system("pause");
return 0;
}
21、面试题21
字符串的排序以及交换: 编写一个函数将字符串分为两部分,将前半部分按升序排序,后半部分不变,若为奇数,则中间的字符不变。再将前后两部分交换,最后将字符串输出。
#include <stdio.h>
#include <stdlib.h>
//冒泡排序算法
void mysort(char *str, int num) {
int i, j;
int temp = 0;
//
for (i = 0; i < num; i++) {
for (j = i + 1; j < num; j++) {
if (str[i] < str[j]) {
temp = str[i];
str[i] = str[j];
str[j] = temp;
}
}
}
}
char *foo(char *str) {
if (str == NULL)
return NULL;
//
char *start = NULL;
start = str; //这是头部的位置
//此时str是尾部的位置
while (*str++)
;
int len = 0;
len = str - start - 1;
len = len / 2;
str = start;
mysort(str, len);
return str;
}
int main() {
char string[] = "ADZDDJKJFIEJHGI";
printf("before transformation:%s\n", string);
foo(string); //调用冒泡排序方法进行排序
printf("after transformation:%s\n", string);
system("pause");
return 0;
}
22、面试题22
编程实现删除字符串中所有指定的字符:。
#include <stdio.h>
#include <iostream>
char *deleteChar(char *str, char c) {
//
if (str == NULL) {
return NULL;
}
//head与p都设置为头节点那边
char *head = NULL;
char *p = NULL;
head = p = str;
//
while (*p++) {
if (*p != c) {
*str++ = *p;
}
}
*str = '\0';
return head;
}
//
int main() {
char string[] = "cabcdefcgchci";
char c = 0;
printf("input char:");
scanf_s("%c", &c);
printf("before delete:%s\n", string);
deleteChar(string, c); //删除所有的c
printf("after delete:%s\n", string);
system("pause");
return 0;
}
23、面试题23
使用strcat连接字符串,strcat的原型为:
e
x
t
e
r
n
c
h
a
r
∗
s
t
r
c
a
t
(
c
h
a
r
∗
d
e
s
t
,
c
o
n
s
t
c
h
a
r
∗
s
r
c
)
extern \ char \ *strcat(char \ *dest,\ const \ char \ *src)
extern char ∗strcat(char ∗dest, const char ∗src)
#include <iostream>
using namespace std;
int main() {
char *str1 = "hello";
char *str2 = "china";
char *str3 = NULL;
//这边用new申请的堆内存没有被初始化
str3 = new char[strlen(str1) + strlen(str2) + 1];
//str3[0] = '\n';
str3[0] = '\0';//上面的堆内存没有初始化,不含有字符串结束符,输出的是随机值。
strcat(str3, str1);
strcat(str3, str2);
cout << str3 << endl;
system("pause");
return 0;
}
24、面试题24
编程实现strcat。
#include <stdio.h>
#include <stdlib.h>
char *mystrcat(char *dest, const char *src) {
char *ret;
//保存目的字符串首地址以便返回
ret = dest;
while (*dest++)
;
//此时dest指向字符串结束符
dest--;
//循环复制
while (*dest++ = *src++)
;
return ret;
}
int main() {
char *dest = NULL;
char *str1 = "Hello";
char *str2 = "World!";
dest = (char *)malloc(256);
*dest = '\0';
mystrcat(mystrcat(dest, str1), str2);
printf("dest:%s\n", dest);
free(dest);
dest = NULL;
system("pause");
return 0;
}
25、面试题25
**编程计算含有汉字的字符串长度:编写gbk_strlen函数,计算含有汉字的字符串长度,汉字作为一个字符处理,已知:汉字编码为双字节,其中首字节<0,尾字节在063以外(如果一个字节是-128127) **。
#include <iostream>
using namespace std;
int gbk_strlen(const char *str) {
const char *p = str; //头节点,p也用于后面的遍历
//使用两个指针指向的地址之差来获取字符串长度
//若是结束符0,则结束循环
while (*p) {
//汉字编码为双字节,其中首字节<0,尾字节在0~63以外
if (*p < 0 && (*(p + 1) < 0 || *(p + 1) > 63)) { //中文汉字情况
str++; //str移动一位,p移动两位,因此长度+1
p = p + 2;
}
else {
p++;
}
}
return p - str;
}
int main() {
char str[] = "abc你好123中国456";
int len = gbk_strlen(str);
cout << str << endl;
cout << "len = " << len << endl;
system("pause");
return 0;
}
26、面试题26
找出01字符串中0和1连续出现的最大次数。
#include <iostream>
using namespace std;
void Calculate(const char *str, int *max0, int *max1) {
int temp0 = 0; //保存连续是'0'的最大长度
int temp1 = 0; //保存连续是'1'的最大长度
while (*str) { //遍历字符串
if (*str == '0') { //当前字符为‘0’
(*max0)++; //‘0’的计算长度加1
if (*(++str) == '1') { //如果下一个字符是'1'
//判断当前最大长度是否需要保存
if (temp0 < *max0) {
temp0 = *max0;
}
*max0 = 0;
}
}
else if (*str == '1') {
(*max1)++;
if (*(++str) == '0') {
if (temp1 < *max1) {
temp1 = *max1;
}
*max1 = 0;
}
}
}
*max0 = temp0;
*max1 = temp1;
}
int main() {
char string[] = "000011101100000001100110101101001010101011111010";
int max0 = 0; //保存连续是'0'的最大长度
int max1 = 0; //保存连续是'1'的最大长度
Calculate(string, &max0, &max1);
cout << "max0 = " << max0 << endl;
cout << "max1 = " << max1 << endl;
system("pause");
return 0;
}
27、面试题27
编程实现字符串的替换:用户输入3个字符串,然后把在第一个字符串中出现的所有第2个字符串替换成第三个字符串,最后输出新的字符串。
#include <iostream>
using namespace std;
//str为原字符串,sub1:为第2个字符串,sub2为第3个字符串,output为结果
char *replace(const char *str, const char *sub1, const char *sub2, char *output) {
char *pOutput = NULL;
const char *pStr = NULL;
int lenSub1 = strlen(sub1); //子串sub1的长度
int lenSub2 = strlen(sub2);//子串sub2的长度
pOutput = output;
pStr = str; //用于寻找子串
while (*pStr != 0) {
pStr = strstr(pStr, sub1); //在str中寻找sub1子串
if (pStr != NULL) { //找到sub1子串
memcpy(pOutput, str, pStr - str); //复制str的前一部分output
pOutput += pStr - str;
memcpy(pOutput, sub2, lenSub2); //复制sub2子串到output
pOutput = pOutput + lenSub2;
pStr = pStr + lenSub1;
str = pStr;
}
else {
break;
}
}
*pOutput = '\0';
if (*str != '\0') {
strcpy(pOutput, str);
}
return output;
}
int main() {
char str[50] = "";
char sub1[10] = "";
char sub2[10] = "";
char output[100] = "";
cout << "str:";
cin >> str;
cout << "sub1:";
cin >> sub1;
cout << "sub2:";
cin >> sub2;
cout << replace(str, sub1, sub2, output) << endl;
system("pause");
return 0;
}