字符串相关的知识点
常用字符串函数
#include <string.h>
// 获取字符串长度
strlen(str);
// 字符串复制
strcpy(dest, src);
strncpy(dest, src, n); // 更安全
// 字符串连接
strcat(dest, src);
// 字符串比较
strcmp(str1, str2);
// 查找字符
strchr(str, ch); // 查找字符第一次出现
strrchr(str, ch); // 查找字符最后一次出现
// 查找子串
strstr(haystack, needle);
题目1:字符串反转
题目描述
实现一个函数,将输入的字符串反转过来。
思路分析
使用双指针法,一个指针指向字符串开头,一个指向末尾,交换两个指针所指向的字符,然后向中间移动,直到相遇。
#include <stdio.h>
#include <string.h>
void reverseString(char* s) {
if (s == NULL) return;
int left = 0;
int right = strlen(s) - 1;
while (left < right) {
// 交换字符
char temp = s[left];
s[left] = s[right];
s[right] = temp;
left++;
right--;
}
}
// 测试代码
int main() {
char str1[] = "hello";
printf("原字符串: %s\n", str1);
reverseString(str1);
printf("反转后: %s\n", str1);
char str2[] = "racecar";
printf("原字符串: %s\n", str2);
reverseString(str2);
printf("反转后: %s\n", str2);
return 0;
}
运行结果

题目2:验证回文串
题目描述
给定一个字符串,验证它是否是回文串,只考虑字母和数字字符,忽略字母的大小写。
思路分析
-
使用双指针,一个从前往后,一个从后往前
-
跳过非字母数字字符
-
比较时统一转换为小写
-
如果所有字符都匹配,则是回文串
#include <stdio.h>
#include <ctype.h>
#include <stdbool.h>
#include <string.h>
bool isPalindrome(char* s) {
if (s == NULL) return true;
int left = 0;
int right = strlen(s) - 1;
while (left < right) {
// 跳过非字母数字字符
while (left < right && !isalnum(s[left])) {
left++;
}
while (left < right && !isalnum(s[right])) {
right--;
}
if (left < right) {
// 转换为小写后比较
if (tolower(s[left]) != tolower(s[right])) {
return false;
}
left++;
right--;
}
}
return true;
}
// 测试代码
int main() {
char str1[] = "A man, a plan, a canal: Panama";
printf("字符串: \"%s\"\n", str1);
printf("是否是回文串: %s\n", isPalindrome(str1) ? "是" : "否");
char str2[] = "race a car";
printf("字符串: \"%s\"\n", str2);
printf("是否是回文串: %s\n", isPalindrome(str2) ? "是" : "否");
return 0;
}
运行结果

题目3:字符串中的第一个唯一字符
题目描述
给定一个字符串,找到它的第一个不重复的字符,并返回它的索引。如果不存在,则返回 -1。
思路分析
-
使用哈希表(数组)统计每个字符出现的次数
-
再次遍历字符串,找到第一个计数为1的字符
-
时间复杂度O(n),空间复杂度O(1)(因为字符集大小固定)
#include <stdio.h>
#include <string.h>
int firstUniqChar(char* s) {
if (s == NULL) return -1;
int count[26] = {0}; // 假设只包含小写字母
int len = strlen(s);
// 第一次遍历:统计每个字符出现的次数
for (int i = 0; i < len; i++) {
count[s[i] - 'a']++;
}
// 第二次遍历:找到第一个只出现一次的字符
for (int i = 0; i < len; i++) {
if (count[s[i] - 'a'] == 1) {
return i;
}
}
return -1;
}
// 扩展版本:支持ASCII所有字符
int firstUniqCharExtended(char* s) {
if (s == NULL) return -1;
int count[256] = {0}; // ASCII字符集
int len = strlen(s);
// 统计频率
for (int i = 0; i < len; i++) {
count[(unsigned char)s[i]]++;
}
// 查找第一个唯一字符
for (int i = 0; i < len; i++) {
if (count[(unsigned char)s[i]] == 1) {
return i;
}
}
return -1;
}
// 测试代码
int main() {
char str1[] = "leetcode";
printf("字符串: %s\n", str1);
printf("第一个唯一字符索引: %d\n", firstUniqChar(str1));
char str2[] = "loveleetcode";
printf("字符串: %s\n", str2);
printf("第一个唯一字符索引: %d\n", firstUniqChar(str2));
return 0;
}
运行结果

题目4:有效的括号
题目描述
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
思路分析
-
使用栈数据结构
-
遇到左括号就入栈
-
遇到右括号就检查栈顶是否匹配
-
最后检查栈是否为空
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
#define MAX_SIZE 10000
bool isValid(char* s) {
if (s == NULL) return true;
char stack[MAX_SIZE];
int top = -1;
int len = strlen(s);
for (int i = 0; i < len; i++) {
char c = s[i];
// 如果是左括号,入栈
if (c == '(' || c == '[' || c == '{') {
stack[++top] = c;
}
// 如果是右括号,检查是否匹配
else if (c == ')') {
if (top == -1 || stack[top] != '(') {
return false;
}
top--; // 弹出匹配的左括号
}
else if (c == ']') {
if (top == -1 || stack[top] != '[') {
return false;
}
top--;
}
else if (c == '}') {
if (top == -1 || stack[top] != '{') {
return false;
}
top--;
}
}
// 如果栈为空,说明所有括号都匹配
return top == -1;
}
// 测试代码
int main() {
char* test_cases[] = {
"()",
"()[]{}",
"(]",
"([)]",
"{[]}",
""
};
int num_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_cases; i++) {
printf("字符串: \"%s\"\n", test_cases[i]);
printf("是否有效: %s\n", isValid(test_cases[i]) ? "是" : "否");
printf("\n");
}
return 0;
}
运行结果

题目5:字符串转整数(atoi)
题目描述
实现一个函数,将字符串转换成整数。
思路分析
-
跳过前导空格
-
检查正负号
-
逐位转换数字,注意溢出处理
-
遇到非数字字符停止转换
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
#include <stdbool.h>
int myAtoi(char* s) {
if (s == NULL) return 0;
int i = 0;
int len = 0;
while (s[len] != '\0') len++;
// 1. 跳过前导空格
while (i < len && s[i] == ' ') {
i++;
}
if (i >= len) return 0;
// 2. 处理正负号
int sign = 1;
if (s[i] == '-') {
sign = -1;
i++;
} else if (s[i] == '+') {
i++;
}
// 3. 转换数字
long result = 0; // 使用long防止溢出
while (i < len && isdigit(s[i])) {
int digit = s[i] - '0';
// 检查溢出
if (result > (INT_MAX - digit) / 10) {
return sign == 1 ? INT_MAX : INT_MIN;
}
result = result * 10 + digit;
i++;
}
result *= sign;
// 处理溢出
if (result > INT_MAX) return INT_MAX;
if (result < INT_MIN) return INT_MIN;
return (int)result;
}
// 测试代码
int main() {
char* test_cases[] = {
"42",
" -42",
"4193 with words",
"words and 987",
"-91283472332",
"2147483648",
"-2147483649"
};
int num_cases = sizeof(test_cases) / sizeof(test_cases[0]);
for (int i = 0; i < num_cases; i++) {
printf("输入: \"%s\"\n", test_cases[i]);
printf("输出: %d\n", myAtoi(test_cases[i]));
printf("\n");
}
return 0;
}
运行结果

1万+

被折叠的 条评论
为什么被折叠?



