1、典型问题一
- 下面的程序输出什么为什么?
char buf[10] = { 0 };
char src[] = "Hello %s";
snprintf(buf, sizeof(buf), src);
printf("buf = %s\n", buf);
snprintf 解析:
函数原型:int snprintf(char *str, size_t size, const char *format, ...);
函数参数 str:目标字符串;size:拷贝字节数(Bytes);format:源字符串; …格式
函数功能:从源字符串format中拷贝size字节的内容(含'\0'
)到目标字符串
注意:当函数只有3个参数时,如果第三个参数没有包含格式化信息,函数调用没有问题;相反,如果第三个参数包含了格式化信息,但缺少后续对应参数,则程序行为不确定。
所以上面那个程序的大致意思就是把src里面sizeof(buf)个字节的东西放到buf里面
因为只有三个参数,且第三个参数包含格式化信息,所以输出出现问题。
修改:
#include <stdio.h>
#include <string.h>
int main()
{
char buf[10] = { 1,2,3,4,5,6,7,8,9,0 };
char src[] = "Hello 33";
snprintf(buf, sizeof(buf), src);
printf("buf = %s\n", buf);
return 0;
}
如果保留%s,我们要在后续的参数加上%s要表达的格式
#include <stdio.h>
#include <string.h>
int main()
{
char buf[10] = { 1,2,3,4,5,6,7,8,9,0 };
char src[] = "Hello %s";
snprintf(buf, sizeof(buf), src,"xiebs");
printf("buf = %s\n", buf);
return 0;
}
2、典型问题二
- 下面的程序输出什么为什么?
#include <stdio.h>
#include <string.h>
#define STR "Hello, \0D.T.Software\0"
int main()
{
char* src = STR;
char buf[255] = { 0 };
snprintf(buf, sizeof(buf), src);
printf("strlen(STR) = %d\n", strlen(STR));
printf("sizeof(STR) = %d\n", sizeof(STR));
printf("strlen(src) = %d\n", strlen(src));
printf("sizeof(src) = %d\n", sizeof(src));
printf("strlen(buf) = %d\n", strlen(buf));
printf("sizeof(buf) = %d\n", sizeof(buf));
printf("src = %s\n", src);
printf("buf = %s\n", buf);
return 0;
}
分析:
- 字符串相关的函数均以第一个出现的
‘\0’
作为结束符 - 编译器总是会在字符串字面量的末尾添加
‘\0’
,不管是不是手动添加‘\0’
- 字符串字面量的本质为数组
3、典型问题三
- 下面的程序输出什么为什么?
#include <stdio.h>
#include <string.h>
#define S1 "D.T.Software"
#define S2 "D.T.Software"
int main()
{
if (S1 == S2)
{
printf("Equal\n");
}
else
{
printf("Non Equal\n");
}
if (strcmp(S1, S2) == 0)
{
printf("Equal\n");
}
else
{
printf("Non Equal\n");
}
return 0;
}
分析:
- 字符串之间的比较需要用strcmp完成
- 不可以直接用 == 进行字符串直接的比较
- 完全相同的字符串字面量的 == 比较结果为false
那为什么我们这里第一个程序会出现equal呢,因为一些现代编译器能够将相同的字符串字面量映射到同一个无名字符数组,因此 == 比较结果为true。
有人会说,宏定义不就是文本替换吗,那么 == 肯定是相等的啊。因为整个字符串相比较,用 == 比较时它们会退化为指向首元素的指针,只要不是遇到sizeof和&,数组名都会退化,所以这里的比较主要是判别两个指针有没有指向同一片地址。
4、典型问题四
- 字符串循环右移
void right_shift_r(const char* src,char* result,unsigned int n)
函数功能:
将输入字符串src循环右移n位,result为输出结果
要求:
以效率最高的方式实现
示例:
“abcde”----2----→“deabc”
“abcde”----8----→“cdeab”
#include <stdio.h>
#include <string.h>
void right_shift_r(const char* src, char* result, unsigned int n)
{
int len = strlen(src);
for (int i = 0; i < len; i++)
{
result[(i + n) % len] = src[i]; //这里取余老是会写成除号
}
result[len] = '\0';
}
int main()
{
char result[255] = { 0 }; //定义字符串最简单的方法,0代表acsii值为0的数,也就是'\0'
right_shift_r("abcde", result, 2);
printf("%s\n", result);
right_shift_r("abcde", result, 8);
printf("%s\n", result);
return 0;
}
为什么说这个效率最高,因为 for 循环只执行一次,无论n多大,也只需要循环一次。
5、strlen 和 sizeof 的区别
个人观点:
strlen主要就是用来针对字符串,看字符串里面有几个有效字符,遇 \0
即停止,且不包括\0
。
而 sizeof 主要是用来算占的字节大小,它算字符串的大小时,遇 \0
加1,到最后结束加一个默认的1即可。