上一篇已经足够长了,再长也就有点不礼貌了,所以在这儿继续来总结分享那个面试中遇到的题目,文中的问题和提供的答案或者代码均代表个人的理解,如有不合理或者错误的地方,欢迎大家批评指正。
本文中题目列表
- 1. 编码实现子串定位
- 2. 找出两个字符串中最大公共子字符串
- 3. 在一个字符串中找到可能的最长的子字符串,且该字符串是由同一字符组成的
- 4. 把字符1串插入到字符串2中
- 5. 在字符串中找出连续最长的数字串,并把这个串的长度返回
- 6. 实现删除字符串str1中含有的字符串str2
- 7. 写一个函数,找出被重复的数字,时间复杂度必须为O(n)
- 8. 结构体、联合体占用内存问题
- 9. 请写出以下数据类型与零值比较的if语句。
- 10. 如下程序运行结果是什么。
- 11. 使用宏(或者函数)实现两个数的交换的功能。
- 12. 已知类String的原型如下,编写类String的构造函数,析构函数和赋值函数。
- 13. 不用库函数,用C语言实现将一整型数字转化为字符串。
- 14. 用指针的方法,将字符串“ABCD1234efgh”前后对调显示。
- 15. 判断一个字符串是不是回文。
1. 编码实现子串定位
题目:编码实现子串定位,函数原型为int FindSubStr(const char *MainStr, const char *SubStr)
。
查找子串的位置,其功能类似与函数
strstr()
,其函数原型是char *strstr(const char *haystack, const char *needle)
。本文中实现的方式比较简单明了,注释也很详细。参考代码如下。
int FindSubStr(const char *MainStr, const char *SubStr)
{
/* 定义位置临时变量,初始化为0,表示没找到 */
int t_index = 0;
char *t_main_str = MainStr;
char *t_sub_str = SubStr;
/* NOTE 下面这部分代码(SECTION -> !SECTION)为冗余设计,如果写上了说明你对于一些异常情况有考虑并处理的能力,算是加分项 */
/* SECTION 参数判断 */
if (NULL == t_main_str || NULL == t_sub_str) /* 空指针判断 */
return -1;
int t_main_len = strlen(MainStr);
int t_sub_len = strlen(SubStr);
if (t_main_len == 0 || t_sub_len == 0) /* 字符串长度判断,长度为0那就没有继续的必要了 */
return -2;
if (t_main_len < t_sub_len) /* 子串长度比主串长,玩呢 */
return -3;
/* !SECTION 参数判断 */
/* 结束查找的条件,主串到结尾 */
while (*t_main_str != '\0')
{
/* 两个字符串都没有到结为,并且 子串与主串字符相同 */
while (*t_main_str && *t_sub_str && *t_main_str == *t_sub_str)
{
/* 记录当前位置(PS:此位置不一定是最终结果,当做标识使用) */
t_index = (t_main_str - MainStr) + 1;
/* 移动指针 */
t_main_str++;
t_sub_str++;
}
/* 子串到结尾了(PS:说明前面的执行已经匹配到了完整的子串) */
if (*t_sub_str == '\0')
{
/* 计算子串在主串中的开始的位置 */
t_index = (t_main_str - MainStr) + 1 - (t_sub_str - SubStr);
/* 跳出循环(PS:必须的)*/
break;
}
/* 如果位置不为0,说明匹配到了一些字符,但是没有匹配完整的子串 */
if (t_index != 0)
{
/* 指针要做后退一个,不然后面的++会导致跳过一个字符 */
t_main_str--;
/* 当然临时的标识也要恢复 */
t_index = 0;
/* 重新开始匹配子串 */
t_sub_str = SubStr;
}
/* 无条件移动主串的指针 */
t_main_str++;
}
/* 返回位置 */
return t_index;
}
2. 找出两个字符串中最大公共子字符串
题目:找出两个字符串中最大公共子字符串,如"abccade",“dgcadde"的最大子串为"cad”。
像这种只有题目要求和举例说明的题目,编码相对来说比较灵活了,但是在定义函数的时候相关参数和返回值都要尽量体现其合理性的,当然只要正当的考虑即可,下面给出两种实现的方案供参考(方案二中使用
malloc()
函数,但是需要调用者去free,这是个坑)。
// 方案一:直接通过参数输出公共子串在任一字符串中其实位置,通过返回值输出公共子串的长度
int FindCommonStr(const char *str1, const char *str2, char **comm)
{
char *t_str1 = (char *)str1;
char *t_str2 = (char *)str2;
char *t_common = NULL;
int i = 0, j = 0, k = 0, t_len = 0, t_maxlen = 0;
/* 参数判断 */
if (NULL == t_str1 || NULL == t_str2 || NULL == comm)
{
return -1;
}
/* 字符串中一个字符一个字符判断 */
for (i = 0; t_str1[i] != '\0'; i++)
{
/* 保存字符串1当前位置,后面需要自增 */
k = i;
/* 字符串中一个字符一个字符判断 */
for (j = 0; t_str2[j] != '\0'; j++)
{
/* 相同字符的长度,每次重新开始 */
t_len = 0;
/* 两个字符串的字符一致 */
if (t_str1[k] == t_str2[j])
{
while ('\0' != t_str1[k] && /* 字符串没到结束 */
'\0' != t_str2[j] && /* 字符串没到结束 */
t_str1[k] == t_str2[j]) /* 字符一致 */
{
/* 指针后移 */
k++;
j++;
/* 相同字符长度自增 */
t_len++;
}
/* 本次相同字符长度大于记录的最大长度 */
if (t_len > t_maxlen)
{
/* 更新最大长度 */
t_maxlen = t_len;
/* 记录公共子串起始的位置 */
t_common = &t_str1[i]; /* NOTE 如果取另一字符串的话则是:&t_str2[j - t_len]; */
}
}
}
}
/* 输出公共子串 */
*comm = t_common;
/* 返回公共子串的长度 */
return t_maxlen;
}
// 方案二:通过返回值返回最大公共子串,此方案最贴近题目要求,但是需要注意的是 malloc 调用
char *FindCommonStr(const char *str1, const char *str2)
{
char *t_str1 = (char *)str1;
char *t_str2 = (char *)str2;
int i = 0