本节关键字:C语言 字符串处理 内存处理
相关C库函数:printf、sprintf、snprintf、scanf、sscanf、strcmp、strstr、strcpy、atoi、atol、atoll、memcpy、memcmp、memmove等
#include
int scanf(const char *format, ...);
/**
@brief 从标准输入stdin读取格式化输入
@param format 可以是:%c %d %f %o %s %u %x %p %[] %%等
@param ... [可变参数](https://blog.csdn.net/qq_45157350/article/details/134600815)
@return 成功返回匹配和赋值的个数,失败返回EOF
*/
// 例程参考之前的文章:[Linux C语言 24-格式化操作](https://blog.csdn.net/qq_45157350/article/details/134594551)
#include
int sscanf(const char *str, const char *format, ...);
/**
@brief 从字符串读取格式化输入
@param str C语言字符串
@param format 可以是:%c %d %f %o %s %u %x %p %[] %%等
@param ... [可变参数](https://blog.csdn.net/qq_45157350/article/details/134600815)
@return 成功返回匹配和赋值的个数,失败返回EOF
*/
/// 后期出一篇单独的文章
#include
int printf(const char *format, ...);
/**
@brief 格式化输出到标准输出stdout
@param format 可以是:%c %d %f %o %s %u %x %p %[] %%等
@param ... [可变参数](https://blog.csdn.net/qq_45157350/article/details/134600815)
@return 成功返回写入的字符总数,失败返回负数
*/
// 例程参考之前的文章:[Linux C语言 24-格式化操作](https://blog.csdn.net/qq_45157350/article/details/134594551)
#include
int sprintf(char *str, const char *format, ...);
/**
@brief 格式化输出到str指向的字符串
@param str 存储格式化结果的缓冲区
@param format 可以是:%c %d %f %o %s %u %x %p %[] %%等
@param ... [可变参数](https://blog.csdn.net/qq_45157350/article/details/134600815)
@return 成功返回写入的字符总数(不包括字符串追加在字符串末尾的空字符),失败返回负数
*/
// 例程参考之前的文章:[Linux C语言 24-格式化操作](https://blog.csdn.net/qq_45157350/article/details/134594551)
#include
int snprintf(char *str, size_t size, const char *format, ...);
/**
@brief 格式化输出到str指向的字符串,限制输出的字符数,避免缓冲区溢出,最多写入size-1个字符
@param str 存储格式化结果的缓冲区
@param format 可以是:%c %d %f %o %s %u %x %p %[] %%等
@param ... [可变参数](https://blog.csdn.net/qq_45157350/article/details/134600815)
@return 成功返回写入缓冲区的字符总数(不包括字符串追加在字符串末尾的空字符),失败返回负数
*/
// 复习一下 # 的作用
#define toStr(a) #a
void tSnprintf(void)
{
int no = 1713080405;
char name[] = "Zhangsan";
int sex = 1;
char language[] = "Chinese";
float score = 99.99;
char sText[512];
memset(sText, 0, sizeof(sText));
sprintf(sText, " %s:%d\n %s:%s\n %s:%s\n %s:%s\n %s:%.02f\n",
toStr(no), no,
toStr(name), name,
toStr(sex), sex ? "man" : "women", // 复习一下三目运算符?
toStr(language), language,
toStr(score), score);
printf("%s\n", sText);
}
#include
size_t strlen(const char *s);
/**
@brief 计算字符串的长度,直到空结束符,但不包括空结束符('\0')
@param s 要计算长度的字符串
@return 返回字符串的长度(不包含字符串结束符)
*/
void tStrlen(void)
{
char str1[] = "abcdefg";
char str2[] = "12345\06789";
char str3[] = "a1 b1 c3 ? ~ @ ";
printf("strlen(str1)=%d, str1: %s\n", strlen(str1), str1);
printf("strlen(str2)=%d, str2: %s\n", strlen(str2), str2); // 有发现什么异常吗?
printf("strlen(str3)=%d, str3: %s\n", strlen(str3), str3);
}
#include
int strcmp(const char *s1, const char *s2);
/**
@brief 比较字符串s1与s2,从第一个字符开始比,直到不相等的字符结束
@param s1 第一个字符串
@param s2 第二个字符串
@return s1s2 返回正数;s1=s2 返回0
*/
void tStrcmp(void)
{
char str1[] = "Hello, i'm Lihua";
char str2[] = "Hello, i'm Lihuan";
char str3[] = "Hello";
char str4[] = "Hello\09";
printf("%d\n", strcmp(str1, str2));
printf("%d\n", strcmp(str1, str3));
printf("%d\n", strcmp(str3, str4)); // 注意!
printf("%d\n", strcmp(str3, str2));
}
#include
int strncmp(const char *s1, const char *s2, size_t n);
/**
@brief 比较字符串s1与s2的前n个字符
@param s1 第一个字符串
@param s2 第二个字符串
@param n 要比较的最大字符数
@return s1s2 返回正数;s1=s2 返回0
*/
void tStrncmp(void)
{
char str1[] = "Hello, i'm Lihua";
char str2[] = "Hello, i'm Lihuan";
char str3[] = "Hello";
char str4[] = "Hello\09";
printf("%d\n", strncmp(str1, str2, 6));
printf("%d\n", strncmp(str1, str3, 6));
printf("%d\n", strncmp(str3, str4, 6)); // 注意!
printf("%d\n", strncmp(str3, str2, 6));
}
#include
char *strstr(const char *haystack, const char *needle);
/**
@brief 在字符串haystack中查找字符串needle第一次出现的位置,不包含终止符'\0'
@param haystack 被检索的字符串
@param needle 需要检索的短字符串
@return 找到返回字符串needle第一次出现的位置,未找到返回NULL
*/
void tStrstr(void)
{
char haystack[] = "Hello Hi DD MM XoX String Name OoO !!!!";
char needle[] = "OoO";
printf("%s\n", strstr(haystack, needle));
}
#include
char *strcpy(char *dest, const char *src);
/**
@brief 将字符串src拷贝到dest中,如果字符串src的长度大于字符串dest可能会造成缓冲溢出
@param dest 存储拷贝内容的数组
@param src 被拷贝的字符串
@return 返回一个指向最终目标字符串dest的指针
*/
void tStrcpy(void)
{
char dest[128] = {0};
char src[] = "OoO";
printf("%s\n", strcpy(dest, src));
}
#include
char *strncpy(char *dest, const char *src, size_t n);
/**
@brief 将字符串src的前n个字符拷贝到dest中,dest的剩余部分用空字节填充
@param dest 存储拷贝内容的数组
@param src 被拷贝的字符串
@param n 要从源字符串中拷贝的字节数
@return 返回一个指向最终目标字符串dest的指针
*/
void tStrncpy(void)
{
char dest[128] = {0};
char src[] = "OoO n|n";
printf("%s\n", strncpy(dest, src, 3));
}
#include
char *strcat(char *dest, const char *src);
/**
@brief 把src指向的字符串追加到dest指向的字符串结尾
@param dest 存储拷贝内容的数组
@param src 被拷贝的字符串,该字符串不会覆盖目标字符串
@return 返回一个指向最终目标字符串dest的指针
*/
void tStrcat(void)
{
char dest[128] = {0};
char src[] = "OoO n|n";
printf("%s\n", strcat(dest, src));
}
#include
char *strncat(char *dest, const char *src, size_t n);
/**
@brief 把src指向字符串的前n个字符追加到dest指向的字符串结尾
@param dest 存储拷贝内容的数组
@param src 被拷贝的字符串,该字符串不会覆盖目标字符串
@return 返回一个指向最终目标字符串dest的指针
*/
void tStrncat(void)
{
char dest[128] = {0};
char src[] = "OoO n|n";
printf("%s\n", strncat(dest, src, 3));
}
#include
char *strtok(char *str, const char *delim);
/**
@brief 分解字符串str为一组字符串,delim为分隔符
@param str 要被分解的字符串
@param delim 包含分隔符的C字符串
@return 返回被分解的第一个子字符串,如果没有可检索的字符串,则返回空指针NULL
*/
void tStrtok(void)
{
char buffer[] = "Chinese man 25,C language 99,there strtok_r,test";
char *token;
token = strtok(str, ",");
while (token)
printf("%s\n", token=strtok(NULL, ","));
}
#include
char *strtok_r(char *str, const char *delim, char **saveptr);
/**
@brief 分解字符串(linux平台下strtok函数的线程安全版)
@param str 要被分解的字符串
@param delim 分隔符C字符串
@param saveptr 保存切分时的上下文,应对连续调用分解相同源字符串
@return 返回被分解的第一个子字符串,如果没有可检索的字符串,则返回空指针NULL
第一次调用strtok_r时,str参数必须指向待提取的字符串,saveptr参数的值可以忽略。
连续调用时,str赋值为NULL,saveptr为上次调用后返回的值,不要修改。
一系列不同的字符串可能会同时连续调用strtok_r进行提取,要为不同的调用传递不同的saveptr参数。
strtok_r实际上就是将strtok内部隐式保存的this指针,以参数的形式与函数外部进行交互。
由调用者进行传递、保存甚至是修改。需要调用者在连续切分相同源字符串时,除了将str参数赋值为NULL,还要传递上次切分时保存下的saveptr。
*/
void tStrtok_r(void)
{
int i, in = 0;
char buffer[] = "Chinese man 25,C language 99,there strtok_r test";
char *p[20];
char *buf = buffer;
char *outer_ptr = NULL;
char *inner_ptr = NULL;
printf("source C string is: %s\n", buffer);
while ((p[in] = strtok_r(buf, ",", &outer_ptr)) != NULL)
{
buf = p[in];
while ((p[in] = strtok_r(buf, " ", &inner_ptr)) != NULL)
{
in++;
buf = NULL;
}
buf = NULL;
}
printf("strtok_r() get %d strings: \n", in);
for (i = 0; i < in; i++)
printf("No(%d) -> %s\n", i, p[i]);
}
#include
char *strerror(int errnum);
/**
@brief 从内部数组中搜索错误码errnum,并返回一个指向错误消息字符串的指针,字符串内容取决于平台和编译器
@param errnum 要查询的错误码,通常是全局变量errno
@return 返回一个指向错误码描述的字符串指针
*/
#include
void tStrerror(void)
{
printf("%s\n", strerror(errno));
}
#include
void *memcpy(void *dest, const void *src, size_t n);
/**
@brief 从存储区src复制n个字节到存储区dest
@param dest 存储复制内容的目标数组,类型强制转换为void*
@param src 要复制的内容,类型强转为void*
@param n 要复制的字节数
@return 返回指向目标存储区dest的指针
*/
void tMemcpy(void)
{
char dest[1024];
char src[] = "memcpy test.";
memset(dest, 0, sizeof(dest));
printf("1: %s\n", dest);
memcpy(dest, src, strlen(src));
printf("2: %s\n", dest);
}
#include
int memcmp(const void *s1, const void *s2, size_t n);
/**
@brief 比较s1和s2的前n个字节
@param s1 指向内存区域的指针
@param s2 指向内存区域的指针
@param n 要比较的字节数
@return s1s2返回正数;s1=s2返回0
*/
void tMemcmp(void)
{
char str1[] = "Hello, i'm Lihua";
char str2[] = "Hello, i'm Lihuan";
char str3[] = "Hello";
char str4[] = "Hello\09";
printf("%d\n", strncmp(str1, str2, 6));
printf("%d\n", strncmp(str1, str3, 6));
printf("%d\n", strncmp(str3, str4, 6));
printf("%d\n", strncmp(str3, str2, 6));
}
#include
void *memmove(void *dest, const void *src, size_t n);
/**
@brief 将src的前n个字符复制到dest,区域重叠时也能避免内容被覆盖,保证内容拷贝成功
@param dest 指针,指向存储复制内容的目标内存区域,类型强转为void*
@param src 指针,指向要复制的数据内存区域,类型强转为void*
@param n 要复制的字节数
@return 返回指向目标存储区dest的指针
*/
void tMemmove(void)
{
char dest[] = "abcdefghijklmnopqrstuvwxyz";
char *src = dest + 5;
printf("dest: %s\n", dest);
printf("%s\n", memmove(dest, src, strlen(src));
}
#include
int atoi(const char *nptr);
/**
@brief 把参数 str 所指向的字符串转换为一个int型的整数
@param nptr 要被转换为整数的字符串
@return 成功返回转换后的整数,失败返回0
*/
void tAtoi(void)
{
char nptr[] = "2234567890";
printf("%d\n", atoi(nptr));
}
#include
long atol(const char *nptr);
/**
@brief 把参数 str 所指向的字符串转换为一个long int型的长整数
@param nptr 要被转换为整数的字符串
@return 成功返回转换后的整数,失败返回0
*/
void tAtol(void)
{
char nptr[] = "2234567890";
printf("%ld\n", atol(nptr));
}
#include
long long atoll(const char *nptr);
/**
@brief 把参数 str 所指向的字符串转换为一个long long int型的长整数(64位)
@param nptr 要被转换为整数的字符串
@return 成功返回转换后的整数,失败返回0
*/
void tAtoll(void)
{
char nptr[] = "2234567890";
printf("%lld\n", atoll(nptr));
}
#include
long long atoq(const char *nptr);
/**
@brief 把参数 str 所指向的字符串转换为一个long long int型的长整数(64位),是atoll()过去的名字
@param nptr 要被转换为整数的字符串
@return 成功返回转换后的整数,失败返回0
*/