C和C++程序员面试秘笈之④

本系列博客基于董山海的<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) charstrcpy(charstrDest,constcharstrSrc)

#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的字符串 遵循三个规则:

  1. 把字符串中的字母替换成它的第4个字母,例如:a->e,A->E,X->b,y->c,z->d
  2. 如果字符不是字母,则忽略替换
  3. 翻转整个字符串
#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

反转字符串,但其指定的字符串的子串:给定一个字符串和一个子串,将第一个字符串反转,但保留子串的顺序

  1. 扫描一遍第一个字符串,然后用stack把它反转,同时记录下子串出现的位置
  2. 扫描一遍把记录下来的子串再用stack反转
  3. 将堆栈里面的字符弹出,这样子串又恢复了原来的顺序
#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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值