注:博客中内容主要来自《狄泰软件学院》,博客仅当私人笔记使用。
测试环境:Ubuntu 10.10
GCC版本:4.4.5
一、典型问题一
1)下面的程序输出什么为什么?
char buf[10] = {0};
char src[] = "hello %s"; //9个字符
snprintf(buf,sizeof(buf),src); //将src要打印的内容放到buf
printf("buf = %s\n",buf);
实例分析
31-1.c
#include <stdio.h>
int main()
{
char buf[10] = {0};
char src[] = "hello %s";
snprintf(buf, sizeof(buf), src); //难点是这个函数理解
printf("buf = %s\n", buf);
return 0;
}
操作:
1) gcc 31-1.c -o 31-1.out编译有警告:
31-1.c:8:2: warning: format not a string literal and no format arguments [-Wformat-security]
snprintf(buf, sizeof(buf), src);
^
警告:不是字符串字面量格式,缺少格式参数
31-1.c:8:2: warning: format not a string literal and no format arguments [-Wformat-security]
打印结果:
buf = hello ��
二、分析
1)snprintf函数本身是可变参数函数,原型如下:
int snprintf(char* buffer,int buf_size,const char* fomart,...)
当函数只有3个参数时,如果第三个参数没有包含格式化信
息,函数调用没有问题;相反,如果第三个参数包含了格式
化信息,但缺少后续对应参数,则程序行为不确定。
三、典型问题二
1)下面的程序输出什么为什么?
#define STR "Hello, \0D.T.Software\0" //'\0'后边内容不打印
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("src = %s\n",src);
printf("buf = %s\n",buf);
31-2.c
#include <stdio.h>
#include <string.h>
int main()
{
#define STR "Hello, \0D.T.Software\0"
char* src = STR;
char buf[255] = {0};
snprintf(buf, sizeof(buf), src);
printf("strlen(STR) = %d\n", strlen(STR)); //7,到第一个\0
printf("sizeof(STR) = %d\n", sizeof(STR)); //22,全部字符长度
printf("strlen(src) = %d\n", strlen(src)); //7,同上
printf("sizeof(src) = %d\n", sizeof(src)); //4,指针大小
printf("strlen(buf) = %d\n", strlen(buf)); //7
printf("sizeof(buf) = %d\n", sizeof(buf)); //255
printf("src = %s\n", src); //"Hello, "
printf("buf = %s\n", buf); //"Hello, "
return 0;
}
操作:
1) gcc 31-2.c -o 31-2.out编译有警告:
31-2.c:11:2: warning: format not a string literal and no format arguments [-Wformat-security]
snprintf(buf, sizeof(buf), src);
^
警告:不是字符串字面量格式,没有格式参数
31-2.c:11:2: warning: format not a string literal and no format arguments [-Wformat-security]
打印结果:
strlen(STR) = 7
sizeof(STR) = 22
strlen(src) = 7
sizeof(STR) = 4
strlen(buf) = 7
sizeof(buf) = 255
src = Hello,
buf = Hello,
分析:
"Hello, \0D.T.Software\0"第一个'\0'后边的字符被丢弃。
四、分析
1) 字符串相关的函数均以第一个出现的'\0'作为结束符
2) 编译器总是会在字符串字面量的末尾添加'\0'
3) 字符串字面量的本质为数组
字符串是一个特殊的字符数组,字符指针(char*)可以指向字符数组,因此字符指针可以指向字符数组。
五、典型问题三
1)下面的程序输出什么为什么?
#define S1 "D.T.Software"
#define S2 "D.T.Software"
if(S1 == S2)
{
printf("Equal\n");
}
else
{
printf("Non Equal\n"); //打印这个内容
}
实例分析
31-3.c
#include <stdio.h>
#include <string.h>
int main()
{
#define S1 "D.T.Software"
#define S2 "D.T.Software"
if( S1 == S2 )
{
printf("Equal\n");
}
else
{
printf("Non Equal\n");
}
if( strcmp(S1, S2) == 0 ) //strcmp中两个参数相同返回0
{
printf("Equal\n");
}
else
{
printf("Non Equal\n");
}
return 0;
}
操作:
1)gcc 31-3.c -o 31-3.out编译正确,打印结果:
Equal(gcc编译器优化结果!gcc认为S1和S2指定的都是同一个字符串数组)
Equal
bcc编译器:
Non Equal
Equal
六、分析
1) 字符串之间的相等比较需要用strcmp完成
2) 不可直接用==进行字符串直接的比较
3) 完全相同的字符串字面量的==比较结果为false(0)
一些现代编译器能够将相同的字符串字面量映射到同一个无名字符数组,因此==比较结果为true。
注:不编写依赖特殊编译器的代码!!!
七、典型问题四
1)字符串循环右移
void right_shift_r(const char* src,char* result,unsigned int n);
函数功能:
将输入字符串src循环右移n位,result为输出结果。
要求:
以效率最高的方式实现
示例:
"abcde" --2--> "deabc"
"abcde" --8--> "cdeab" 等价于 右移3位
实例分析
31-4.c
#include <stdio.h>
#include <string.h>
/*
src:输入字符串
result:输出字符串
n:右移位数
*/
void right_shift_r(const char* src, char* result, unsigned int n)
{
const unsigned int LEN = strlen(src); //LEDN为只读变量
int i = 0;
for(i=0; i < LEN; i++) //i遍历到LEN
{
result[(n + i) % LEN] = src[i]; //这个变换公式有难度
}
result[LEN] = '\0'; //补上字符'\0'
}
//从数据结构来看,这个效率高呢:因为只遍历一边数组,时间复杂度为O(n)
int main()
{
char result[255] = {0};
right_shift_r("abcde", result, 2);
printf("%s\n", result);
right_shift_r("abcde", result, 5);
printf("%s\n", result);
right_shift_r("abcde", result, 8);
printf("%s\n", result);
return 0;
}
操作:
1) gcc 31-4.c -o 31-4.out编译正确,打印结果:
deabc
abcde
cdeab