C语言: 字符串 -1

字符串是一个或多个字符的序列。在 C 语言中没有专门用于存储字符串的变量类型,字符串被存储在 char 类型的数组中。数组由连续的存储单元组成,字符串中的字符被存储在相邻的存储单元中,每个单元存储一个字符。如下图:

注意: 数组末尾的字符 '\0' 是空字符( null character) ,在 C 语言中它标记字符串的结束。空字符不是 0 ,它是非打印字符,其 ASCII 码值是 (或等价于)0 。 C 语言中,字符串一定以 空字符结尾,意味数组的容量至少要比待存储的字符的字符数多 1 。

 

1 字符串的定义和初始化:

 

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>


void main()
{
    //char str[] = { 'c','a','l','c' }; //错误,没有结束标志 '\0'
	//char str[5] = { 'c','a','l','c','o' }; // 错误,字符超过数组元素个数

	//数组 如果初始化时初值个数小于数组长度,系统会为剩余元素自动赋值为'\0'
    char str[10] = { 'c','a','l','c' };
	char array[10] = "write";

	//指针
	char* pstr = "你好,世界!";
	char* p = pstr;//存储字符串首地址
	
	printf("字符串首地址=%x \n", str);  //打印字符数组的首地址

	printf("str=%s\n", str);// 遇到 '\0'为止,没有遇到一直向前
	printf("array=%s\n", array);

	//利用指针循环输出字符串
	while (*pstr)//值为0终止 *pstr='\0'
	{
		putchar(*pstr);
		pstr++; //指针向前
	}
	puts("\n");

	
	//通过sizeof运算符求出str所占的字节
	printf("字符数组 array 字节大小=%d ;常量 write 的字节大小=%d \n", sizeof(array), sizeof("write"));

	//变量字符数组:
	for (int i = 0; i < 10; i++)
	{
		printf("str[%d]=[%c] \n", i, str[i]);
	}


    system("pause");
}

此外,C 语言还允许用字符串常量来初始化字符数组:如:char c[100] ={"C Program"};

示例:随机执行命令

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h> //包含时间处理头文件

void main()
{
	time_t ts;//声明一个时间类型变量
	srand((unsigned int)time(&ts));//取时间的随机数种子
	int num = rand() % 10; //取 0--9 之间

	char str[10][10] = { {"calc"},{"notepad"},{"write"},{"tasklist"},{"ipconfig"},{"color 4f"},{"mspaint"},{"mstsc"},{"control"},{"osk"} };

	system(str[num]);

	getchar();
}

2 字符数组的输入和输出:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>



void main()
{
	//1 声明 指针 和 字符数组
	char* p;
	char str[20];

	//2:初始化 str由若干元素组成,每个元素放一个字符;而cp中存放字符串首地址
	//str = "AAAAAAA"; //错误 str是地址常量;p是地址变量
	//p = "chian"; //p接受键入字符串时,必须先开辟存储空间

	//初始化字符数组
	char arr[50] = { 0 };//初始化字符数组
	scanf("%s", arr);//接受键盘输入初始化
	printf("arr=%s\n", arr);

	//初始化字符指针
	//char* string = NULL; //用指针初始化,必须让指针存储一片可以读写的内存 (这样的初始化是错误的)
	char* string =(char *) malloc(sizeof(char) * 30); //分配 30个字节存储空间 
	/*
	 指针初始化方式2,指向数组的首地址
	 char array[30]={0};
	 char *string=array; 
	*/
	scanf("%s", string);
	printf("string=%s\n", string);
	
	if (string != NULL)
	{
		free(string); //释放内存
	}

	system("pause");

}

注意 下面情况:

  str[100]代表第101个元素,下面的初始化就会越界

            char str[100];

            str[100]="ABCD";     错误的赋值, 数组将越界

            str="ASSAHJS";        错误的赋值   str是数组名,是常量不可以修改和赋值。

char* p = "ADDDDDD";        这中是正确的赋值,指针 p 存储了常量("ADDDDDD")的首地址

gets输入字符串和puts输出字符串:

 

    char s[100];
    gets(s);//输入
    puts(s);//输出

gets(s)函数与scanf("%s:",&s)/* scanf("%s",s) */相似,但不完全相同,

使用scanf("%s",&s);  函数输入字符串时存在一个问题,就是如果输入了空格会认为字符串结束,空格后的字符将作为下一个输入项处理,但gets()函数将接收输入的整个字符串直到遇到换行为止。
puts()函数的作用与语句“printf("%s\n",s);的作用相同。

 

字符串与字符数组的关系:

字符串用一维字符数组存放 。字符数组具有一维数组的所有特点,数组名是指向数组首地址的地址常量,数组元素的引用方法可用指针法和下标法,数组名作函数参数是地址传递等。

区别  ,存储格式:字符串结束标志,赋值方式与初始化,输入输出方式:%s  %c。

字符数组作为函数参数:

函数的副本机制,只有数组例外,数组拷贝非常耗费时间与空间。数组传递过来的实际上是指针就是地址。

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h> //包含时间处理头文件


//函数的副本机制,只有数组例外。
void Change(char str[])
{
	printf("Change= %d \n", sizeof(str)); //传递指针
	*str = 'A'; //改变指针指向的内容实际上就是改变数组的本身。
	*(str + 1) = 'B';
}

void main()
{
	//字符数组存储字符串就具备所有数组的特性
	char str[100] = "calc";
	printf("%s\n", str);

	//str = "ASSSASASA";//str是常量,不能赋值

	//遍历
	for (int i = 0; i < 8; i++)
	{
		printf("%c ,%c \n", str[i], *(str + i)); //下标和指针
	}

	printf("\n");

	char* ch = str; //数组名是常量,不可以赋值
	printf("--------------------");
	while (*ch) //用指针访问
	{
		putchar(*ch);
		ch++;
	}
	printf("--------------------\n");
	//system(str);//执行
	printf("Main= %d \n", sizeof(str)); //数组数据大小
	Change(str);

	printf("%s \n", str);

	system("pause");
}

 

总结:

1:用字符数组和字符指针变量都能实现字符串的存储和运算,但它们二者之间是有区别的,不应混为一谈,主要有以下几点。

  1. 字符数组由若干个元素组成,每个元素中放一个字符,而字符指针变量中存放的是地址(字符串第1个字符的地址),决不是将字符串放到字符指针变量中。
  2.  赋值方式。可以对字符指针变量赋值,但不能对数组名赋值。( char *a; a=”I love You!”;   对 ),(char str[14];str[0]=’I’;   对) ,(char str[14]; str=”I love You!”; 错)
  3. 初始化的含义 : (char *a=”I love You!”;与 char *a; a=”I love China!”;等价),(char str[14]= ”I love China!”;与 char str[14]; str[]=”I love China!”;    不等价
  4. 存储单元的内容 ,编译时为字符数组分配若干存储单元,以存放各元素的值,而对字符指针变量,只分配一个存储单元存储地址。(char *a; scanf(“%s”,a);   错   ) ,(char *a,str[10];  a=str;  scanf (“%s”,a);      对)。          

2:字符指针,改变地址,可以决定字符串从哪里开始

示例:

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>


void main()
{
	char* p = "123ABCDE";
	p = p + 3;
	printf("p=%s", p);

	char* p1 = "12345ADSGZ";

	printf("\n 通过指针的方式打印出字符串 \n");

	for (char* pstr = p1; *pstr != '\0'; pstr++)
	{
		printf("%c \n", *pstr);
	}

	system("pause");
}

3:指针变量的值是可以改变的,而数组名代表一个固定的值(数组首元素的地址),不能改变。

int main()
{  
    char *a="I love China!";//不能改为char a[]=“I love China!”;
    a=a+7;   
    printf(“%s\n”,a);   
    return 0;
}

4:字符数组中各元素的值是可以改变的,但字符指针变量指向的字符串常量中的内容是不可以被取代的。

5:用指针变量指向一个格式字符串,可以用它代替printf函数中的格式字符串。

char *format;
format=”a=%d,b=%f\n”; 
printf(format,a,b);
相当于printf(“a=%d,b=%f\n”,a,b);

6:printf和scanf

          char ch[100];

          scanf(“%s”,ch);   /*空格、制表符、换行为分隔符*/

          printf(“%s”,ch);   /*输出后不会自动换行*/

7:gets和puts

          char ch[100];

          gets(ch);    /* 回车为分隔符 */

          puts(ch);   /* 输出后会自动换行 */

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值