C&C++快速入门
13、字符串操作函数
1、课程目标
- 掌握常用的字符串操作函数
- 理解安全与不安全的字符串函数
- 掌握Windows字符串API
- 了解字符串处理中的安全问题
2、名词解释
| 函数 | 说明 |
|---|---|
| strlen | 获取字符串长度 |
| strcpy/strncpy | 字符串复制 |
| strcat/strncat | 字符串连接 |
| strcmp/strncmp | 字符串比较 |
| strchr/strrchr | 查找字符 |
| strstr | 查找子串 |
| sprintf/snprintf | 格式化字符串 |
| sscanf | 从字符串解析 |
3、代码实现
1. 基础字符串函数
#include <stdio.h>
#include <string.h>
int main() {
printf("=== 基础字符串函数 ===\n\n");
char str1[] = "Hello";
char str2[] = "World";
char buffer[50];
// strlen: 获取长度
printf("【strlen】\n");
printf("strlen(\"%s\") = %d\n", str1, (int)strlen(str1));
// strcpy: 复制
printf("\n【strcpy】\n");
strcpy(buffer, str1);
printf("strcpy后: %s\n", buffer);
// strcat: 连接
printf("\n【strcat】\n");
strcat(buffer, " ");
strcat(buffer, str2);
printf("strcat后: %s\n", buffer);
// strcmp: 比较
printf("\n【strcmp】\n");
printf("strcmp(\"abc\", \"abc\") = %d\n", strcmp("abc", "abc"));
printf("strcmp(\"abc\", \"abd\") = %d\n", strcmp("abc", "abd"));
printf("strcmp(\"abd\", \"abc\") = %d\n", strcmp("abd", "abc"));
// strchr/strstr: 查找
printf("\n【查找】\n");
char* p = strchr(buffer, 'o');
if (p) printf("strchr 'o': %s\n", p);
p = strstr(buffer, "World");
if (p) printf("strstr \"World\": %s\n", p);
return 0;
}
2. 安全字符串函数
#include <stdio.h>
#include <string.h>
int main() {
printf("=== 安全字符串函数 ===\n\n");
char buffer[10];
const char* longStr = "This is a very long string";
// strncpy: 限制复制长度
printf("【strncpy】\n");
strncpy(buffer, longStr, sizeof(buffer) - 1);
buffer[sizeof(buffer) - 1] = '\0'; // 确保\0结束
printf("截断后: %s\n", buffer);
// snprintf: 安全的格式化
printf("\n【snprintf】\n");
int written = snprintf(buffer, sizeof(buffer), "%s %d", "Value:", 12345);
printf("结果: %s\n", buffer);
printf("实际需要: %d字节, 写入: %d字节\n", written, (int)strlen(buffer));
// 安全的字符串连接
printf("\n【安全连接】\n");
char dest[20] = "Hello";
size_t remaining = sizeof(dest) - strlen(dest) - 1;
strncat(dest, " World!", remaining);
printf("结果: %s\n", dest);
return 0;
}
3. 格式化与解析
#include <stdio.h>
#include <string.h>
int main() {
printf("=== 格式化与解析 ===\n\n");
// sprintf: 格式化到字符串
printf("【sprintf】\n");
char buffer[100];
int num = 42;
float pi = 3.14159f;
sprintf(buffer, "数字: %d, 圆周率: %.2f", num, pi);
printf("%s\n", buffer);
// 构建十六进制字符串
unsigned char bytes[] = {0xDE, 0xAD, 0xBE, 0xEF};
char hexStr[20];
sprintf(hexStr, "%02X%02X%02X%02X", bytes[0], bytes[1], bytes[2], bytes[3]);
printf("十六进制: %s\n", hexStr);
// sscanf: 从字符串解析
printf("\n【sscanf】\n");
const char* data = "192.168.1.100:8080";
int ip1, ip2, ip3, ip4, port;
sscanf(data, "%d.%d.%d.%d:%d", &ip1, &ip2, &ip3, &ip4, &port);
printf("解析: IP=%d.%d.%d.%d, Port=%d\n", ip1, ip2, ip3, ip4, port);
return 0;
}
4. Windows字符串API
#include <stdio.h>
#include <windows.h>
int main() {
printf("=== Windows字符串API ===\n\n");
// lstrcpy / lstrcat / lstrlen
printf("【lstr系列】\n");
char buffer[50];
lstrcpyA(buffer, "Hello");
lstrcatA(buffer, " Windows");
printf("lstrlenA: %d\n", lstrlenA(buffer));
printf("内容: %s\n", buffer);
// 宽字符版本
printf("\n【宽字符版本】\n");
WCHAR wBuffer[50];
lstrcpyW(wBuffer, L"Hello");
lstrcatW(wBuffer, L" World");
wprintf(L"wBuffer: %ls, len=%d\n", wBuffer, lstrlenW(wBuffer));
// 字符串转换
printf("\n【ANSI<->Unicode转换】\n");
const char* ansi = "Hello";
WCHAR wide[50];
int wideLen = MultiByteToWideChar(CP_ACP, 0, ansi, -1, wide, 50);
wprintf(L"ANSI->Wide: %ls (%d字符)\n", wide, wideLen);
char back[50];
WideCharToMultiByte(CP_ACP, 0, wide, -1, back, 50, NULL, NULL);
printf("Wide->ANSI: %s\n", back);
return 0;
}
5、课后作业
5.1、作业1:实现字符串函数
手动实现strlen、strcpy、strcmp函数。
5.2、作业2:字符串分割
实现一个函数,按指定分隔符分割字符串。
5.3、作业3:字符串替换
实现字符串替换函数,替换所有匹配的子串。