Appearance
字符串
在C语言中,字符串是以空字符'\0'结尾的字符数组。本章将详细介绍C语言字符串的定义、操作和常用函数。
字符串基础
字符串的定义
c
/*
* 字符串的定义方式
*/
#include <stdio.h>
#include <string.h>
int main(void)
{
/* 方式1:字符数组初始化 */
char str1[] = "Hello"; /* 自动添加'\0',大小为6 */
/* 方式2:指定大小 */
char str2[10] = "Hello"; /* 后面自动填充'\0' */
/* 方式3:逐个字符初始化 */
char str3[] = {'H', 'e', 'l', 'l', 'o', '\0'};
/* 方式4:字符指针(指向字符串常量) */
char *str4 = "Hello"; /* 字符串常量,不可修改 */
/* 方式5:动态分配 */
char *str5 = (char*)malloc(10);
strcpy(str5, "Hello");
/* 打印字符串 */
printf("str1: %s\n", str1);
printf("str2: %s\n", str2);
printf("str3: %s\n", str3);
printf("str4: %s\n", str4);
printf("str5: %s\n", str5);
/* 字符串大小 */
printf("\nstr1的大小: %zu\n", sizeof(str1)); /* 6字节 */
printf("str1的长度: %zu\n", strlen(str1)); /* 5个字符 */
/* 字符数组 vs 字符指针 */
str1[0] = 'h'; /* 可以修改 */
printf("修改后str1: %s\n", str1);
/* str4[0] = 'h'; */ /* 错误!字符串常量不可修改 */
free(str5);
return 0;
}字符串的输入输出
c
/*
* 字符串的输入输出
*/
#include <stdio.h>
int main(void)
{
char name[50];
/* 使用scanf输入 */
printf("请输入姓名(不含空格): ");
scanf("%s", name); /* 注意:不需要& */
printf("姓名: %s\n", name);
/* scanf遇到空格会停止 */
/* 输入 "Hello World" 只会读取 "Hello" */
/* 使用fgets输入(推荐) */
char sentence[100];
getchar(); /* 清除缓冲区中的换行符 */
printf("请输入一句话: ");
fgets(sentence, sizeof(sentence), stdin);
/* 去除末尾的换行符 */
int len = 0;
while (sentence[len] != '\0' && sentence[len] != '\n') {
len++;
}
sentence[len] = '\0';
printf("你输入的是: %s\n", sentence);
/* 使用puts输出 */
puts("使用puts输出"); /* 自动换行 */
/* 使用fputs输出 */
fputs("使用fputs输出", stdout);
putchar('\n');
return 0;
}字符串函数
字符串长度和复制
c
/*
* 字符串长度和复制函数
*/
#include <stdio.h>
#include <string.h>
int main(void)
{
char src[] = "Hello, World!";
char dest[50];
/* strlen - 获取字符串长度(不包括'\0') */
printf("strlen(src) = %zu\n", strlen(src));
/* strcpy - 复制字符串 */
strcpy(dest, src);
printf("strcpy后: dest = %s\n", dest);
/* strncpy - 复制指定长度 */
char dest2[10];
strncpy(dest2, src, 5);
dest2[5] = '\0'; /* 手动添加结束符 */
printf("strncpy后: dest2 = %s\n", dest2);
/* strcat - 字符串连接 */
char str1[50] = "Hello";
char str2[] = " World";
strcat(str1, str2);
printf("strcat后: str1 = %s\n", str1);
/* strncat - 连接指定长度 */
char str3[20] = "Hello";
strncat(str3, " World!!!", 6);
printf("strncat后: str3 = %s\n", str3);
/* 自定义strlen */
size_t my_strlen(const char *s);
printf("\n自定义strlen: %zu\n", my_strlen(src));
return 0;
}
/* 自定义strlen函数 */
size_t my_strlen(const char *s)
{
size_t len = 0;
while (s[len] != '\0') {
len++;
}
return len;
}字符串比较
c
/*
* 字符串比较函数
*/
#include <stdio.h>
#include <string.h>
int main(void)
{
char str1[] = "Hello";
char str2[] = "Hello";
char str3[] = "World";
char str4[] = "hello";
/* strcmp - 字符串比较 */
/* 返回值:0表示相等,<0表示str1<str2,>0表示str1>str2 */
printf("strcmp(str1, str2) = %d\n", strcmp(str1, str2)); /* 0 */
printf("strcmp(str1, str3) = %d\n", strcmp(str1, str3)); /* <0 */
printf("strcmp(str3, str1) = %d\n", strcmp(str3, str1)); /* >0 */
/* 大小写敏感 */
printf("strcmp(str1, str4) = %d\n", strcmp(str1, str4)); /* <0 */
/* strncmp - 比较指定长度 */
printf("strncmp(\"Hello\", \"Help\", 3) = %d\n",
strncmp("Hello", "Help", 3)); /* 0(前3个字符相同) */
/* strcasecmp - 忽略大小写比较(非标准,POSIX) */
/* printf("strcasecmp(str1, str4) = %d\n", strcasecmp(str1, str4)); */
/* 使用示例 */
if (strcmp(str1, str2) == 0) {
printf("\nstr1和str2相等\n");
}
/* 自定义strcmp */
int my_strcmp(const char *s1, const char *s2);
printf("\n自定义strcmp: %d\n", my_strcmp("abc", "abd"));
return 0;
}
int my_strcmp(const char *s1, const char *s2)
{
while (*s1 && (*s1 == *s2)) {
s1++;
s2++;
}
return *(unsigned char*)s1 - *(unsigned char*)s2;
}字符串查找
c
/*
* 字符串查找函数
*/
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Hello, World! Welcome to C!";
/* strchr - 查找字符第一次出现的位置 */
char *p = strchr(str, 'W');
if (p != NULL) {
printf("找到'W'在位置: %ld\n", p - str);
printf("从'W'开始: %s\n", p);
}
/* strrchr - 查找字符最后一次出现的位置 */
p = strrchr(str, 'o');
if (p != NULL) {
printf("最后一个'o'在位置: %ld\n", p - str);
}
/* strstr - 查找子串 */
p = strstr(str, "World");
if (p != NULL) {
printf("找到\"World\"在位置: %ld\n", p - str);
}
/* strpbrk - 查找任意匹配字符 */
p = strpbrk(str, "aeiou");
if (p != NULL) {
printf("第一个元音字母'%c'在位置: %ld\n", *p, p - str);
}
/* strspn - 计算匹配字符集的长度 */
size_t len = strspn("123abc", "0123456789");
printf("\n\"123abc\"中数字部分的长度: %zu\n", len);
/* strcspn - 计算不匹配字符集的长度 */
len = strcspn("abc123", "0123456789");
printf("\"abc123\"中非数字部分的长度: %zu\n", len);
/* strtok - 分割字符串 */
char str_copy[] = "Hello,World,Welcome";
char *token;
printf("\n分割字符串:\n");
token = strtok(str_copy, ",");
while (token != NULL) {
printf(" %s\n", token);
token = strtok(NULL, ",");
}
return 0;
}字符串转换
c
/*
* 字符串转换函数
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
char str[] = "Hello World 123";
/* 大小写转换 */
printf("原字符串: %s\n", str);
/* 转换为大写 */
char upper[50];
for (int i = 0; str[i]; i++) {
upper[i] = toupper(str[i]);
}
upper[strlen(str)] = '\0';
printf("大写: %s\n", upper);
/* 转换为小写 */
char lower[50];
for (int i = 0; str[i]; i++) {
lower[i] = tolower(str[i]);
}
lower[strlen(str)] = '\0';
printf("小写: %s\n", lower);
/* 字符串转数字 */
char num_str[] = "12345";
int num = atoi(num_str); /* 字符串转int */
printf("\natoi(\"12345\") = %d\n", num);
long lnum = atol("1234567890"); /* 字符串转long */
printf("atol(\"1234567890\") = %ld\n", lnum);
double dnum = atof("3.14159"); /* 字符串转double */
printf("atof(\"3.14159\") = %f\n", dnum);
/* strtol - 更安全的转换 */
char *end;
long val = strtol("12345abc", &end, 10);
printf("\nstrtol(\"12345abc\") = %ld\n", val);
printf("未转换部分: %s\n", end);
/* 不同进制转换 */
val = strtol("FF", NULL, 16); /* 十六进制 */
printf("strtol(\"FF\", 16) = %ld\n", val);
val = strtol("77", NULL, 8); /* 八进制 */
printf("strtol(\"77\", 8) = %ld\n", val);
/* strtod - 字符串转double */
double d = strtod("3.14abc", &end);
printf("\nstrtod(\"3.14abc\") = %f\n", d);
printf("未转换部分: %s\n", end);
return 0;
}字符处理函数
c
/*
* 字符处理函数(ctype.h)
*/
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char ch;
printf("=== 字符分类函数 ===\n");
/* isalpha - 是否是字母 */
printf("isalpha('A'): %d\n", isalpha('A')); /* 非0(真) */
printf("isalpha('1'): %d\n", isalpha('1')); /* 0(假) */
/* isdigit - 是否是数字 */
printf("isdigit('5'): %d\n", isdigit('5'));
/* isalnum - 是否是字母或数字 */
printf("isalnum('A'): %d\n", isalnum('A'));
printf("isalnum('5'): %d\n", isalnum('5'));
/* islower - 是否是小写字母 */
printf("islower('a'): %d\n", islower('a'));
/* isupper - 是否是大写字母 */
printf("isupper('A'): %d\n", isupper('A'));
/* isspace - 是否是空白字符 */
printf("isspace(' '): %d\n", isspace(' '));
printf("isspace('\\n'): %d\n", isspace('\n'));
/* ispunct - 是否是标点符号 */
printf("ispunct('.'): %d\n", ispunct('.'));
/* iscntrl - 是否是控制字符 */
printf("iscntrl('\\n'): %d\n", iscntrl('\n'));
/* isxdigit - 是否是十六进制数字 */
printf("isxdigit('F'): %d\n", isxdigit('F'));
printf("\n=== 字符转换函数 ===\n");
/* tolower - 转小写 */
printf("tolower('A') = %c\n", tolower('A'));
/* toupper - 转大写 */
printf("toupper('a') = %c\n", toupper('a'));
/* 实际应用:统计字符串中的字符类型 */
char str[] = "Hello World 123!";
int letters = 0, digits = 0, spaces = 0, others = 0;
for (int i = 0; str[i] != '\0'; i++) {
if (isalpha(str[i])) {
letters++;
} else if (isdigit(str[i])) {
digits++;
} else if (isspace(str[i])) {
spaces++;
} else {
others++;
}
}
printf("\n字符串 \"%s\" 中:\n", str);
printf("字母: %d, 数字: %d, 空格: %d, 其他: %d\n",
letters, digits, spaces, others);
return 0;
}格式化字符串
c
/*
* 格式化字符串函数
*/
#include <stdio.h>
int main(void)
{
char buffer[100];
int num = 42;
float pi = 3.14159;
/* sprintf - 格式化输出到字符串 */
sprintf(buffer, "数字: %d, 圆周率: %.2f", num, pi);
printf("sprintf结果: %s\n", buffer);
/* snprintf - 限制输出长度(更安全) */
snprintf(buffer, 10, "很长的字符串会被截断");
printf("snprintf结果: %s\n", buffer);
/* sscanf - 从字符串读取格式化输入 */
char input[] = "姓名:张三 年龄:25";
char name[20];
int age;
sscanf(input, "姓名:%s 年龄:%d", name, &age);
printf("\nsscanf解析:\n");
printf("姓名: %s\n", name);
printf("年龄: %d\n", age);
/* 解析日期 */
char date[] = "2024-01-15";
int year, month, day;
sscanf(date, "%d-%d-%d", &year, &month, &day);
printf("\n解析日期: %d年%d月%d日\n", year, month, day);
/* 解析IP地址 */
char ip[] = "192.168.1.1";
int a, b, c, d;
sscanf(ip, "%d.%d.%d.%d", &a, &b, &c, &d);
printf("IP地址: %d.%d.%d.%d\n", a, b, c, d);
return 0;
}字符串应用实例
字符串反转
c
/*
* 字符串反转
*/
#include <stdio.h>
#include <string.h>
/* 反转字符串 */
void reverse(char *str)
{
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
char temp = str[i];
str[i] = str[len - 1 - i];
str[len - 1 - i] = temp;
}
}
/* 使用指针反转 */
void reverse_ptr(char *str)
{
char *start = str;
char *end = str + strlen(str) - 1;
while (start < end) {
char temp = *start;
*start = *end;
*end = temp;
start++;
end--;
}
}
int main(void)
{
char str1[] = "Hello";
char str2[] = "World";
printf("原字符串: %s\n", str1);
reverse(str1);
printf("反转后: %s\n", str1);
printf("\n原字符串: %s\n", str2);
reverse_ptr(str2);
printf("反转后: %s\n", str2);
return 0;
}判断回文
c
/*
* 判断回文字符串
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/* 判断是否是回文 */
int is_palindrome(const char *str)
{
int len = strlen(str);
for (int i = 0; i < len / 2; i++) {
if (str[i] != str[len - 1 - i]) {
return 0; /* 不是回文 */
}
}
return 1; /* 是回文 */
}
/* 忽略大小写和空格判断回文 */
int is_palindrome_ignore(const char *str)
{
char filtered[100];
int j = 0;
/* 过滤非字母字符并转小写 */
for (int i = 0; str[i]; i++) {
if (isalpha(str[i])) {
filtered[j++] = tolower(str[i]);
}
}
filtered[j] = '\0';
return is_palindrome(filtered);
}
int main(void)
{
char str[] = "上海自来水来自海上";
printf("\"%s\" 是回文: %s\n", str,
is_palindrome(str) ? "是" : "否");
char str2[] = "A man a plan a canal Panama";
printf("\"%s\" 是回文(忽略大小写和空格): %s\n", str2,
is_palindrome_ignore(str2) ? "是" : "否");
return 0;
}小结
本章学习了:
- 字符串定义:字符数组、字符指针、字符串常量
- 字符串输入输出:scanf、fgets、puts、fputs
- 字符串函数:strlen、strcpy、strcat、strcmp、strstr等
- 字符处理函数:isalpha、isdigit、toupper、tolower等
- 格式化字符串:sprintf、snprintf、sscanf
- 字符串应用:反转、回文判断
下一章,我们将学习结构体,了解C语言结构体的定义和使用。
