📝 Strings字符串处理

String operations, file I/O, and memory safety掌握字符串操作、文件处理与内存安全

String Basics in CC语言字符串基础

A C string is a character array terminated by the null character '\0'. This sentinel is fundamental to C string handling. 在 C 语言中,字符串是以null 终止符('\0')结尾的字符数组。这是 C 字符串处理的核心特征。

String Memory Representation:字符串内存表示:
"Hello" 在内存中的表示:
+------+------+------+------+------+------+
|  'H' |  'e' |  'l' |  'l' |  'o' | '\0' |
+------+------+------+------+------+------+
  地址0   地址1   地址2   地址3   地址4   地址5
                
char str1[] = "Hello"; // 自动添加'\0',长度为6 char str2[6] = {'H', 'e', 'l', 'l', 'o', '\0'}; // 手动指定 char *str3 = "World"; // 字符串指针

⚠️ Common String Pitfalls常见字符串错误

  • Buffer overflow: string exceeds allocated size缓冲区溢出: 字符串长度超过分配空间
  • Missing terminator: forgetting '\\0' causes UB缺少终止符: 忘记添加'\\0'导致未定义行为
  • Wild pointer: using freed string memory野指针: 操作已经释放的字符串内存

String Length Clamping字符串长度限制

Clamping string length is a key Week 1 practice: safely truncate overly long strings. 字符串长度限制是 Week 1 的重要练习:需要安全地截断过长的字符串。

void clamp_string(char *string, int limit) { int length = 0; // 找到字符串的实际长度 while (string[length] != '\0') { length++; } // 如果字符串长度超过限制,截断它 if (length >= limit) { string[limit] = '\0'; // 在limit位置设置终止符 } // 如果字符串已经短于limit,不需要做任何事 }

🎯 字符串限制实例

int main() { char text[] = "Hello, World!"; printf("原字符串: %s\n", text); clamp_string(text, 5); printf("限制后: %s\n", text); // 输出: Hello return 0; }

Filename Suffix Handling文件后缀处理

Handling filenames is a common string task; here we remove the file extension:处理文件名是字符串操作的常见应用,我们需要移除文件扩展名:

#include #include void remove_file_suffix(char *filename) { int length = strlen(filename); int dot_position = -1; // 从后往前查找最后一个点号 for (int i = length - 1; i >= 0; i--) { if (filename[i] == '.') { dot_position = i; break; } } // 如果找到点号且不是第一个字符,移除后缀 if (dot_position > 0) { filename[dot_position] = '\0'; } }

💡 字符串函数库

The C standard library offers many string functions:C标准库提供了丰富的字符串处理函数:

  • strlen(): get lengthstrlen(): 获取字符串长度
  • strcpy(): copy stringstrcpy(): 复制字符串
  • strcat(): concatenatestrcat(): 连接字符串
  • strcmp(): comparestrcmp(): 比较字符串
  • strchr(): find charstrchr(): 查找字符
  • strstr(): find substringstrstr(): 查找子串

String Concatenation字符串组合

Dynamically creating a new string is an important skill:动态创建新字符串是字符串处理的重要技能:

void strip_newline(char *sentence) { int length = strlen(sentence); if (length > 0 && sentence[length - 1] == '\n') { sentence[length - 1] = '\0'; } } char *combine_sentences(char *sentence1, char *sentence2) { // 移除换行符 strip_newline(sentence1); strip_newline(sentence2); // 计算新字符串长度 int len1 = strlen(sentence1); int len2 = strlen(sentence2); // 分配内存 (+1 for null terminator) char *combined = (char *)malloc(len1 + len2 + 1); if (combined == NULL) { return NULL; } // 复制并连接字符串 strcpy(combined, sentence1); strcat(combined, sentence2); return combined; }

⚠️ 内存安全

  • Always check malloc return value总是检查malloc的返回值
  • Ensure string ends with '\\0'确保字符串以'\\0'结尾
  • Avoid buffer overflows避免缓冲区溢出
  • Free dynamically allocated memory记得释放动态分配的内存

Safe String Input安全字符串输入

Use fgets to safely read input and avoid buffer overflows:使用fgets安全地读取用户输入,避免缓冲区溢出:

#define MAX_LENGTH 100 int main() { char filename[MAX_LENGTH]; printf("输入文件名: "); if (fgets(filename, MAX_LENGTH, stdin) != NULL) { // 移除换行符 strip_newline(filename); printf("处理后的文件名: %s\n", filename); remove_file_suffix(filename); printf("无后缀文件名: %s\n", filename); } return 0; }

💡 fgets vs scanf

  • fgets(): safe, bounded readfgets(): 安全,可以指定最大读取长度
  • scanf(): unsafe, may overflowscanf(): 不安全,容易导致缓冲区溢出
  • gets(): dangerous, deprecatedgets(): 危险,已废弃,绝对不要使用

🎯 Practice & Consolidation练习与巩固

练习1: 字符串反转

Write a function to reverse a string in place:编写一个函数,将字符串原地反转:

void reverse_string(char *str) { int length = strlen(str); // 使用双指针法反转字符串 // 左指针从开头,右指针从结尾 // 交换字符并向中间移动 }

Answer:答案:

void reverse_string(char *str) { int length = strlen(str); for (int i = 0; i < length / 2; i++) { char temp = str[i]; str[i] = str[length - 1 - i]; str[length - 1 - i] = temp; } }

练习2: 字符串统计

Write a function to count the number of words in a string:编写函数统计字符串中的单词数量:

int count_words(char *str) { int count = 0; int in_word = 0; // 是否在单词中 // 遍历字符串,统计单词数量 // 单词定义:由空格分隔的连续字符 return count; }

Answer:答案:

int count_words(char *str) { int count = 0; int in_word = 0; while (*str) { if (*str == ' ' || *str == '\t' || *str == '\n') { in_word = 0; } else if (!in_word) { in_word = 1; count++; } str++; } return count; }

Summary总结

String handling is a fundamental C skill. In this module, you learned:字符串处理是C语言编程的基础技能,本周我们学习了:

🚀 下一步学习

After mastering strings, you’ve covered most of Week 1. Next, learn arrays to complete the skill set.掌握了字符串处理后,我们已经完成了Week 1的大部分内容。接下来可以学习数组操作来完善技能体系。