今天又来继续我们的字符串函数的文章,这也是最后一篇了。希望这两篇文章能让各位理解透字符串函数。
strchr
strchr 是一个用于在字符串中查找特定字符首次出现位置的函数。以下是解析和模拟实现 strchr 函数的示例:
解析 strchr 函数:
#include <stdio.h> // 解析 strchr 函数 void parse_strchr() { const char *string = "Hello, World!"; char target = 'l'; // 使用 strchr 函数查找字符 const char *found = strchr(string, target); if (found != NULL) { printf("Character '%c' found at index: %zu\n", target, found - string); } else { printf("Character '%c' not found in string\n", target); } } int main() { parse_strchr(); return 0; }
在上述示例中,我们定义了一个字符串 string 和要查找的目标字符 target 。然后,使用 strchr 函数在字符串中查找目标字符,并将找到的位置存储在 found 变量中。根据 found 是否为 NULL ,我们输出相应的结果。
模拟实现 strchr 函数:
#include <stdio.h> // 模拟实现 strchr 函数 const char * my_strchr(const char * string, char target) { for (; *string != '\0'; string++) { if (*string == target) { return string; } } return NULL; } int main() { const char * string = "Hello, World!"; char target = 'l'; // 使用模拟的 my_strchr 函数查找字符 const char * found = my_strchr(string, target); if (found != NULL) { printf("Character'%c'found at index:%zu\n", target, found - string); } else { printf("Character'%c' not found in string\n", target); } return 0; }
在模拟实现中,我们使用一个循环遍历字符串中的每个字符。如果找到了与目标字符匹配的字符,就返回该字符的地址。如果循环结束后仍未找到,返回 NULL 。
这两种方法(解析和模拟实现)都可以用来在字符串中查找特定字符。使用标准库中的 strchr 函数通常更方便和可靠,但模拟实现可以帮助你更好地理解其工作原理。
strtok
strtok 是一个用于分割字符串的函数。它根据指定的分隔符将字符串分割成多个部分,并可以逐个提取这些部分。
下面是模拟和解析 strtok 函数的示例:
解析 strtok 函数:
#include <stdio.h> #include <string.h> // 解析 strtok 函数 void parse_strtok() { char string[] = "apple,banana,cherry"; char delimiter[] = ","; // 使用 strtok 函数分割字符串 char * token = strtok(string, delimiter); while (token != NULL) { printf("%s\n", token); token = strtok(NULL, delimiter); } } int main() { parse_strtok(); return 0; }
在这个示例中,我们直接使用了标准库中的 strtok 函数来分割字符串,并打印每个部分。
模拟 strtok 函数:
#include <stdio.h> #include <string.h> // 模拟 strtok 函数 char * my_strtok(char * str, const char * delimiter) { static char* token = NULL; if (str == NULL) { return NULL; } while (1) { // 查找下一个分隔符的位置 char* next = strstr(str, delimiter); // 如果找到分隔符 if (next != NULL) { *next = '\n'; } else if (next == NULL) break; } token = str; return token; } int main() { char string[] = "apple,banana,cherry"; char delimiter[] = ","; // 使用模拟的 my_strtok 函数分割字符串 char * token = my_strtok(string, delimiter); while (token != NULL) { printf("%s\n", token); token = my_strtok(NULL, delimiter); } return 0; }
在上述示例中,我们模拟了 strtok 函数的行为。通过使用 strstr 函数查找分隔符的位置,并将其设置为字符串的换行符。然后,返回找到的下一个部分的指针。
无论是模拟还是直接使用 strtok ,它们的基本原理都是根据指定的分隔符将字符串分割成多个部分。需要注意的是, strtok 函数会修改原始字符串,并且在多次调用时需要注意处理 NULL 指针的情况。
sprintf和sscanf
sprintf 是一个变参函数,用于格式化字符串并将结果写入到指定的缓冲区中,其函数声明为 int sprintf(char *buffer, const char *format, ...) 。下面是对各参数的详细解释:
- buffer :是 char 类型的指针,指向要写入的字符串的指针。
- format :格式化字符串,即在程序中指定的格式。
- argument :可选参数,可以为任意类型的数据,可以有一个或多个参数。
该函数的返回值是写入到缓冲区中的字符数,不包括字符串结尾的空字符 \0 。下面是一些常见的用法示例:
- 格式化数字字符串:
// 把整数123打印成一个字符串保存在s中 sprintf(s, "%d", 123); // 产生 "123"
- 控制浮点数打印格式:
// 保留小数点后6位数字 sprintf(s, "%f", 3.1415926); // 产生 "3.141593"
- 连接字符串:
// 连接字符串 char *who = "I"; char *whom = "52PHP"; sprintf(s, "%s love %s.", who, whom); // 产生 "I love 52PHP. "
- 打印整数和浮点数时可以指定宽度:
// 指定宽度 char a1[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'}; char a2[] = {'H', 'I', 'J', 'K', 'L', 'M', 'N'}; sprintf(s, "%.7s%.7s", a1, a2); // 产生 "ABCDEFGHIJKLMN"
需要注意的是, sprintf 函数在字符串中插入变量时不会进行边界检查,如果格式化字符串和变参列表不匹配,可能会导致缓冲区溢出或其他问题。因此,在使用 sprintf 函数时,应确保格式化字符串和变参列表的匹配,并确保缓冲区的大小足够容纳输出结果。
sscanf 函数是一个用于从字符串中读取数据的 C 语言函数,与 scanf 函数类似,但是它的输入源是一个字符串而不是标准输入。 sscanf 函数的声明如下:
int sscanf(const char *str, const char *format, ...)
参数说明:
- str :这是 C 字符串,是函数检索数据的源。
- format :这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符 。
- ... :这是可变参数,为对应的附加参数所指向的数据指定一个不同于整型(针对 d、i 和 n)、无符号整型(针对 o、u 和 x)或浮点型(针对 e、f 和 g)的大小。
该函数会将参数 str 的字符串根据参数 format 字符串来转换并格式化数据,转换后的结果存于对应的参数内。返回值为成功匹配和赋值的个数,如果没有成功匹配的项,则返回 0 。
下面是一些常见的用法示例:
- 从字符串中读取一个字符:
char c; sscanf("Hello", "%c", &c);
- 从字符串中读取一个整数:
1. int i; 2. sscanf("12345", "%d", &i); 3.
- 从字符串中读取一个浮点数:
float f; sscanf("3.1415", "%f", &f);
- 从字符串中读取多个数据:
int i, j; char s[50]; sscanf("12 56", "%d %s", &i, s, &j);
需要注意的是, sscanf 函数在字符串中读取数据时不会进行边界检查,可能会导致缓冲区溢出或其他问题。因此,在使用 sprintf 函数时,应确保字符串中的数据格式与 format 字符串中的格式说明符相匹配,并确保缓冲区的大小足够容纳读取的数据。
sprintf和sscanf的模拟实现太复杂就不模拟了。
文章已到末尾,希望多多支持。