hello,大家好,本文为大家带来字符串的常见操作以及常见算法题讲解,话不多说,开讲吧!
提取字符串里的数字
此题为经典的字符串操作,读取用户输入的字符串,要求分离出字符串中的数字并输出,具体代码如下:
void getNumsInStr(char *str){if(str == NULL) return;int nums[100];int i = 0, count = 0;int begin = 0, end = 0;if(str[0] == '0'){ // 首字符为0的特殊处理nums[count++] = 0;i = 1;}while(1){// 跳过无效字符while(str[i] && (str[i] < '0' || str[i] > '9')) i++;if(str[i] >= '0' && str[i] <= '9'){nums[count] = str[i] - '0';// 双指针求解字符串中的数字begin = i, end = i + 1;while(str[end] >= '0' && str[end] <= '9'){nums[count] = nums[count] * 10 + str[end] - '0';end ++;}// 更新索引值为endi = end;// 更新数字数量count ++;}else{break;}}printf("输入字符串中的数字有:\n");for(i = 0; i < count; ++i){printf("%d\t", nums[i]);}printf("%n");return ;}
上述程序的运行结果如下:

需要注意的是,本代码存在一个小BUG,也即输入字符串为"0000"时,输出应该为"0 0 0 0"而不是"0 0";欢迎读者讨论并提出修改意见。
无重复字符的最长子串
此题输入为一个字符串,要求输出无重复字符的最长子串,需要注意的是子串是连续的,子序列则是不连续的。
思路分析:定义一个数组用于统计每个字符的出现次数,采用双指针算法,当快指针对应的字符出现次数大于1时,慢指针前移缩小区间,直到慢指针对应的字符次数为1;定义一个变量保留最长的区间长度即可,C语言代码如下:
void longestSubString(char *str){if(str == NULL) return ;int count[128] = { 0 }; // 利用数组构建哈希表int fast = 0, slow = 0, ret = 0;for(fast = 0; str[fast] != '\0'; fast++){// 当str[fast]对应的字符数大于1时,slow指针前移,缩小区间if(++ count[str[fast] > 1){while(slow < fast){count[str[slow ++]] --;if(count[str[slow]] == 1) break;}}// 更新结果ret = ret > (fast - slow + 1) ? ret : (fast - slow + 1);}printf("%s的无重复字符最长子串长度为%d\n", str, ret);return ;}
上述代码的运行结果如下:

最长回文子串
此题为输入为一串字符串,要求输出此字符串的最长回文子串,可采用中心扩散法,定义三个指针,一个指针left向左扩散,一个指针right向右扩散,另外一个中心指针进行遍历,由于回文串可能是奇数串(asdsa),也可能是偶数串(qwwq);因此需要分两种情况进行讨论,C语言代码如下:
char *longestPalindrome(char *str){int len = strlen(str);if(len == 0 || len == 1) return str;int maxLen = 1, start = 0;int left = 0, right = 0;for(int i = 0; i < len; ++i){// 偶数串left = i, right = i + 1;// 指针中心扩散,求解回文串while(left >= 0 && right < len && str[left--] == str[right++]);// 更新结果if(right - left - 1 > maxLen){maxLen = right - left - 1;start = i + 1;}// 奇数串left = i - 1, right = i + 1;// 中心扩散求解回文串长度while(left >= 0 && right < len && str[left--] == str[right++]);if(right - left - 1 > maxLen){maxLen = right - left - 1;start = i + 1;}}char *res = (char *)malloc(sizeof(char) * (maxLen + 1));memcpy(res, str + start, maxLen);res[maxLen] = '\0'; // C语言的细节处理return res;}
上述代码的运行结果如下:

atoi函数自实现
此函数的实现需要注意以下几点:
忽略字符串前导空格
注意整数的正负号
只转换第一个整数,后续的字符串直接丢弃
注意int的范围
C语言代码如下:
int myAtoi(char *str){if(str == NULL) return 0;while(*str == ' ') str++; // 跳过前导空格if(*str == '\0') return 0;if(*str >= 'a' && *str <= 'z') return 0; // 首字母无效if(*str >= 'A' && *str <= 'Z') return 0; // 首字母无效int ret = 0, flag = 1;// 符号问题if(*str == '-'){flag = -1;str++;}else if(*str == '+'){flag = 1;str++;}while(*str != '\0'){// 计算数字大小if(*str >= '0' && *str <= '9'){ret = ret * 10 + *str - '0';str ++;}else {break;}// int溢出处理if((int)ret != ret){if(flag == -1) ret = pow(2, 31);else if(flag == 1) ret = pow(2, 31) - 1;break;}}ret *= flag;return ret;}
上述代码的运行结果如下:

strcpy自实现
此题面试中极为常见,实现也较为简单,C语言代码如下:
char *myStrcpy(char *dest, const char *src){if(!dest || !src) return NULL;char *ret = dest;while((*dest++ = *src++) != '\0');return ret;}
翻转字符串里的单词
此题给定一字符串,字符串里的单词由一个或者多个空格分开,要求将字符串里的单词翻转,单词之间由一个空格隔开;由于此题涉及到翻转,因此可考虑采用先进后出的栈作为辅助,从后往前遍历,遇到空格就出栈,否则入栈,并添加一个空格作为分隔符即可,C语言代码如下:
char *reverseWords(char *str){if(!str) return NULL;int len = strlen(str);char *ret = (char *)malloc(sizeof(char) * (len + 1));char *stk = (char *)malloc(sizeof(char* * (len + 1));int i = 0, top = 0;int count = 0, flag = 0;// 从后往前遍历for(i = len - 1; i >= 0; --i){// 遇见单词 逐字符入栈if(*(str + i) != ' '){stk[top ++] = str[i];flag = 1;}// 遇见空格 出栈并记录结果if(*(str + i) == ' '){while(top > 0){ret[count++] = stk[--top];}if(flag == 1){ret[count++] = ' ';}flag = 0;}}// 特殊处理if(top == 0) {if(count > 0) count--;}// 清空栈,更新结果while(top > 0){ret[count ++] = stk[--top];}ret[count] = '\0';free(stk);return ret;}
上述代码的运行结果如下:

比较运算符的结果
输入一个条件运算符字符串,要求输出字符串的结果,示例如下:
示例一:输入:"T?2:3"输出:"2"
示例二:输入:"T?(T?F:3)" 输出:"F"
规则如下:
条件表达式仅包含0-9,T,F,:,?,数字仅为个位数
表达式从右向左结合
条件一定是T或F两者之一
表达式结果为0-9,F或T
思路分析:此题为模拟题,从右往左遍历字符串,按照规则模拟即可输出结果,C语言代码如下:
void threeEleCounter(void){char str[100];scanf("%s", str);int len = strlen(str);int i = len;while(i > 4){if(str[i - 1] == ':' && str[i - 3] == '?'){if(str[i - 4] == 'T'){str[i - 4 ] = str[i - 2];}else if(str[i - 4] == 'F'){str[i - 4] = str[i];}// 更新下一轮待计算的运算式for(int j = i + 1; j < len; ++j){str[j - 4] = str[j];}len -= 4;i = len - 1;}else{i--;}}if(str[0] == 'T') printf("结果为:%c\n", str[2]);if(str[0] == 'F') printf("结果为:%c\n", str[4]);return ;}
上述程序的执行结果如下:

后记
以上就是本文的全部内容了,C语言解决算法题时,相较于C++,少了许多现成的API接口函数,需要着重厘清指针的指向关系,否则很容易出错,欢迎大家勘误或提出有效建议(seuhyz@163.com),非常感谢大家的支持!





