每日一个C语言知识:C 字符串

C语言字符串详解

1. 什么是字符串?

在C语言中,字符串是以null字符(`'\0')结尾的字符数组。字符串不是C语言的基本数据类型,而是通过字符数组来实现的。

字符串的特点

  • 以null字符'\0'结尾
  • 存储在字符数组中
  • 可以使用字符串字面量初始化
  • 有一系列标准库函数用于处理

2. 字符串的基本概念

C语言字符串 字符串声明 字符串输入输出 字符串函数 字符串操作 动态字符串 字符数组 字符串字面量 printf/scanf gets/puts fgets/fputs strlen/strcpy strcat/strcmp strchr/strstr 遍历 修改 搜索 malloc/free 动态分配


3. 字符串的声明和初始化

基本字符串操作
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    printf("=== 字符串声明和初始化 ===\n");
    
    // 方式1:字符数组(不是字符串,因为没有null终止符)
    char arr1[] = {'H', 'e', 'l', 'l', 'o'};
    
    // 方式2:字符串(以null字符'\0'结尾)
    char arr2[] = "Hello";  // 自动添加'\0'
    
    // 方式3:指定大小的字符数组
    char arr3[10] = "Hello";
    
    // 方式4:逐个初始化
    char arr4[6];
    arr4[0] = 'H';
    arr4[1] = 'e';
    arr4[2] = 'l';
    arr4[3] = 'l';
    arr4[4] = 'o';
    arr4[5] = '\0';  // 重要:必须添加null终止符
    
    // 方式5:字符指针指向字符串字面量
    char *str_ptr = "Hello World";
    
    printf("arr1 (字符数组): ");
    for (int i = 0; i < 5; i++) {
        printf("%c", arr1[i]);
    }
    printf("\n");
    
    printf("arr2 (字符串): %s\n", arr2);
    printf("arr3: %s\n", arr3);
    printf("arr4: %s\n", arr4);
    printf("str_ptr: %s\n", str_ptr);
    
    // 字符串长度 vs 数组大小
    printf("arr2字符串长度: %lu\n", strlen(arr2));
    printf("arr2数组大小: %lu\n", sizeof(arr2));  // 包括'\0'
    
    // 显示字符串内容(包括null字符)
    printf("arr2详细内容: ");
    for (int i = 0; i <= strlen(arr2); i++) {
        if (arr2[i] == '\0') {
            printf("'\\0' ");
        } else {
            printf("'%c' ", arr2[i]);
        }
    }
    printf("\n");
    
    return 0;
}
字符串字面量 vs 字符数组
c 复制代码
#include <stdio.h>

int main() {
    printf("=== 字符串字面量 vs 字符数组 ===\n");
    
    // 字符串字面量(存储在只读内存)
    char *literal1 = "Hello";
    char *literal2 = "Hello";
    
    // 字符数组(存储在可写内存)
    char array1[] = "Hello";
    char array2[] = "Hello";
    
    printf("字符串字面量:\n");
    printf("literal1: %s (地址: %p)\n", literal1, literal1);
    printf("literal2: %s (地址: %p)\n", literal2, literal2);
    printf("字面量地址相同吗? %s\n", literal1 == literal2 ? "是" : "否");
    
    printf("\n字符数组:\n");
    printf("array1: %s (地址: %p)\n", array1, array1);
    printf("array2: %s (地址: %p)\n", array2, array2);
    printf("数组地址相同吗? %s\n", array1 == array2 ? "是" : "否");
    
    // 修改尝试
    array1[0] = 'h';  // ✅ 可以修改
    printf("修改后array1: %s\n", array1);
    
    // literal1[0] = 'h';  // ❌ 运行时错误:尝试修改只读内存
    
    return 0;
}

4. 字符串输入输出

基本输入输出函数
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    char name[50];
    char sentence[100];
    
    printf("=== 字符串输入输出 ===\n");
    
    // 使用scanf输入字符串(遇到空格停止)
    printf("请输入你的名字(不要有空格): ");
    scanf("%s", name);
    printf("你好, %s!\n", name);
    
    // 清除输入缓冲区
    while (getchar() != '\n');
    
    // 使用fgets输入包含空格的字符串
    printf("请输入一句话: ");
    fgets(sentence, sizeof(sentence), stdin);
    
    // 移除fgets读取的换行符
    size_t len = strlen(sentence);
    if (len > 0 && sentence[len - 1] == '\n') {
        sentence[len - 1] = '\0';
    }
    
    printf("你输入的是: %s\n", sentence);
    
    // 使用puts输出(自动添加换行)
    printf("使用puts输出: ");
    puts(sentence);
    
    // 使用printf输出
    printf("使用printf输出: %s\n", sentence);
    
    return 0;
}
安全的字符串输入
c 复制代码
#include <stdio.h>
#include <string.h>
#include <ctype.h>

// 安全的字符串输入函数
void safeInput(char *buffer, int size, const char *prompt) {
    printf("%s", prompt);
    
    if (fgets(buffer, size, stdin) != NULL) {
        // 移除换行符
        size_t len = strlen(buffer);
        if (len > 0 && buffer[len - 1] == '\n') {
            buffer[len - 1] = '\0';
        } else {
            // 清除输入缓冲区剩余字符
            int c;
            while ((c = getchar()) != '\n' && c != EOF);
        }
    }
}

// 去除字符串两端的空格
void trimString(char *str) {
    char *start = str;
    char *end = str + strlen(str) - 1;
    
    // 去除开头空格
    while (isspace(*start)) start++;
    
    // 去除结尾空格
    while (end > start && isspace(*end)) end--;
    
    // 移动字符串
    memmove(str, start, end - start + 1);
    str[end - start + 1] = '\0';
}

int main() {
    char name[50];
    char email[100];
    
    printf("=== 安全的字符串输入 ===\n");
    
    // 使用安全输入函数
    safeInput(name, sizeof(name), "请输入你的全名: ");
    safeInput(email, sizeof(email), "请输入你的邮箱: ");
    
    printf("\n输入验证:\n");
    printf("姓名: '%s'\n", name);
    printf("邮箱: '%s'\n", email);
    
    // 测试去除空格
    char test_string[] = "   前后有空格的字 符串   ";
    printf("\n去除空格测试:\n");
    printf("原始: '%s'\n", test_string);
    trimString(test_string);
    printf("去除后: '%s'\n", test_string);
    
    return 0;
}

5. 字符串处理函数

C语言提供了丰富的字符串处理函数,这些函数在string.h头文件中声明。

基本字符串函数
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    printf("=== 基本字符串函数 ===\n");
    
    char str1[50] = "Hello";
    char str2[50] = "World";
    char str3[100];
    char str4[50];
    
    // strlen - 字符串长度
    printf("str1长度: %lu\n", strlen(str1));
    
    // strcpy - 字符串复制
    strcpy(str3, str1);
    printf("复制后str3: %s\n", str3);
    
    // strcat - 字符串连接
    strcat(str3, " ");
    strcat(str3, str2);
    printf("连接后str3: %s\n", str3);
    
    // strcmp - 字符串比较
    printf("str1和str2比较: %d\n", strcmp(str1, str2));
    printf("str1和\"Hello\"比较: %d\n", strcmp(str1, "Hello"));
    
    // strncpy - 安全复制
    strncpy(str4, str3, sizeof(str4) - 1);
    str4[sizeof(str4) - 1] = '\0';  // 确保null终止
    printf("安全复制str4: %s\n", str4);
    
    // strncat - 安全连接
    char str5[20] = "Hello";
    strncat(str5, " World!!!", sizeof(str5) - strlen(str5) - 1);
    printf("安全连接str5: %s\n", str5);
    
    return 0;
}
字符串搜索函数
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    printf("=== 字符串搜索函数 ===\n");
    
    char text[] = "Hello World! Welcome to C programming.";
    char *result;
    
    printf("原始文本: %s\n", text);
    
    // strchr - 查找字符第一次出现
    result = strchr(text, 'W');
    if (result != NULL) {
        printf("找到'W': %s\n", result);
    }
    
    // strrchr - 查找字符最后一次出现
    result = strrchr(text, 'o');
    if (result != NULL) {
        printf("最后一个'o': %s\n", result);
    }
    
    // strstr - 查找子字符串
    result = strstr(text, "Welcome");
    if (result != NULL) {
        printf("找到'Welcome': %s\n", result);
    }
    
    // strpbrk - 查找任何指定字符的第一次出现
    result = strpbrk(text, "aeiou");
    if (result != NULL) {
        printf("第一个元音字母: %c (在: %s)\n", *result, result);
    }
    
    // strspn - 查找只包含指定字符的初始段长度
    char digits[] = "12345abc";
    size_t span = strspn(digits, "0123456789");
    printf("'%s'中数字前缀长度: %lu\n", digits, span);
    
    // strcspn - 查找不包含指定字符的初始段长度
    span = strcspn(text, " ,.!");
    printf("第一个分隔符前长度: %lu\n", span);
    
    return 0;
}
字符串分割函数
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    printf("=== 字符串分割函数 ===\n");
    
    char csv_data[] = "John,25,Engineer,New York";
    char path[] = "/home/user/documents/file.txt";
    char sentence[] = "This is a sample sentence with multiple words";
    
    printf("CSV数据: %s\n", csv_data);
    printf("路径: %s\n", path);
    printf("句子: %s\n", sentence);
    
    // 使用strtok分割字符串
    printf("\n分割CSV数据:\n");
    char *token = strtok(csv_data, ",");
    int field_count = 0;
    
    while (token != NULL) {
        printf("字段 %d: %s\n", ++field_count, token);
        token = strtok(NULL, ",");
    }
    
    // 分割路径
    printf("\n分割路径:\n");
    char path_copy[100];
    strcpy(path_copy, path);
    
    token = strtok(path_copy, "/");
    while (token != NULL) {
        printf("路径组件: %s\n", token);
        token = strtok(NULL, "/");
    }
    
    // 分割句子为单词
    printf("\n分割句子为单词:\n");
    char sentence_copy[100];
    strcpy(sentence_copy, sentence);
    
    token = strtok(sentence_copy, " ");
    int word_count = 0;
    
    while (token != NULL) {
        printf("单词 %d: %s\n", ++word_count, token);
        token = strtok(NULL, " ");
    }
    
    return 0;
}

6. 自定义字符串函数

理解字符串函数的最好方式是自己实现它们。

自定义字符串函数实现
c 复制代码
#include <stdio.h>
#include <stddef.h>

// 自定义字符串长度函数
size_t myStrlen(const char *str) {
    const char *s = str;
    while (*s != '\0') {
        s++;
    }
    return s - str;
}

// 自定义字符串复制函数
char* myStrcpy(char *dest, const char *src) {
    char *start = dest;
    while (*src != '\0') {
        *dest = *src;
        dest++;
        src++;
    }
    *dest = '\0';
    return start;
}

// 自定义字符串连接函数
char* myStrcat(char *dest, const char *src) {
    char *start = dest;
    
    // 找到dest的结尾
    while (*dest != '\0') {
        dest++;
    }
    
    // 复制src到dest的结尾
    while (*src != '\0') {
        *dest = *src;
        dest++;
        src++;
    }
    *dest = '\0';
    
    return start;
}

// 自定义字符串比较函数
int myStrcmp(const char *str1, const char *str2) {
    while (*str1 && *str2 && *str1 == *str2) {
        str1++;
        str2++;
    }
    return *(unsigned char*)str1 - *(unsigned char*)str2;
}

// 自定义字符串反转函数
char* myStrrev(char *str) {
    if (str == NULL) return NULL;
    
    char *start = str;
    char *end = str;
    char temp;
    
    // 找到字符串结尾
    while (*end != '\0') {
        end++;
    }
    end--;  // 指向最后一个字符
    
    // 反转字符串
    while (start < end) {
        temp = *start;
        *start = *end;
        *end = temp;
        
        start++;
        end--;
    }
    
    return str;
}

// 自定义字符串查找函数
char* myStrchr(const char *str, int ch) {
    while (*str != '\0') {
        if (*str == ch) {
            return (char*)str;
        }
        str++;
    }
    return NULL;
}

int main() {
    printf("=== 自定义字符串函数 ===\n");
    
    char str1[50] = "Hello";
    char str2[50] = "World";
    char result[100];
    
    printf("myStrlen(\"%s\") = %lu\n", str1, myStrlen(str1));
    
    myStrcpy(result, str1);
    printf("myStrcpy: %s\n", result);
    
    myStrcat(result, " ");
    myStrcat(result, str2);
    printf("myStrcat: %s\n", result);
    
    printf("myStrcmp(\"%s\", \"%s\") = %d\n", str1, str2, myStrcmp(str1, str2));
    printf("myStrcmp(\"%s\", \"%s\") = %d\n", str1, "Hello", myStrcmp(str1, "Hello"));
    
    char rev_str[] = "Hello";
    printf("myStrrev(\"%s\") = %s\n", rev_str, myStrrev(rev_str));
    
    char *found = myStrchr("Hello World", 'W');
    if (found != NULL) {
        printf("myStrchr找到'W': %s\n", found);
    }
    
    return 0;
}

7. 字符串与数字转换

数字与字符串相互转换
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    printf("=== 字符串与数字转换 ===\n");
    
    // 字符串转整数
    char int_str[] = "12345";
    char float_str[] = "123.45";
    char hex_str[] = "1A3F";
    
    int int_val = atoi(int_str);
    long long_val = atol(int_str);
    double double_val = atof(float_str);
    
    printf("atoi(\"%s\") = %d\n", int_str, int_val);
    printf("atol(\"%s\") = %ld\n", int_str, long_val);
    printf("atof(\"%s\") = %.2f\n", float_str, double_val);
    
    // 使用strtol进行更安全的转换
    char *endptr;
    long safe_long = strtol(hex_str, &endptr, 16);  // 16进制
    printf("strtol(\"%s\", 16) = %ld\n", hex_str, safe_long);
    
    // 数字转字符串
    char buffer[50];
    int num = 12345;
    double pi = 3.14159;
    
    sprintf(buffer, "整数: %d", num);
    printf("sprintf: %s\n", buffer);
    
    sprintf(buffer, "浮点数: %.2f", pi);
    printf("sprintf: %s\n", buffer);
    
    // 安全的数字转字符串(snprintf)
    snprintf(buffer, sizeof(buffer), "格式化: %d, %.2f", num, pi);
    printf("snprintf: %s\n", buffer);
    
    return 0;
}
高级数字转换
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>

// 安全的字符串转整数函数
int safeStringToInt(const char *str, int *result) {
    if (str == NULL || *str == '\0') {
        return 0;  // 失败
    }
    
    char *endptr;
    errno = 0;  // 清除错误
    long val = strtol(str, &endptr, 10);
    
    // 检查错误
    if (errno == ERANGE || val > INT_MAX || val < INT_MIN) {
        return 0;  // 溢出
    }
    
    // 检查是否整个字符串都被转换
    if (*endptr != '\0') {
        return 0;  // 无效字符
    }
    
    *result = (int)val;
    return 1;  // 成功
}

// 安全的字符串转浮点数函数
int safeStringToDouble(const char *str, double *result) {
    if (str == NULL || *str == '\0') {
        return 0;
    }
    
    char *endptr;
    errno = 0;
    double val = strtod(str, &endptr);
    
    if (errno == ERANGE) {
        return 0;  // 溢出
    }
    
    if (*endptr != '\0') {
        return 0;  // 无效字符
    }
    
    *result = val;
    return 1;
}

int main() {
    printf("=== 安全的数字转换 ===\n");
    
    char valid_int[] = "12345";
    char invalid_int[] = "123abc";
    char overflow_int[] = "999999999999999";
    char valid_double[] = "123.456";
    char invalid_double[] = "123.45.6";
    
    int int_result;
    double double_result;
    
    // 测试有效的整数转换
    if (safeStringToInt(valid_int, &int_result)) {
        printf("成功转换整数: %d\n", int_result);
    } else {
        printf("整数转换失败: %s\n", valid_int);
    }
    
    // 测试无效的整数转换
    if (safeStringToInt(invalid_int, &int_result)) {
        printf("成功转换整数: %d\n", int_result);
    } else {
        printf("整数转换失败: %s\n", invalid_int);
    }
    
    // 测试溢出的整数转换
    if (safeStringToInt(overflow_int, &int_result)) {
        printf("成功转换整数: %d\n", int_result);
    } else {
        printf("整数转换失败(溢出): %s\n", overflow_int);
    }
    
    // 测试有效的浮点数转换
    if (safeStringToDouble(valid_double, &double_result)) {
        printf("成功转换浮点数: %.3f\n", double_result);
    } else {
        printf("浮点数转换失败: %s\n", valid_double);
    }
    
    // 测试无效的浮点数转换
    if (safeStringToDouble(invalid_double, &double_result)) {
        printf("成功转换浮点数: %.3f\n", double_result);
    } else {
        printf("浮点数转换失败: %s\n", invalid_double);
    }
    
    return 0;
}

8. 动态字符串

动态字符串操作
c 复制代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

// 动态字符串结构
typedef struct {
    char *data;
    size_t length;
    size_t capacity;
} DynamicString;

// 创建动态字符串
DynamicString* createDynamicString(size_t initial_capacity) {
    DynamicString *str = malloc(sizeof(DynamicString));
    if (str == NULL) return NULL;
    
    str->data = malloc(initial_capacity);
    if (str->data == NULL) {
        free(str);
        return NULL;
    }
    
    str->data[0] = '\0';
    str->length = 0;
    str->capacity = initial_capacity;
    
    return str;
}

// 追加字符串到动态字符串
int appendString(DynamicString *str, const char *append) {
    size_t append_len = strlen(append);
    size_t new_length = str->length + append_len;
    
    // 检查是否需要扩容
    if (new_length + 1 > str->capacity) {
        size_t new_capacity = str->capacity * 2;
        while (new_capacity <= new_length + 1) {
            new_capacity *= 2;
        }
        
        char *new_data = realloc(str->data, new_capacity);
        if (new_data == NULL) {
            return 0;  // 失败
        }
        
        str->data = new_data;
        str->capacity = new_capacity;
    }
    
    // 追加字符串
    strcpy(str->data + str->length, append);
    str->length = new_length;
    
    return 1;  // 成功
}

// 获取C风格字符串
const char* getCString(const DynamicString *str) {
    return str->data;
}

// 释放动态字符串
void freeDynamicString(DynamicString *str) {
    if (str != NULL) {
        free(str->data);
        free(str);
    }
}

// 清空动态字符串
void clearDynamicString(DynamicString *str) {
    str->data[0] = '\0';
    str->length = 0;
}

int main() {
    printf("=== 动态字符串操作 ===\n");
    
    // 创建动态字符串
    DynamicString *dyn_str = createDynamicString(16);
    if (dyn_str == NULL) {
        printf("创建动态字符串失败!\n");
        return 1;
    }
    
    printf("初始状态: 长度=%lu, 容量=%lu\n", 
           dyn_str->length, dyn_str->capacity);
    
    // 追加多个字符串
    appendString(dyn_str, "Hello");
    appendString(dyn_str, " ");
    appendString(dyn_str, "World!");
    appendString(dyn_str, " This is a dynamic string example.");
    
    printf("追加后: 长度=%lu, 容量=%lu\n", 
           dyn_str->length, dyn_str->capacity);
    printf("内容: %s\n", getCString(dyn_str));
    
    // 清空并重新使用
    clearDynamicString(dyn_str);
    appendString(dyn_str, "重新开始!");
    printf("清空后: %s\n", getCString(dyn_str));
    
    // 释放内存
    freeDynamicString(dyn_str);
    
    return 0;
}

9. 实际应用示例

示例1:简单的文本分析器
c 复制代码
#include <stdio.h>
#include <string.h>
#include <ctype.h>

// 文本分析结构
typedef struct {
    int char_count;
    int word_count;
    int line_count;
    int sentence_count;
} TextStats;

// 分析文本
TextStats analyzeText(const char *text) {
    TextStats stats = {0, 0, 0, 0};
    int in_word = 0;
    
    for (int i = 0; text[i] != '\0'; i++) {
        // 字符计数
        stats.char_count++;
        
        // 行计数
        if (text[i] == '\n') {
            stats.line_count++;
        }
        
        // 句子计数
        if (text[i] == '.' || text[i] == '!' || text[i] == '?') {
            stats.sentence_count++;
        }
        
        // 单词计数
        if (isspace(text[i])) {
            in_word = 0;
        } else if (!in_word) {
            in_word = 1;
            stats.word_count++;
        }
    }
    
    // 如果文本不以换行符结束,也要计数最后一行
    if (stats.char_count > 0) {
        stats.line_count++;
    }
    
    return stats;
}

// 查找最长的单词
void findLongestWord(const char *text, char *longest_word, int max_length) {
    char current_word[100];
    char longest[100] = "";
    int word_index = 0;
    int in_word = 0;
    
    for (int i = 0; text[i] != '\0'; i++) {
        if (isspace(text[i]) || ispunct(text[i])) {
            if (in_word) {
                current_word[word_index] = '\0';
                if (strlen(current_word) > strlen(longest)) {
                    strcpy(longest, current_word);
                }
                word_index = 0;
                in_word = 0;
            }
        } else {
            current_word[word_index++] = text[i];
            in_word = 1;
        }
    }
    
    // 处理最后一个单词
    if (in_word) {
        current_word[word_index] = '\0';
        if (strlen(current_word) > strlen(longest)) {
            strcpy(longest, current_word);
        }
    }
    
    strncpy(longest_word, longest, max_length - 1);
    longest_word[max_length - 1] = '\0';
}

int main() {
    printf("=== 简单文本分析器 ===\n");
    
    char sample_text[] = "Hello world! This is a sample text.\n"
                        "It contains multiple lines and sentences.\n"
                        "We will analyze this text for statistics.";
    
    printf("分析文本:\n%s\n\n", sample_text);
    
    // 分析文本
    TextStats stats = analyzeText(sample_text);
    
    printf("文本统计:\n");
    printf("字符数: %d\n", stats.char_count);
    printf("单词数: %d\n", stats.word_count);
    printf("行数: %d\n", stats.line_count);
    printf("句子数: %d\n", stats.sentence_count);
    
    // 查找最长单词
    char longest_word[100];
    findLongestWord(sample_text, longest_word, sizeof(longest_word));
    printf("最长单词: %s (长度: %lu)\n", longest_word, strlen(longest_word));
    
    return 0;
}
示例2:简单的命令行解析器
c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAX_ARGS 10
#define MAX_ARG_LENGTH 50

// 命令结构
typedef struct {
    char *name;
    void (*execute)(int argc, char *argv[]);
    const char *description;
} Command;

// 各种命令函数
void cmd_help(int argc, char *argv[]) {
    printf("可用命令:\n");
    printf("help - 显示帮助信息\n");
    printf("echo - 回显参数\n");
    printf("calc - 简单计算器\n");
    printf("exit - 退出程序\n");
}

void cmd_echo(int argc, char *argv[]) {
    printf("回显: ");
    for (int i = 1; i < argc; i++) {
        printf("%s ", argv[i]);
    }
    printf("\n");
}

void cmd_calc(int argc, char *argv[]) {
    if (argc != 4) {
        printf("用法: calc <数字1> <操作符> <数字2>\n");
        return;
    }
    
    double num1 = atof(argv[1]);
    double num2 = atof(argv[2]);
    char op = argv[3][0];
    double result;
    
    switch (op) {
        case '+': result = num1 + num2; break;
        case '-': result = num1 - num2; break;
        case '*': result = num1 * num2; break;
        case '/': 
            if (num2 == 0) {
                printf("错误:除数不能为零\n");
                return;
            }
            result = num1 / num2; 
            break;
        default:
            printf("错误:不支持的操作符 '%c'\n", op);
            return;
    }
    
    printf("计算结果: %.2f %c %.2f = %.2f\n", num1, op, num2, result);
}

void cmd_exit(int argc, char *argv[]) {
    printf("再见!\n");
    exit(0);
}

// 命令表
Command commands[] = {
    {"help", cmd_help, "显示帮助信息"},
    {"echo", cmd_echo, "回显参数"},
    {"calc", cmd_calc, "简单计算器"},
    {"exit", cmd_exit, "退出程序"}
};

int command_count = sizeof(commands) / sizeof(commands[0]);

// 解析命令行输入
void parseCommand(char *input) {
    char *args[MAX_ARGS];
    int argc = 0;
    
    // 使用strtok分割命令行
    char *token = strtok(input, " \t\n");
    while (token != NULL && argc < MAX_ARGS) {
        args[argc++] = token;
        token = strtok(NULL, " \t\n");
    }
    
    if (argc == 0) {
        return;  // 空命令
    }
    
    // 查找并执行命令
    for (int i = 0; i < command_count; i++) {
        if (strcmp(args[0], commands[i].name) == 0) {
            commands[i].execute(argc, args);
            return;
        }
    }
    
    printf("未知命令: %s\n", args[0]);
    printf("输入 'help' 查看可用命令\n");
}

int main() {
    printf("=== 简单命令行解析器 ===\n");
    printf("输入 'help' 查看可用命令\n\n");
    
    char input[256];
    
    while (1) {
        printf("> ");
        
        if (fgets(input, sizeof(input), stdin) == NULL) {
            break;
        }
        
        // 移除换行符
        size_t len = strlen(input);
        if (len > 0 && input[len - 1] == '\n') {
            input[len - 1] = '\0';
        }
        
        // 解析并执行命令
        parseCommand(input);
    }
    
    return 0;
}

10. 字符串常见错误和最佳实践

常见错误示例
c 复制代码
#include <stdio.h>
#include <string.h>

int main() {
    printf("=== 字符串常见错误 ===\n");
    
    // ❌ 错误1:字符串未正确终止
    /*
    char str1[5] = {'H', 'e', 'l', 'l', 'o'};  // 缺少'\0'
    printf("%s\n", str1);  // 未定义行为
    */
    
    // ✅ 正确:确保字符串以'\0'结尾
    char str1_correct[6] = {'H', 'e', 'l', 'l', 'o', '\0'};
    printf("正确终止: %s\n", str1_correct);
    
    // ❌ 错误2:缓冲区溢出
    /*
    char str2[10] = "Hello";
    strcat(str2, " World! This is too long!");  // 缓冲区溢出
    */
    
    // ✅ 正确:使用安全的字符串函数
    char str2_correct[20] = "Hello";
    strncat(str2_correct, " World!", sizeof(str2_correct) - strlen(str2_correct) - 1);
    printf("安全连接: %s\n", str2_correct);
    
    // ❌ 错误3:修改字符串字面量
    /*
    char *str3 = "Hello";
    str3[0] = 'h';  // 运行时错误
    */
    
    // ✅ 正确:使用字符数组或动态分配
    char str3_correct[] = "Hello";
    str3_correct[0] = 'h';
    printf("可修改字符串: %s\n", str3_correct);
    
    // ❌ 错误4:未检查字符串函数返回值
    /*
    char src[10] = "Too long!";
    char dest[5];
    strcpy(dest, src);  // 缓冲区溢出
    */
    
    // ✅ 正确:检查边界和使用安全函数
    char src_correct[10] = "Hello";
    char dest_correct[10];
    if (strlen(src_correct) < sizeof(dest_correct)) {
        strcpy(dest_correct, src_correct);
        printf("安全复制: %s\n", dest_correct);
    } else {
        printf("错误:源字符串太长\n");
    }
    
    return 0;
}
最佳实践
c 复制代码
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// ✅ 好的实践:使用安全的字符串函数
void safeStringCopy(char *dest, size_t dest_size, const char *src) {
    if (dest == NULL || src == NULL || dest_size == 0) {
        return;
    }
    
    // 使用strncpy并确保null终止
    strncpy(dest, src, dest_size - 1);
    dest[dest_size - 1] = '\0';
}

// ✅ 好的实践:检查字符串长度
int isValidString(const char *str, size_t max_length) {
    if (str == NULL) return 0;
    
    size_t len = strlen(str);
    return len > 0 && len < max_length;
}

// ✅ 好的实践:动态字符串构建
char* buildDynamicString(const char *part1, const char *part2) {
    if (part1 == NULL || part2 == NULL) {
        return NULL;
    }
    
    size_t len1 = strlen(part1);
    size_t len2 = strlen(part2);
    char *result = malloc(len1 + len2 + 1);
    
    if (result != NULL) {
        strcpy(result, part1);
        strcat(result, part2);
    }
    
    return result;
}

int main() {
    printf("=== 字符串最佳实践 ===\n");
    
    // 安全字符串复制
    char buffer[10];
    safeStringCopy(buffer, sizeof(buffer), "Hello World");
    printf("安全复制: '%s'\n", buffer);
    
    // 字符串验证
    printf("'Hello' 是有效字符串吗? %s\n", 
           isValidString("Hello", 10) ? "是" : "否");
    printf("NULL 是有效字符串吗? %s\n", 
           isValidString(NULL, 10) ? "是" : "否");
    
    // 动态字符串构建
    char *dynamic_str = buildDynamicString("Hello ", "World!");
    if (dynamic_str != NULL) {
        printf("动态构建: %s\n", dynamic_str);
        free(dynamic_str);
    }
    
    return 0;
}

相关推荐
0110_10247 小时前
tauri + rust的环境搭建---初始化以及构建
开发语言·后端·rust
会开花的二叉树7 小时前
C++微服务 UserServer 设计与实现
开发语言·c++·微服务
像风一样自由20207 小时前
Rust Tokio vs Go net/http:云原生与嵌入式生态选型指南
开发语言·golang·rust
DuHz7 小时前
C程序中的数组与指针共生关系
linux·c语言·开发语言·嵌入式硬件·算法
我星期八休息7 小时前
C++智能指针全面解析:原理、使用场景与最佳实践
java·大数据·开发语言·jvm·c++·人工智能·python
来生硬件工程师7 小时前
【STM32笔记】:P04 断言的使用
c语言·笔记·stm32·单片机·嵌入式硬件·硬件架构·硬件设计
大猫会长7 小时前
docker安装php+apache
java·开发语言
道之极万物灭7 小时前
Go小工具合集
开发语言·后端·golang
梵得儿SHI7 小时前
Java 反射机制深度剖析:性能与安全性的那些坑
java·开发语言·安全·反射·动态代理·性能·反射机制