C语言练习之字符串

1,有关字符串的函数介绍

 字符串长度获取
strlen(const char *str)`:获取字符串的长度,不包括结束字符'\0'。

字符串复制
 `strcpy(char *dest, const char *src)`:将源字符串`src`复制到目标字符串`dest`。
 `strncpy(char *dest, const char *src, size_t n)`:复制`src`的前`n`个字符到`dest`。

字符串比较
`strcmp(const char *str1, const char *str2)`:比较两个字符串的大小。
`strncmp(const char *str1, const char *str2, size_t n)`:比较两个字符串的前`n`个字符。

字符串查找
`strchr(const char *str, int c)`:查找字符串`str`中第一次出现字符`c`的位置。
`strrchr(const char *str, int c)`:查找字符串`str`中最后一次出现字符`c`的位置。

字符串分割
`strtok(char *str, const char *delim)`:使用指定的分隔符`delim`对字符串`str`进行分割。

字符串替换
`strreplace(char *str, const char *old, const char *new)`:替换字符串`str`中的`old`为`new`。

 字符串格式化
- `printf(const char *format, ...)`和`fprintf(FILE *stream, const char *format, ...)`:格式化输出字符串。
- `scanf(const char *format, ...)`和`fscanf(FILE *stream, const char *format, ...)`:格式化输入字符串。

字符串转换
`strtol(const char *str, char **endptr, int base)`:将字符串`str`转换为长整型。
`strtoul(const char *str, char **endptr, int base)`:将字符串`str`转换为无符号长整型。
`strtod(const char *str, char **endptr)`:将字符串`str`转换为双精度浮点型。

以上函数都定义在`<string.h>`或`<stdio.h>`头文件中。在使用这些函数时,需要注意字符串的长度和边界,以防止缓冲区溢出等问题。

2,字符串逆序

2.1题目示例

/*
思路:该题比较简单,请参考代码
*/
void Reverse(char* str)
{
    char* left = str;
    char* right = str + strlen(str)-1;
    while(left < right)
    {
        char temp = *left;
        *left = *right;
        *right = temp;
        ++left;
        --right;
    }
}


int main()
{
    char str[] = "hello bit";
    //在这里完成下面函数,参数自己设计,要求:使用指针
    Reverse(str);
    return 0;
}


// 注意:如果是在线OJ时,必须要考虑循环输入,因为每个算法可能有多组测试用例进行验证,参考以下main函数写法,
int main()
{
    char str[101] = {0};
    while(gets(str))
    {
        Reverse(str);
        printf("%s\n", str);
        memset(str, 0, sizeof(str)/sizeof(str[0]));
    }
    return 0;

2.2 reverse()函数的解释

reverse()函数通常用于数据结构(如数组或列表)中的元素进行反转。具体来说,它可以将数组或列表 的前后元素互换,使得第一个元素变成最后一个元素,第二个元素变成倒数第二个元素,以此类推

3,字符串比较

在C语言中,你可以使用`strcmp()`函数来比较两个字符串。这个函数的原型如下:

int strcmp(const char *str1, const char *str2);

其中,`str1`和`str2`是要比较的两个字符串。这个函数会比较两个字符串的每个字符,按照ASCII码值进行比较。如果两个字符串完全相同,则返回0;如果`str1`的ASCII码值大于`str2`的,则返回正值;反之,如果`str1`的ASCII码值小于`str2`的,则返回负值。

以下是一个使用`strcmp()`函数的例子:

#include <stdio.h>
#include <string.h>

int main() {
    char *str1 = "Hello";
    char *str2 = "World";
    int result = strcmp(str1, str2);
    if(result == 0){
        printf("The strings are equal.\n");
    }else if(result < 0){
        printf("str1 is less than str2.\n");
    }else{
        printf("str1 is greater than str2.\n");
    }
    return 0;
}

在这个例子中,我们首先定义了两个字符串`str1`和`str2`,然后使用`strcmp()`函数比较它们。最后,根据比较结果打印相应的信息。

输出将会是:
result1: -1 (或者任何负数)

result2: 0

result3: 1 (或者任何正数)
需要注意的是,strcmp函数在比较时不会检查字符串是否以空字符('\0')结尾,因为它假设传入的都是合法的以空字符结尾的C字符串。如果字符串不是以空字符结尾,那么strcmp的行为是未定义的。

4,字符串替换

 在C语言中测试字符串的替换功能,你可以编写一个单元测试或者简单地调用替换函数并打印结果来验证其行为是否符合预期。以下是如何实现这一测试的步骤:

1. 实现一个字符串替换函数(如之前所述)。
2. 编写测试用例,包括正常情况和边界条件。
3. 调用替换函数,并检查返回的字符串是否正确。
4. 验证替换后的字符串长度和内容。

以下是一个测试字符串替换功能的示例:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

// 字符串替换函数
void replaceString(char* str, const char* search, const char* replacement) {
    char* src = str;
    size_t lenSearch = strlen(search);
    size_t lenReplacement = strlen(replacement);
    char* temp = NULL;
    size_t foundCount = 0;

    // 计算搜索字符串出现的次数
    while ((temp = strstr(src, search)) != NULL) {
        ++foundCount;
        src = temp + lenSearch;
    }

    // 如果没有找到要替换的子串,直接返回
    if (foundCount == 0) {
        return;
    }

    // 为新的字符串分配足够的空间
    char* newStr = (char*)malloc((strlen(str) + (lenReplacement - lenSearch) * foundCount + 1) * sizeof(char));
    if (newStr == NULL) {
        fprintf(stderr, "Memory allocation failed\n");
        exit(EXIT_FAILURE);
    }

    src = str;
    size_t offset = 0;

    // 进行替换操作
    while ((temp = strstr(src, search)) != NULL) {
        memcpy(newStr + offset, src, temp - src);
        memcpy(newStr + offset + (temp - src), replacement, lenReplacement);
        offset += (temp - src) + lenReplacement;
        src = temp + lenSearch;
    }
    memcpy(newStr + offset, src, strlen(src) + 1);

    // 替换完成后,释放原字符串空间并将新字符串赋值给原字符串指针
    free(str);
    strcpy(str, newStr);
    free(newStr);
}

// 主函数,包含测试用例
int main() {
    // 测试用例1: 替换字符串中的单词
    char str1[] = "Hello world, this is an example sentence.";
    const char* search1 = "example";
    const char* replacement1 = "test";
    
    printf("Test Case 1:\n");
    printf("Original String: %s\n", str1);
    replaceString(str1, search1, replacement1);
    printf("Replaced String: %s\n\n", str1);

    // 测试用例2: 不存在的搜索词
    char str2[] = "Hello world, this is a sentence.";
    const char* search2 = "not-found";
    const char* replacement2 = "found";
    
    printf("Test Case 2:\n");
    printf("Original String: %s\n", str2);
    replaceString(str2, search2, replacement2);
    printf("Replaced String: %s\n\n", str2);

    return 0;
}

在这个例子中,我们有两个测试用例。

第一个测试用例检查了一个已存在于原始字符串中的单词是否被正确替换。

第二个测试用例检查了当搜索的子串不存在时,原始字符串是否保持不变。

在每个测试用例中,我们都会打印原始字符串和替换后的字符串,以验证替换功能是否按预期工作。

4.1memcpy()函数的解释

`memcpy()`函数是C/C++编程中常用的内存拷贝函数,它的原型如下:

void *memcpy(void* dest, const void *src, size_t n);

其中,`dest`是指向目标内存空间的指针,`src`是指向源内存空间的指针,`n`是要拷贝的字节数。

`memcpy()`函数会将`src`指向的内存空间中的连续`n`个字节的数据复制到`dest`指向的内存空间中。

需要注意的是,`dest`和`src`所指的内存区域不能重叠,否则可能导致不可预期的结果。另外,`memcpy()`并不像`strcpy()`那样在遇到字符串结束符`\0`时停止复制,它会一直复制`n`个字节。

下面是一个简单的使用例子:

char a, b;
memcpy(b, a, sizeof(b));  // 将a数组的内容复制到b数组中

在这个例子中,`sizeof(b)`会计算出`b`数组的大小,然后`memcpy()`会从这个位置开始复制,直到复制完所有字节。

此外,`memcpy()`不仅可以用于数组,也可以用于任何可读写的内存空间。例如,如果你想从一个字符串中复制一部分内容到一个字符数组中,你可以这样做:

char* s = "Hello World";
char d;
memcpy(d, s + 12, 4);  // 从s的第12个字符开始复制4个字符

在这个例子中,`s + 12`指向的是字符串`s`的第12个字符,因此`memcpy()`会从这里开始复制4个字符到`d`数组中

5,字符串动态增长

5.1,用realloc()函数实现

 在C语言中,可以使用 `realloc()` 函数来实现字符串的动态大小增长。`realloc()` 函数允许你在运行时重新分配内存,这对于动态增加字符串大小非常有用。

以下是一个简单的示例,展示了如何使用 `realloc()` 来扩展字符串的大小:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char* str = malloc(sizeof(char) * 10); // 初始化字符串,长度为10
    strcpy(str, "Hello, World!"); // 将字符串复制到新分配的内存中

    // 使用realloc()函数扩展字符串大小
    str = realloc(str, sizeof(char) * 20); // 现在字符串的长度为20

    // 继续向字符串添加更多内容
    strcat(str, " This is an example of dynamic memory allocation and string growth in C language.");

    printf("Expanded String: %s\n", str);

    // 记得释放内存
    free(str);

    return 0;
}

在这个例子中,首先使用 `malloc()` 函数为字符串分配初始内存,然后将字符串复制到新分配的内存中。接下来,使用 `realloc()` 函数扩展字符串的大小,最后使用 `strcat()` 函数向字符串添加更多内容。

请注意,在使用 `realloc()` 函数后,原来的指针可能指向不同的内存地址,因此在使用 `realloc()` 之后,一定要将指针指向新的内存地址。此外,当不再需要使用动态分配的内存时,应使用 `free()` 函数释放这些内存。

在C语言中,除了使用 `realloc()` 函数,还有以下几种方法可以实现字符串的动态大小增长:

5.2. 使用 strcat()`函数

`strcat()` 函数可以将两个字符串连接起来,这可以用于在不使用 `realloc()` 的情况下增加字符串的大小。但是这种方法有一个限制,那就是你需要预先知道字符串的最大可能大小,并在初始化时分配足够的内存。

#include <stdio.h>
#include <string.h>

int main() {
    char str = "Hello";
    char newStr = " World";
    strcat(str, newStr);
    printf("%s\n", str);
    return 0;
}

在这个例子中,`str` 初始化为 "Hello",`newStr` 初始化为 " World"。`strcat(str, newStr)` 将 " World" 连接到 "Hello" 的末尾,然后打印出新的字符串。

5.3. 使用 `strncpy()` 函数

`strncpy()` 函数可以将源字符串的一部分复制到目标字符串中,并且可以指定复制的最大长度这可以用于在不使用 `realloc()` 的情况下增加字符串的大小。

#include <stdio.h>
#include <string.h>

int main() {
    char str = "Hello";
    char newStr = " World";
    strncpy(str + strlen(str), newStr, 10 - strlen(str));
    printf("%s\n", str);
    return 0;
}

在这个例子中,`strncpy(str + strlen(str), newStr, 10 - strlen(str))` 将 " World" 复制到 "Hello" 的末尾,然后打印出新的字符串。

这两种方法都有各自的优点和缺点。

使用 `strcat()` 或 `strncpy()` 不需要重新分配内存,但是它们假设你已经预先知道字符串的最大可能大小,并且在初始化时已经分配了足够的内存。而 `realloc()` 可以在运行时动态地增加内存,但是每次增加内存都需要重新分配内存,这可能比其他方法更慢。

6,字符串拼接

 在C语言中,字符串拼接通常涉及使用标准库函数`strcat`。这个函数定义在`<string.h>`头文件中。`strcat`函数将一个字符串(第二个参数)附加到另一个字符串的末尾。

以下是`strcat`函数的原型:

char *strcat(char *dest, const char *src);

这里,`dest`是目标字符串,它必须有足够的空间来存储结果字符串。`src`是源字符串,它的内容将被追加到`dest`的末尾。

使用`strcat`函数前,你需要确保目标字符串有足够的空间来存放两个字符串的组合。如果没有足够的空间,可能会发生缓冲区溢出,这是一种常见的安全漏洞。

下面是一个简单的示例,展示了如何使用`strcat`函数:

#include <stdio.h>
#include <string.h>

int main() {
    char str1[50] = "Hello"; // 目标字符串
    char str2[] = "World!";   // 源字符串

    // 确保str1有足够的空间来存放拼接后的字符串
    strcat(str1, str2);

    printf("拼接后的字符串: %s\n", str1);

    return 0;
}

在这个例子中,`str1`有50个字符的空间,所以可以安全地将`str2`的内容"World!"附加到其后。执行上述程序后,控制台会打印出:

拼接后的字符串: HelloWorld!

除了`strcat`之外,C语言还提供了其他用于字符串操作的函数,例如`strcpy`(复制字符串)、`strlen`(计算字符串长度)、`strncat`(安全版本的字符串拼接,允许指定最大长度)等。在使用这些函数时,始终要注意避免缓冲区溢出和其他潜在的安全问题。

7,字符串拆成字串

在C语言中,可以使用`strtok`函数将字符串分割成多个子串。`strtok`函数定义在`<string.h>`头文件中。

`strtok`函数的原型如下:

char *strtok(char *str, const char *delim);

其中,`str`是要被分割的字符串,`delim`是分隔符

`strtok`函数的工作原理是在`str`中查找`delim`中出现的任何字符,然后将这些字符替换为`\0`,从而将字符串分割成多个子串。

使用`strtok`函数的一般步骤如下:

1. 初始化`str`为待分割的字符串,`delim`为分隔符。
2. 调用`strtok`函数,它会返回第一个子串的指针。
3. 为了获取后续的子串,将`str`设置为`NULL`,这样`strtok`就会从上次停止的位置继续查找

以下是一个简单的示例,演示了如何使用`strtok`函数将字符串分割成多个子串:

#include <stdio.h>
#include <string.h>

int main() {
    char str[] = "Hello, World!";
    char *token;

    // 初始化str为待分割的字符串,delim为分隔符
    token = strtok(str, ",");

    // 获取第一个子串
    printf("%s\n", token);  // 输出 "Hello"

    // 获取后续的子串
    token = strtok(NULL, ",");
    printf("%s\n", token);  // 输出 "World"

    token = strtok(NULL, ",");
    printf("%s\n", token);  // 输出 "!"

    return 0;
}

在这个例子中,我们首先使用`strtok`函数获取第一个子串,然后将其余的子串全部获取出来。

需要注意的是,`strtok`函数会修改原字符串,将分隔符替换为`\0`,因此在使用完`strtok`函数后,原字符串可能无法再使用。另外,`strtok`函数每次调用都会返回一个新的子串,直到所有的子串都被获取为止。

8,字符串删除指定字符

8.1运用strcpy()函数

 在C语言中,要删除字符串中的指定字符,可以通过遍历字符串,并使用`strcpy`函数将不需要的字符之后的所有字符复制到当前位置来实现。

以下是一个示例函数,它接受一个字符串和要删除的字符作为参数,并返回修改后的字符串:

#include <stdio.h>
#include <string.h>

char* removeChar(char *str, char c) {
    char *dest = str;
    while (*str) {
        if (*str != c) {
            *dest++ = *str;
        }
        str++;
    }
    *dest = '\0'; // 确保新字符串以空字符结尾
    return str; // 返回修改后的字符串(即原字符串的下一位置)
}

int main() {
    char str[] = "Hello, World!";
    char c = 'o';
    
    printf("原始字符串: %s\n", str);
    removeChar(str, c);
    printf("删除字符 '%c' 后的字符串: %s\n", c, str);
    
    return 0;
}

这个函数会修改输入的字符串,因此如果你想保留原始字符串不变,应该先对其进行复制

例如:

char originalStr[] = "Hello, World!";
char modifiedStr[strlen(originalStr) + 1]; // 加1是为了空字符
strcpy(modifiedStr, originalStr);
removeChar(modifiedStr, 'o');
printf("删除字符 '%c' 后的字符串 (不影响原始): %s\n", 'o', modifiedStr);

注意:`removeChar`函数返回的是指向原字符串中第一个不需要删除的字符之后位置的指针。这意味着如果你想继续在原字符串上操作,你需要从这个位置开始。如果你想得到一个全新的字符串,那么你应该在调用`removeChar`函数后立即使用返回值。

8.2 使用`strstr`和`strncpy`函数

`strstr`函数用于在字符串中查找另一个字符串,而`strncpy`函数用于将字符串的一部分复制到另一个字符串中。结合这两个函数,你可以实现删除字符串中特定字符的功能。以下是一个示例:

#include <stdio.h>
#include <string.h>

void deleteChar(char *str, char c) {
    char *pos;
    while ((pos = strstr(str, &c)) != NULL) {
        strncpy(pos, pos + 1, strlen(pos));
    }
}

int main() {
    char str[] = "Hello, World!";
    char c = 'o';
    deleteChar(str, c);
    printf("删除字符 '%c' 后的字符串: %s\n", c, str);
    return 0;
}

在这个例子中,`deleteChar`函数通过`strstr`找到第一个匹配的字符,然后使用`strncpy`将剩余的字符复制到当前位置,从而达到删除特定字符的目的。

8.3 使用`strlwr`和`strupr`函数

`strlwr`和`strupr`函数分别用于将字符串转换为小写和大写。

如果你确定要删除的字符是小写或大写的,你可以使用这些函数将其转换为另一种大小写形式,然后再进行删除。以下是一个示例:

#include <stdio.h>
#include <string.h>

void deleteChar(char *str, char c) {
    char *pos;
    while ((pos = strstr(str, &c)) != NULL) {
        if (*pos == 'A' && c == 'a') {
            continue; // 如果当前字符是大写的'A',并且要删除的字符是小写的'a',则跳过
        } else if (*pos == 'a' && c == 'A') {
            break; // 如果当前字符是小写的'a',并且要删除的字符是大写的'A',则停止
        }
        strlwr(pos); // 将当前字符转换为小写
        strupr(pos + 1); // 将当前字符后面的所有字符转换为大写
        strlwr(pos + 1); // 将当前字符后面的所有字符重新转换为小写
    }
}

int main() {
    char str[] = "Hello, World!";
    char c = 'o';
    deleteChar(str, c);
    printf("删除字符 '%c' 后的字符串: %s\n", c, str);
    return 0;
}

在这个例子中,`deleteChar`函数首先检查当前字符是否是要删除的字符,如果是,则根据当前字符的大小写情况决定是否跳过或停止。然后,它使用`strlwr`和`strupr`函数将当前字符和当前字符后面的所有字符分别转换为小写和大写,再将它们重新转换为小写,从而达到删除特定字符的目的。

8.4 使用`strspn`和`strcpy`函数

`strspn`函数用于计算字符串中满足特定条件的最大长度。

#include <stdio.h>
#include <string.h>

void deleteChar(char *str, char c) {
    char *pos;
    while ((pos = strstr(str, &c)) != NULL) {
        strspn(pos, &c); // 计算从pos开始的字符中,不包含c的最大长度
        strcpy(pos, pos + strspn(pos, &c)); // 将pos之后的字符复制到pos
    }
}

int main() {
    char str[] = "Hello, World!";
    char c = 'o';
    deleteChar(str, c);
    printf("删除字符 '%c' 后的字符串: %s\n", c, str);
    return 0;
}

在这个例子中,`deleteChar`函数通过`strstr`找到第一个匹配的字符,然后使用`strspn`计算从当前位置开始的字符中,不包含要删除字符的最大长度,最后使用`strcpy`将当前位置之后的字符复制到当前位置,从而达到删除特定字符的目的。

8.5 使用`strtok`和`strcpy`函数

`strtok`函数用于分割字符串,每次调用都会返回一个新的指针,指向下一个分割的部分。结合`strcpy`函数,你可以实现删除字符串中特定字符的功能。以下是一个示例:

#include <stdio.h>
#include <string.h>

void deleteChar(char *str, char c) {
    char *pos;
    while ((pos = strstr(str, &c)) != NULL) {
        strtok(pos, &c); // 分割字符串,将pos指向的字符分割出去
        strcpy(pos, pos + strlen(pos)); // 将pos之后的字符复制到pos
    }
}

int main() {
    char str[] = "Hello, World!";
    char c = 'o';
    deleteChar(str, c);
    printf("删除字符 '%c' 后的字符串: %s\n", c, str);
    return 0;
}

在这个例子中,`deleteChar`函数通过`strstr`找到第一个匹配的字符,然后使用`strtok`将当前位置指向的字符分割出去,最后使用`strcpy`将当前位置之后的字符复制到当前位置,从而达到删除特定字符的目的。

9,字符串查找

 在C语言中,字符串查找通常使用`strchr`和`strstr`函数。

`strchr`函数用于查找一个字符串中是否包含某个字符。它的原型如下:

char *strchr(const char *s, int c);


这里`s`是要搜索的字符串,`c`是要查找的字符。如果找到该字符,`strchr`会返回指向该字符的指针;如果没有找到,则返回`NULL`。例如,查找字符串`"hello"`中是否包含字符`'e'`:

#include <stdio.h>
#include <string.h>

int main() {
    const char *str = "hello";
    char *result = strchr(str, 'e');
    if (result != NULL) {
        printf("找到字符 '%c' 在位置 %ld\n", result[0], result - str);
    } else {
        printf("未找到字符 '%c'\n", 'e');
    }
    return 0;
}

`strstr`函数用于查找一个字符串中是否包含另一个字符串。它的原型如下:

char *strstr(const char *haystack, const char *needle);


这里`haystack`是主字符串,`needle`是子字符串。如果`haystack`中包含`needle`,则`strstr`返回第一次出现的位置的指针;如果没有找到,则返回`NULL`。例如,查找字符串`"hello world"`中是否包含子字符串`"world"`:

#include <stdio.h>
#include <string.h>

int main() {
    const char *str = "hello world";
    const char *sub = "world";
    char *result = strstr(str, sub);
    if (result != NULL) {
        printf("找到子字符串 '%s' 在位置 %ld\n", sub, result - str);
    } else {
        printf("未找到子字符串 '%s'\n", sub);
    }
    return 0;
}

这些函数都定义在`<string.h>`头文件中,因此使用它们时需要包含这个头文件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值