编程总结
每每刷完一道题后,其思想和精妙之处没有地方记录,本篇博客用以记录刷题过程中的遇到的算法和技巧
字符串函数汇总
memcpy_s
函数原型
errno_t memcpy_s(void *dest, size_t destSize, const void *src, size_t count);
函数描述
memcpy_s 函数,从 src 中复制 count 个字节到 dest 中。它是 memcpy 的安全版本,因为参数中限制了目标内存区域的大小。是在内存级别上直接进行拷贝操作,但注意它一次拷贝的数量为一个字节,而不是一个位(比特)。
参数描述
dest: 目标数组,或者说目标内存区域
destSize:目标内存区域的大小,其单位是字节
src: 源数组,或者说源内存区域
count: 要复制的源内存区域元素的个数,其单位是字节
返回值
如果成功则返回零(EOK)
memset_s
函数原型
errno_t memset_s(void *dest,rsize_t destsz,int ch,rsize_t count)
函数描述
1)将ch值(在转换为无符号字符后,就像通过(unsigned char)ch)复制到dest指向的对象的每个第一个计数字符中。
如果访问超出dest数组的末尾,则行为未定义。如果dest是空指针,行为是未定义的。
2)与(1)相同,只是在运行时检测到以下错误,并且如果dest和destsz本身有效,则在将ch存储到目标范围[dest,dest + destsz)的每个位置之后调用当前安装的约束处理函数:
参数描述
dest: 指向要填充的对象的指针
ch: 填充字节
count:要填充的字节数
destsz: 目标数组的大小
返回值
1)dest 副本
2)如果成功则返回零(EOK),错误时为非零。 同样出错的是,如果dest不是空指针并且destsz有效,那么将destsz填充字节ch写入目标数组
strncpy_s
函数原型
errno_t strncpy_s(char *restrict dest,rsize_t destsz,const char *restrict src,rsize_t count)
函数描述
1)将由src指向的字符数组的大部分计数字符(包括终止空字符,但不包括空字符后面的任何字符)复制到由dest指向的字符数组。如果在复制完整个数组src之前达到count,则生成的字符数组不会以null结尾。
如果在复制src中的终止空字符之后,未达到count,则将额外的空字符写入dest,直到写入总计数字符。
如果字符数组重叠,如果dest或src不是指向字符数组的指针(包括如果dest或src是空指针),如果dest指向的数组大小小于count,则行为未定义, 或者如果src指向的数组大小小于count并且不包含空字符。
2)与(1)相同,除了该函数不会继续将零写入目标数组以填充计数,它将在写入终止空字符后停止(如果源中没有空值,它将在dest处写入一个 [count]然后停止)。
参数描述
dest: 指向要复制到的字符数组的指针
destsz: 目标缓冲区的大小
src: 指向要复制的字符数组的指针
count: 最大数量的字符复制
返回值
1)返回 dest 副本
2)在成功时返回零(EOK),错误时返回非零值。 另外,如果出错,则将0写入dest [0](除非dest为空指针或destsz为零或大于RSIZE_MAX),并可能用未指定的值来摧毁目标数组的其余部分
strcat_s
函数原型
errno_t strncat_s(char *restrict dest,rsize_t destsz,const char *restrict src,rsize_t count)
函数描述
1)追加由src指向的字符数组中的大多数计数字符,如果找到空字符,则停止到由dest指向的以null结尾的字节字符串的末尾。 字符src [0]替换dest结尾处的空终止符。 终止空字符总是附加在最后(因此函数可以写入的最大字节数为count + 1)。
如果目标数组没有足够的空间用于dest和src的第一个计数字符的内容以及终止的空字符,则行为未定义。 如果源和目标对象重叠,则行为未定义。 如果dest不是指向以空字符结尾的字节字符串的指针,或者src不是指向字符数组的指针,则行为未定义.
2)与(1)相同,只是此函数可能会打断目标数组的其余部分(从写入到destsz的最后一个字节开始),并且在运行时检测到以下错误并调用当前安装的约束处理函数。
参数描述
dest: 指向要附加到的以空字符结尾的字节字符串
destsz: 目标缓冲区的大小
src: 指向要复制的字符数组的指针
count 最大数量的字符复制
返回值
1)返回 dest 副本
2)在成功时返回零(EOK),错误时返回非零值。 另外,如果发生错误,则将零写入dest [0](除非dest是空指针或destsz为零或大于RMAX_SIZE)。
strtok_s
函数原型
char *strtok_s(char *restrict str,rsize_t *restrict strmax,const char *restrict delim,char **restrict ptr)
函数描述
1)在由str指向的以空字符结尾的字节字符串中查找下一个标记。 分隔符字符由delim指向的以空字符结尾的字节字符串标识。该函数被设计为被称为倍数时间以从相同的字符串获得连续的令牌。
如果str!= NULL,则该调用被视为针对此特定字符串的第一次调用strtok。该函数搜索不在delim中的第一个字符。
如果没有找到这样的字符,那么str中就没有令牌了,并且该函数返回一个空指针。
如果找到这样的字符,它就是令牌的开始。然后该函数从此处开始搜索包含在delim中的第一个字符。
如果没有找到这样的字符,str只有一个标记,未来对strtok的调用将返回一个空指针
如果找到这样的字符,它将被替换为空字符’\ 0’,并且指向以下字符的指针将存储在静态位置以供后续调用。
该函数然后将指针返回到令牌的开始处如果str == NULL,则该调用将被视为对strtok的后续调用:该函数将继续前一次调用中的离开。行为与先前存储的指针作为str传递的行为相同。如果str或delim不是指向以空字符结尾的字节字符串的指针,则行为未定义。
2)与(1)相同,除了在每一步中,将留在str中的字符数写入* strmax并将标记器的内部状态写入* ptr。 重复调用(使用null str)必须将strmax和ptr与先前调用所存储的值一起传递。 此外,在运行时检测到以下错误,并调用当前安装的约束处理函数,而不在ptr指向的对象中存储任何内容
参数描述
str: 指向以空字符结尾的字节字符串进行标记的指针
delim: 指向标识分隔符的以空字符结尾的字节串的指针
strmax: 指向最初保存str大小的对象的指针:strtok_s存储待检查的字符数
ptr: 指向char *类型的对象的指针,strtok_s用它来存储它的内部状态
返回值
返回指向下一个标记开头的指针,如果没有其他标记,则返回NULL。
sprintf_s
函数原型
int sprintf_s(char *buffer, size_t sizeOfBuffer, const char *format, ...);
函数描述
1)在由str指向的以空字符结尾的字节字符串中查找下一个标记。 分隔符字符由delim指向的以空字符结尾的字节字符串标识。该函数被设计为被称为倍数时间以从相同的字符串获得连续的令牌。
如果str!= NULL,则该调用被视为针对此特定字符串的第一次调用strtok。该函数搜索不在delim中的第一个字符。
如果没有找到这样的字符,那么str中就没有令牌了,并且该函数返回一个空指针。
如果找到这样的字符,它就是令牌的开始。然后该函数从此处开始搜索包含在delim中的第一个字符。
如果没有找到这样的字符,str只有一个标记,未来对strtok的调用将返回一个空指针
如果找到这样的字符,它将被替换为空字符’\ 0’,并且指向以下字符的指针将存储在静态位置以供后续调用。
该函数然后将指针返回到令牌的开始处如果str == NULL,则该调用将被视为对strtok的后续调用:该函数将继续前一次调用中的离开。行为与先前存储的指针作为str传递的行为相同。如果str或delim不是指向以空字符结尾的字节字符串的指针,则行为未定义。
2)与(1)相同,除了在每一步中,将留在str中的字符数写入* strmax并将标记器的内部状态写入* ptr。 重复调用(使用null str)必须将strmax和ptr与先前调用所存储的值一起传递。 此外,在运行时检测到以下错误,并调用当前安装的约束处理函数,而不在ptr指向的对象中存储任何内容
参数描述
buffer 输出的存储位置
sizeOfBuffer 可存储的最多字符数。
format 格式控件字符串
… 要设置格式的可选参数
locale 要使用的区域设置。
返回值
写入的字符数或 -1(如果发生错误)。 如果 buffer 或 format 是 null 指针,sprintf_s 和 swprintf_s 将返回 -1 并将 errno 设置为 EINVAL。
sprintf_s 返回存储在 buffer中的字节数,不包括终止 null 字符。 swprintf_s 返回存储在 buffer 中的宽字符数,不包括中止 null 宽字符。
int main( void )
{
char buffer[200], s[] = "computer", c = 'l';
int i = 35, j;
float fp = 1.7320534f;
// Format and print various data:
j = sprintf_s(buffer, 200, " String: %s\n", s );
j += sprintf_s(buffer + j, 200 - j, " Character: %c\n", c );
j += sprintf_s(buffer + j, 200 - j, " Integer: %d\n", i );
j += sprintf_s(buffer + j, 200 - j, " Real: %f\n", fp );
printf_s( "Output:\n%s\ncharacter count = %d\n", buffer, j );
}
Output:
String: computer
Character: l
Integer: 35
Real: 1.732053
character count = 79
strncmp
函数原型
int strncmp(const char *str1, const char *str2, size_t n)
函数描述
strncmp函数为字符串比较函数 ,功能是将str1和str2进行比较,最多比较n个字节。若str1与str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。
参数描述
str1 – 要进行比较的第一个字符串。
str2 – 要进行比较的第二个字符串。
n – 要比较的最大字符数
返回值
str1=str2 返回0
str1>str2 返回大于0的数
str1<str2 返回小于0的数
函数Demo_字符函数
#define BUFFER_SIZE 128
int safetyFunction(char *s)
{
int len = strlen(s);
if (len <= 1) {
return len;
}
errno_t rc;
char hashtable1[BUFFER_SIZE] = {false};
char hashtable2[BUFFER_SIZE] = {"@123@1234@12345@"};
char hashtable3[BUFFER_SIZE] = {"12345678"};
// 1. errno_t memcpy_s(void* dest, size_t destMax, const void* src, size_t count)
rc = memcpy_s(hashtable1, BUFFER_SIZE, hashtable2, BUFFER_SIZE - 1);
if (rc != EOK) {
return -1;
}
// 2.errno_t memset_s(void* dest, size_t destMax, int c, size_t count)
rc = memset_s(hashtable1, BUFFER_SIZE, '1', BUFFER_SIZE);
if (rc != EOK) {
return -1;
}
// 3.errno_t strcpy_s(char* strDest,size_t destMax,const char* strSrc)
rc = strncpy_s(hashtable1, BUFFER_SIZE, "The Love of the game", BUFFER_SIZE);
if (rc != EOK) {
return -1;
}
// 4.errno_t strcat_s(char* strDest,size_t destMax,const char* strSrc)
rc = strcat_s(hashtable1, BUFFER_SIZE, "Make the choice");
if (rc != EOK) {
return -1;
}
// 5.char* strtok_s(char* strToken, const char* strDelimit, char** context)
// 成功:返回被分割出的子字符串首地址(当子字符串长度等于0时返回NULL)
// 失败:当参数不合法或找到的子字符串长度为0时,返回NULL。
char *next = NULL; // 保存调用strok_s后的位置信息
char *token = NULL;
const char *plim = "@";
token = strtok_s(hashtable2, plim, &next);
while (token != NULL) {
if (token != NULL) {
printf(" %s\n", token);
token = strtok_s(NULL, plim, &next);
}
}
// 6.int sprintf_s(char *strDest, size_t destMax, const char *format, ...) -- 将数据格式化输出到目的缓冲区。
// 成功:操作成功时,返回写入的字符个数
char buffer[BUFFER_SIZE] = {0};
char *string = "Kobe Kobe";
int intString = 20201204;
int iRet;
iRet = sprintf_s(buffer, BUFFER_SIZE, "%s, %d", string, intString);
printf("iRet = %d, buffer = %s.\n", iRet, buffer);
iRet = atoi(hashtable3);
return len;
}
int main()
{
const char *str = "abcabcd";
safetyFunction(str);
}
sprintf_s 还可以组合多个不同格式的统一到字符数组里:
tmp = atoi(res);
sprintf_s(result, NUM_9, "%08d", tmp);
sprintf_s(node[cnt].buf, NUM_9 + 1, "%c%08s", strs[i][0], result);
qsort函数
手法1:qsort可以用来排序结构体
a -b 的顺序就是从小往大
typedef struct student {
int height;
int weight;
int id;
} student_t;
int cmp(const void *a, const void *b)
{
student_t *aa = (student_t *)a;
student_t *bb = (student_t *)b;
// 3. 如果身高、体重都相同,则按ID排序
if (aa->height == bb->height && aa->weight == bb->weight) {
return (aa->id - bb->id); // 由小往大排序
}
// 2. 身高相同,体重不同,按体重排序
if (aa->height == bb->height) {
return (aa->weight - bb->weight);
}
// 1. 身高、体重均不同,优先按身高排序
return (aa->height - bb->height);
}
qsort(stu, num, sizeof(student_t), cmp);
手法2:在排序字符串时,我们可以利用qsort的cmp,这么来写,可以做字典序由低至高排序:
int cmp(const void *a, const void *b)
{
jobNumber *aa = (jobNumber *)a;
jobNumber *bb = (jobNumber *)b;
return strncmp(aa->buf, bb->buf, BUF_LEN);
}
手法3:对 double / float 数组升序排序
以上方法对 double 型则不适用,因为 cmp 返回值为 int 型,若两个小数差距极小,例如:a=0.15 ,b=0.14,将会被强制转换为0返回,不发生交换。
double 与 float 需要转成 1 和 -1
int cmp(const void *a, const void *b)
{
if(*(double *)a > *(double *)b) {
return 1;
}
else if(*(double *)a < *(double *)b) {
return -1;
}
return 0;
}
整数的翻转
字符串的翻转我们有手法处理,这里记录下整数的翻转,当然只是我自己的方法,并不是Golden的,有好的建议的朋友可以指出来。主要用到 sprintf_s 函数
// 反转一个整数
int numFanzhuan(int num)
{
int i;
int len = 0;
char str[STR_MAX_LEN] = {0};
char strTmp[STR_MAX_LEN] = {0};
int res;
sprintf_s(str, STR_MAX_LEN, "%d", num);
for (i = 0; i < STR_MAX_LEN; i++) {
if (str[i] != '\0') {
len++;
}
}
for (i = 0; i < len; i++) {
strTmp[i] = str[len - 1 - i];
}
res = atoi(strTmp);
return res;
}