C语言中字符串是以'\0'结尾的字符数组。字符串字面量(如"hello")自动在末尾添加'\0'。
字符串长度 vs 数组大小:
strlen():返回字符数(不含'\0')sizeof:返回数组总字节数(含'\0')| 函数 | 功能 | 安全版本 |
|---|---|---|
strlen |
计算字符串长度 | - |
strcpy |
复制字符串 | strncpy |
strcat |
连接字符串 | strncat |
strcmp |
比较字符串 | strncmp |
strchr |
查找字符首次出现 | - |
strstr |
查找子串首次出现 | - |
strtok |
分割字符串 | - |
snprintf |
安全格式化到字符串 | - |
| 函数 | 功能 | 说明 |
|---|---|---|
atoi |
字符串转整数 | 无错误检测 |
atof |
字符串转浮点数 | 无错误检测 |
strtol |
字符串转长整数 | 可检测错误 |
#include <string.h>
// 字符串长度
size_t strlen(const char *s);
// 字符串复制
char *strcpy(char *dest, const char *src);
char *strncpy(char *dest, const char *src, size_t n);
// 字符串连接
char *strcat(char *dest, const char *src);
char *strncat(char *dest, const char *src, size_t n);
// 字符串比较
int strcmp(const char *s1, const char *s2);
int strncmp(const char *s1, const char *s2, size_t n);
// 查找
char *strchr(const char *s, int c);
char *strstr(const char *haystack, const char *needle);
char *strtok(char *str, const char *delim);
// 安全格式化
int snprintf(char *str, size_t size, const char *format, ...);
// 字符串转换
int atoi(const char *str);
double atof(const char *str);
long strtol(const char *str, char **endptr, int base);
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void demonstrate_basic(void) {
printf("=== 基础字符串函数 ===\n");
char src[] = "Hello, World!";
char dest[50];
// strlen
printf("strlen(\"%s\") = %zu\n", src, strlen(src));
printf("sizeof(src) = %zu\n", sizeof(src));
// strcpy
strcpy(dest, src);
printf("strcpy: dest = \"%s\"\n", dest);
// strncpy(注意:不会自动添加'\0')
char buf[10];
strncpy(buf, src, sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
printf("strncpy: buf = \"%s\"\n", buf);
// strcat
char str1[50] = "Hello";
char str2[] = " World";
strcat(str1, str2);
printf("strcat: str1 = \"%s\"\n", str1);
// strcmp
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"));
}
void demonstrate_search(void) {
printf("\n=== 查找函数 ===\n");
char str[] = "Hello, World!";
// strchr
char *p = strchr(str, 'W');
if (p) {
printf("strchr('W'): found at index %ld, rest = \"%s\"\n",
p - str, p);
}
// strstr
p = strstr(str, "World");
if (p) {
printf("strstr(\"World\"): found at index %ld\n", p - str);
}
// strtok
char data[] = "one,two,three,four";
char *token = strtok(data, ",");
printf("strtok tokens: ");
while (token != NULL) {
printf("[%s] ", token);
token = strtok(NULL, ",");
}
printf("\n");
}
void demonstrate_snprintf(void) {
printf("\n=== snprintf安全格式化 ===\n");
char buffer[50];
int result;
result = snprintf(buffer, sizeof(buffer), "Number: %d, Float: %.2f", 42, 3.14);
printf("snprintf: \"%s\" (would write %d chars)\n", buffer, result);
// 截断测试
char small_buf[10];
result = snprintf(small_buf, sizeof(small_buf), "This is a long string");
printf("Truncated: \"%s\" (would write %d chars)\n", small_buf, result);
}
void demonstrate_conversion(void) {
printf("\n=== 字符串转换 ===\n");
// atoi
printf("atoi(\"123\") = %d\n", atoi("123"));
printf("atoi(\"abc\") = %d\n", atoi("abc"));
// strtol(更安全,可检测错误)
char *endptr;
long val;
val = strtol("123abc", &endptr, 10);
printf("strtol(\"123abc\"): val = %ld, endptr = \"%s\"\n", val, endptr);
val = strtol("abc", &endptr, 10);
printf("strtol(\"abc\"): val = %ld, endptr = \"%s\"\n", val, endptr);
// 十六进制转换
val = strtol("0xFF", NULL, 16);
printf("strtol(\"0xFF\", 16) = %ld\n", val);
}
int main() {
demonstrate_basic();
demonstrate_search();
demonstrate_snprintf();
demonstrate_conversion();
return 0;
}
编译命令:
gcc -Wall -Wextra -o string_functions string_functions.c
./string_functions
==比较指针地址,应用strcmpQ1: strcpy和strncpy有什么区别?
A: strcpy不检查目标空间,可能溢出。strncpy最多复制n个字符,但不保证添加'\0'。安全用法:strncpy(dest, src, n-1); dest[n-1] = '\0';
Q2: 为什么说atoi不安全? A: atoi无法区分"0"和非法输入,没有错误检测。应使用strtol,通过endptr检测转换是否成功。
Q3: strtok的线程安全性问题? A: strtok使用静态内部状态保存位置,多线程调用不安全。可使用strtok_r(POSIX)或strtok_s(C11)替代。
Q4: 如何安全地拼接多个字符串? A: 使用snprintf计算所需空间,动态分配,或使用足够大的缓冲区。避免使用strcat多次追加导致溢出。
Q5: sizeof和strlen对字符串的区别? A: sizeof返回数组总大小(含'\0'),strlen返回字符数(不含'\0')。对指针使用sizeof得到的是指针大小,不是字符串长度。