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:字符串替换

实现字符串替换函数,替换所有匹配的子串。