C语言进阶:第31课:字符串典型问题分析

下面的程序输出什么,为什么?

	char buf[10] = {0};
	char src[] = "hello %s";
	
	snprintf(buf, sizeof(buf), src);
	
	printf("buf = %s\n", buf);

编译运行:

~/will$ gcc test.c
test.c: In function ‘main’:
test.c:9: warning: format not a string literal and no format arguments
test.c:9: warning: format not a string literal and no format arguments
delphi@delphi-vm:~/will$ ./a.out
buf = hello ?? 

snprintf函数本身是可变参数函数,原型如下:

int snprintf(char* buffer, int buf_size, const char* format,...)

当函数只有三个参数时,如果第三个参数没有包含格式化信息,函数调用没有问题;相反,如果第三个参数包含了格式化信息,但缺少后续对应参数,则程序行为不确定。(必须存在第四个参数——字符串)

修改程序如下:

int main()
{
	char buf[10] = {0};
	char src[] = "hello %s";
	
	snprintf(buf, sizeof(buf), src, "123");
	
	printf("buf = %s\n", buf);
	
	return 0;	
}

编译运行:

~/will$ ./a.out
buf = hello 123
下面的程序输出什么,为什么?
#include <stdio.h>
#include <string.h>

int main()
{
    #define STR "hello, \0willwilling\0"    //hello,后有个空格

    char* src = STR;
    char buf[255] = {0};

    snprintf(buf, sizeof(buf), src);    //字符串操作函数

    printf("strlen(STR) = %d\n", strlen(STR));    //7
    printf("sizeof(STR) = %d\n", sizeof(STR));    //21
    
    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,
    printf("STR = %s\n", STR);   //hello,
    
    char SS[255] = "hello, \0willwilling\0";
    
    printf("SS = %s\n", SS);    //hello,
	
	return 0;	
}
字符串相关的函数均以第一个出现的 '\0'作为结束符;
编译器总是会在字符串字面量的末尾添加'\0';

字符串字面量的本质为数组。

字符串、字符数组、字符指针有联系,但是是不同的。

下面的程序输出什么为什么?

int main()
{
    #define S1 "willwilling"
    #define S2 "willwilling"

    if( S1 == S2 )  //GCC的优化
    {
	    printf("Equal\n");
    }
    else
    {
	    printf("No Equal\n");
    }
    
    if( strcmp(S1, S2) == 0)
    {
	    printf("Equal\n");
    }
    else
    {
	    printf("No Equal\n");
    }
	
	return 0;	
}

编译运行:

delphi@delphi-vm:~/will$ ./a.out
Equal
Equal

S1 和 S2 的比较,在编译的时候,对于已经定义的字符串字面量,(已经存在于只读存储区)编译器会进行优化,S1和S2是同一个。

    printf("S1 = %p\n", S1);
    printf("S2 = %p\n", S1);

编译运行结果:

~/will$ ./a.out
Equal
Equal
S1 = 0x804851f
S2 = 0x804851f
字符串之间的相等比较需要用strcmp完成;
不可直接使用"=="进行字符串比较;

完全相同的字符串字面量的 == 比较结果为false(一些旧的编译器)

一些现在的编译器能够将相同的字符串字面量映射到一个无名字符数组,因此 "=="比较结果为true。
(不能编写依赖编译器的代码)

字符串循环右移:

	void right_shift_r(const char* src, char* result, unsigned int n)
函数功能: 将输入字符串src循环右移n位,result为输出结果;
要求: 以效率最高的方式实现
示例:
		"abcde"  --2--> "deabc"
		"abcde"  --8--> "cdeab"	
划重点:遇见问题首先分析特征:
循环右移,也就是每个元素的下标要发生变化: (i+3)%7
	void right_shift_r(const char* src, char* result, unsigned int n)
	{
		const unsigned int LEN = strlen(src);
		int i;
		
		for(i=0; i<LEN; i++)  //循环右移
		{
			result[(i+n) % LEN] = src[i];
		}
		
		result[LEN] = '\0';	
	}
	
	int main()
	{
		char result[255] = {0};
		
		right_shift_r("abcde", result, 2);
		printf("%s\n", result);
		
		right_shift_r("abcde", result, 8);
		printf("%s\n", result);
		
		return 0;
	}

编译运行:

	~/will$ ./a.out
	deabc
	cdeab
良好的分析问题的习惯,抓住重点才能更好的解决问题。


猜你喜欢

转载自blog.csdn.net/qq_28388835/article/details/80398480