常量字符串:

C语言中

void main(){
	char* p1 = "abcd";  //"abcd"是字符串常量
    char* p2 = "abcd";
	char* p3 = "china"; //"china"也是字符串常量
    printf("p1=%o\np2=%o\np3=%o\n", p1, p2,p3);
}

运行结果:

android 0宽字符_字符数组


p1和p2所指向的常量字符串内容相同而且地址也相同,

个人理解因为常量字符串位于静态区,p1指向的“abcd”已经分配了空间,p2所指向的常量字符串与p1指向的常量字符串相同,所以不需要另外开辟空间。有些文章说,这取决于编译器。


常量字符串内容不可更改,但可以通过下标和移动指针来访问

void main(){
	char* p1 = "abcd";  //"abcd"是字符串常量
	printf("%s\n",p1); //打印常量字符串
    printf("%c\n",*p1);  //获得第一个字符
	printf("%c\n",*(p1+1)); //可以通过移动指向常量的指针来访问常量字符串中的字符
	printf("%c\n",p1[1]);  //可以通过下标来访问常量字符串中的字符
	//p1[1]='d'; 编译没有问题,运行出错
}

运行结果

android 0宽字符_字符串_02


字符串输入:

void main(){
	char* p1;  //p1指针指向的地址为随机的,而且没有分配空间,禁止向p1指向的内容输入内容
	scanf("%s",p1);

	char* p2=""; //""常量字符串,只读不可写
	scanf("%s",p2);

	char* p3=NULL; //NULL为0,地质空间首地址,绝对不允许写入内容
	scanf("%s",p3);
}

以上程序运行都会出错,在C语言中正确的输入字符串,是通过做够长的字符数组来实现

void main(){
	char a[10];
	scanf("%s",a); //允许最大输入的字符个数为9,回车后在在字符末尾加'\0'
	printf("%s\n",a); //打印字符串
	for(int i =0 ;i < 10 ;i++){ //输出字符数组中的字符
		printf("%c\n",a[i]);
	}
}

运行结果:

android 0宽字符_字符数组_03

可见在4的末尾有一个不可见字符‘\0’,因为数组长度为10,后面5个元素没有赋值,所以出现乱码。通过gets输入字符串效果和scanf一致。但以下情况需要注意:

void main(){
	char a[3];
	gets(a); //可以输入超过2个的字符,scanf跟gets一致
	puts(a);
}

运行结果:

android 0宽字符_字符串_04


数组大小为3,按道理最多只能输入长度为2的字符串并在字符串最后补一个'\0',这样刚好存满整个数组。但现在输入了长度为4的字符串而且没有出错。但这只是幸运的,很多情况该程序会崩溃,因为数组越界,数组相邻的空间可能是重要的数据。所以C语言中数组越界的情况需要程序员自己去把握,数组越界带来的后果是很严重的。

还需要注意一点是,在C语言中用scanf输入字符串会以空格和回车符为间隔

void main(){
	char a[100];
	scanf("%s",a);
	puts(a);
}

运行结果:

android 0宽字符_字符数组_05

输入的字符串为“abc空格efg”,但实际存储的仅仅是“ abc”,所以当想给多个字符数组赋值时,可以通过空格或回车来输入。

void main(){
	char a[100];
	char b[100];
	char c[100];
	scanf("%s%s%s",a,b,c);
	puts(a);
	puts(b);
	puts(c);
}

运行结果:

android 0宽字符_字符串_06

android 0宽字符_字符数组_07

gets则不会出现这种情况,这是gets和scanf主要区别,gets和scanf还有一个区别就是gets只能输入一个字符串,而scanf可以输入多个。gets通过回车来确认字符串输入的结束,scanf通过回车或者空格符来确认字符串输入的结束

void main(){
	char a[100];
	gets(a);
	puts(a);
}

android 0宽字符_bc_08



void main(){
	char a[10]={"1234"}; //与char a[10]="1234"等效,在输入字符串最后会补一个'\0'
	printf("%s\n",a); //打印字符串
	for(int i =0 ;i < 10 ;i++){ //输出字符数组中的字符
		printf("%c\n",a[i]);
	}
}

运行结果:

android 0宽字符_bc_09

可见直接初始化字符数组,缺省的空间以'\0'填补,这点与scanf和gets不同,需要注意。


字符串的输出:

输出就比较简单,通过printf和puts就可以了,两者的区别在于puts输出字符串之后会换行。


字符数组:

字符数组很好理解无非就是char a[10];

void main(){
	char a[10]={'a','b','c'};
	for(int i = 0 ; i< 10;i++)
		printf("%c\n",a[i]);
}

运行结果:

android 0宽字符_字符数组_10

可见字符数组缺省的空间以‘\0’填补


void main(){
	char a[2]={'a','b'};
	puts(a);
}

运行结果:

android 0宽字符_android 0宽字符_11

若字符数组已满,而且最后一个字符不是'\0',则整体输出数组超出数组长度的内容会是乱码。