C语言的学习(八)---二维数组和字符型数组
本文介绍了C语言中二维数组和字符数组的相关知识。二维数组采用行优先存储方式,初始化可分为全部初始化、按行初始化和部分初始化,访问需使用双重循环。字符数组主要用于处理字符串,其特点是自带结束符'\0',实际长度与数组长度可能不同。文中详细讲解了字符串的输入输出函数(gets/puts)、长度统计(strlen)、拷贝(strcpy)、拼接(strcat)和比较(strcmp)等操作的实现原理及注意事
目录
一、二维数组介绍和特点
二维数组是难点,但不是重点
1.内存本身是线性
2.安行优先存储
3.先放第一行,再放第二行
int a[3][4];//开空间 = 3*4*sizeof(int) = 48
二、二维数组初始化与赋值
1.初始化:
//初始化
int a[3][4] = {1,2,3,4,5,6,7,8,9,10,11,12}; //全部初始化
int a[3][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12}}; //按行初始化
//部分初始化
int a[3][4] = {1,2,3,4,5,6};
//不初始化为随机值
int a[3][4] ;
//初始化为0
int a[3][4] = {};
int a[3][4] = {0};
//行数可以省略 列数不能省略
int a[][4];
//int[4] a[] ; //一维数组
2.赋值:
数组名[行下标][列下标] //下标运算
访问: 先访问行下标,然后列下标
想要访问所有元素, 一定得配合两层循环
for(i=0;i<row;i++)
{
for(j=0;j<4;j++)
{
printf("%d ",a[i][j]);
}
}
三、字符型数组介绍和特点
在C语言中,是将字符申作为字符数组来处理的。例如用一个一维的字符数组来存放字符串"I am a boy",字符串中的字符是逐个存放到数组元素中的。这个字符串的实际长度与数组长度相等。在实际工作中,人们关心的往往是字符串的有效长度而不是字符数组的长度。例如,定义一个字符数组长度为100,而实际有效字符只有40个。为了测定字符串的实际长度,C语言规定了一个"字符串结束标志",以字符\0'作为标志。如果有一个字符串,前面9个字符都不是空字符(即\0),而第10个字符是\0',则此字符串的有效字符为9个。也就是说,在遇到字符‘\0'时,表示字符串结束,由它前面的字符组成字符串。
系统对字符串常量也自动加一个'\0'作为结束符。例如"C_Program"共有9个字符,但在内存中占10个字节,最后一个字节\0'是由系统自动加上的。字符串作为一维数组存放在内存中。
有了结束标志\0后,字符数组的长度就显得不那么重要了。在程序中往往依靠检测\0'的位置来判定字符串是否结束,而不是根据数组的长度来决定字符串长度。当然,在定义字符数组时应估计实际字符串长度,保证数组长度始终大于字符串实际长度。如果在一个字符数组中先后存放多个不同长度的字符串,则应使数组长度大于最长的字符串的长度。
说明:'\0'代表ASCII码为0的字符,从ASCII码表中可以查到,ASCII码为0的字符不是一个可以显示的字符,而是一个"空操作符",即它什么也不做。用它来作为字符串结束标志不会产生附加的操作或增加有效字符,只起一个供辨别的标志。
char s[10]; //字符型一维数组
//字符型数组 --- 要存放字符数据
char s[10] = {'a','b','c'};
//字符型数组
char s[10] = {"hello world!"};
字符型数组 --- 主要用来存放字符串数据
字符串: ---双引号扩起来的一组字符
"123"
"hello"
字符串说明:
1.字符串本身 在C语言中是按照 字符数组 处理!
"hello"
字符数组 --数组 --数组特点
a.连续空间
b.单一性
c.有序性
"hello"=内存中=> ['h''e''l''l''o''\0']
2.字符串 会自己携带一个结束标志
'\0' 是 编码值为 0的那个字符
3.字符串长度 vs 数组长度:
char s[10]; //数组长度为10 ,字符串长度为9
"hello" //字符串长度为5 ---表示的是 '\0'前的有效字符个数
1.输出字符串:
puts()函数:
int puts(const char *s);
功能:
输出字符串
参数:
@s 需要字符串起始地址
返回值:
成功 返回非负值它的原理是:
int i = 0; while(s[i] != '\0') { putchar(s[i]); ++i; } putchar('\n');这串代码等价于puts(s)
也可以用printf()来实现
printf("%s",s);
2.输入字符串:
gets()函数
har *gets(char *s);
功能:
输入一个字符串 存放到s指定一块空间
参数:
@s 存放字符串的空间 ---空间首地址
返回值:
返回sgets(s);但是并不推荐使用gets函数,它很容易导致数组越界(即数组长度不够)
scanf也能输入字符串,但是字符串中,不能有空格scanf("%s",&s);因为在scanf()函数中的分隔符是空格
所以如果要打印有空格的字符串就用do-while循环:
do { s[i] = getchar(); }while(s[i++] !='\n') { s[i-1 ] = '\0'; }
3.统计字符串长度:
strlen()函数
#include <string.h>
size_t strlen(const char *s);
功能:
统计字符串长度
参数:
@s 存在字符串的一块内存空间地址
返回值:
返回对应字符串才长度它的原理是:
'\0'前面有效字符的个数
判断是否到达'\0'结束标志,
没有就计数一次i=0; while(s[i] != '\0') { i++; } printf("字符串有效长度为%d\n",i);
4.拷贝字符串:
strcpy(目的地,源)函数
char *strcpy(char *dest, const char *src);
功能:
拷贝字符串
将src字符串 拷贝到 dest中
参数:
@dest 目的字符串
@src 源字符串
返回值:
成功 返回的是 dest
失败 NULL它的原理是:
while(s[i] != '\0') { s2[i] = s[i]; i++; } s2[i] = s[i];
5.字符串拼接(重点)
strcat(目的地,源)函数
char *strcat(char *dest, const char *src);
功能:
字符串拼接函数
将src拼接到dest中
参数:
@src 源字符串
@dest 目标字符串
返回值:
成功 返回dest
失败 NULL它的原理:
思路:
step1 找到s1的'\0'位置
step2 从这个位置 将 s2中字符串 复制过来
step3 s1是否有'\0' 如果没有 自己手动加一个 保证是字符串
i =0; while(s[i] !='\0')//这个就是不考虑数组长度了,直接考虑字符串 { ++i; } int j =0; while(s2[j] !='\0') { s[i] = s2[j]; i++;j++; } s[i] = '\0';我一开始写错了:写成了。犯错的点在依然是用数组的方式在操作
for(i=0;i<10;i++)//依然是用数组的方式在操作,要考虑字符穿 //要转变过来,我们不关心数组长度,只需要看标志符\0就行 { if(s[i]= '\0') { int j=0; while(s2[i] !='\0') { s[i+j] = s2[j]; j++; } } }
6.字符串比较:
strcmp(s1,s2)函数
int strcmp(const char *s1, const char *s2);
功能:
比较字符 s1 和 s2
返回值:
s1 > s2 结果 >0
s1==s2 结果==0
s1 < s2 结果<0它的原理是
字符串比较的规则与其他语言中的规则相同,
即:
对两个字符串自左至右逐个字符相比(按ASCII码值大小比较),直到出现不同的字符或遇到'\0'为止。
如全部字符相同,则认为相等;
若出现不相同的字符,
则以第一个不相同的字符的比较结果为准。
比较的结果由函数值带回。
(1)如果字符串1=字符串2,则函数值为0。
(2)如果字符串1>字符串2,则函数值为一个正整数。
(3)如果字符串1<字符串2,则函数值为一个负整数。//比较字符串大小 i=0; // while(s[i] =s3[i] ||s[i]!='\0' ||s3[i]!='\0')我写的 while(s[i] ==s3[i] &&s[i]!='\0' &&s3[i]!='\0')//正确写法,有两处错误, //为什么是与呢,因为这个式子是为真的时候循环,为假才跳出,我写的时候想成了为真跳出循环 { i++; } printf("s[i] -s3[i] = %d\n",s[i] - s3[i]);我写错了,我写的while(s[i] =s3[i] ||s[i]!='\0' ||s3[i]!='\0'),在条件这里有两个要用&&不是用|| ,我写的时候想成了为真跳出循环
四、小结
补充知识点,字符数组的数据存入是系统将字符串保存到字符串常量区后自动添加标识符'\0'再把它存到栈上,
如这个例子就是 char[5] = "hello"这个存入内存中越界了

更多推荐
所有评论(0)