Day08——我真的很懒

Day08

睡不着…

纠正Day07的错误

数组可以动态定义

代码案例

#include <stdio.h>
int main()
{
	int i,n;
	printf("请输入一个常数\n");
	scanf("%d",&i);
    char a[i+1];
    printf("请开始输入字符\n");
	for(n=0;n<i;n++)
	{
		
		scanf("%c",&a[n]); 
		
	}
	a[i]='\0';//数组不会自动添加'\0',要主动去设置,这样才能输出字符串
	printf("你输入的字符串是;%s\n",a);
	return 0;
 } 

​ 在C99的数组标准中,有这样一句话,数组的尺寸如果是整型常量或整型常量表达式,或已确定数组尺寸时,

那么这个数组的类型不是一个可变长度的数组,否则,它就是可变数组

但是仍然存在一个问题,这行代码的输出结果:

请输入一个常数
3
请开始输入字符
abc
你输入的字符串是;
ab

会发现输出的字符比输入的字符少一位

原因:在使用第一个scanf函数时,按下了换行符,此时换行符就被保留在缓冲区内,下一个scanf读取到的第一个字符其实是换行符。

修改后:

#include <stdio.h>
int main()
{
	int i,n;
	printf("请输入一个常数\n");
	scanf("%d",&i);
    getchar()//用来读取输入的换行符
    char a[i+1];
    printf("请开始输入字符\n");
	for(n=0;n<i;n++)
	{
		
		scanf("%c",&a[n]); 
		
	}
	a[i]='\0';//数组不会自动添加'\0',要主动去设置,这样才能输出字符串
	printf("你输入的字符串是;%s\n",a);
	return 0;
 } 

数组的边界可以访问

#include <stdio.h>
int main()
{
	int i;
	int a[10];
	for(i=0;i<=10;i++)//故意写成这样引起数组越界问题
	{
		a[i]=i;
	 } 
	 for(i=0;i<=10;i++)
	 {
	 	printf("%d",a[i]) ;
	 }
	 return 0;
}

输出结果:

012345678910

奇怪之处:十一号元素可以输出

添加一句a[10]=111,仍然可以解决

可能新版的编译器对数组越界问题建立的保护机制,但最好不要这样做

字符数组

保存字符串的方式:

  • 字符串常量
  • 字符数组

字符串初始化

int main()
{
char a[]={'H','0','D','1','N','\0'};//不写元素个数,编译器会自动计算
char b[]={"H0D1N"};//可以使用字符串常量初始化
char c[]="H0D1N"//使用字符串常量初始化可以省略大括号
}

字符串处理函数

使用字符串处理函数需要加上头文件**#include <string.h>**

  • 获取字符串的长度:strlen
#include <stdio.h>
#include <string.h>
int main()
{
	char a[]="H0D1N";
	printf ("size of string=%d\n",sizeof(a)) ;
	printf ("strlen string=%u\n",strlen(a)) ;//strlen返回值为size.t定义在<string.h中,数据类型实际上是unsigned int ,所以用%u ,用%d也行 
	return 0;
 } 

输出结果:

size of string=6
strlen string=5

输出结果表明,strlen计算的是字符的个数,不包括数组后的’\0’,计算尺寸时才包括

  • 拷贝字符串:strcpy&strncpy

字符串的拷贝不能使用赋值号,使用赋值号会有报错

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[]="Original string";
	char str2[]="New string"; 
	char str3[100];
	strcpy(str1,str2);
	strcpy(str3,"Copy successfully");
	printf("str1:%s\n",str1);
	printf("str2:%s\n",str2);
	printf("str3:%s\n",str3);
	return 0;
} 

输出结果:

str1:New string
str2:New string
str3:Copy successfully

str2的内容复制到str1内后为何str1多出来的“tring”不被打印??

复制的过程将’\0’也复制了进去。编译器读到’\0’时让字符串结束了

注意!!!使用该函数时要保证目标字符数组足以容纳零数组(即逗号左边的容量容得下右边的),**

	strcpy(str2,str1);//错误的!!

但很奇怪,我这样写编译器还能正常输出。

  • strncpy
#include <stdio.h>
#include <string.h>
int main()
{
	char str1[]="To be or not to be";
	char str2[40];
	strncpy(str2,str1,5);//5是用于限制原字符串拷贝过去的长度,不包括结束符 
	str2[5]='\0';//由于结束符没有被拷贝,所以要手动添加!!!!!
	 printf("str2=%s\n",str2);
	return 0;
} 

输出结果

str2=To be
  • 连接字符串:strcat&strncat

​ 要求:目标数组(左边的)已经包含一个字符串,也可以是一个空字符串即“ ”,它会找到这个字符串的末尾,并把原字符串的一个拷贝给连接过去

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[]="H0";
	char str2[]="D1N";
	strcat(str1,str2);//str2也可以是一个字符串
	printf("str1=%s",str1);
	return 0;
 } 

输出:

str1=H0D1N

  • strncat

​ strncat与strncpy相似,都要添加一个参数来限定连接字符串的个数,唯一不同的是,strncat会在连接后字符末尾自动添加’\0’

  • 比较字符串:strcmp & strncmp

    用此函数来比较两个字符串是否完全一致若完全一致,返回值是0,若存在差异,根据情况返回大于0或小于0的值。

    原理:该函数从第一个字符开始,依次对比两个字符串每一个字符的ASC码,若第一个字符串字符的asc码小于对应的第二个字符串的字符,那么返回一个小于0的值,反之相反

例:

#include <stdio.h>
#include <string.h>
int main()
{
	char str1[]="H0D1N";
	char str2[]="H0D1N";
	if(strcmp(str1,str2)==0)//也可以写!strcmp(str1,str2),strcmp使用后的值即为返回值 
	{
		printf("两个字符串完全一致\n");
	}
	else
	{
		printf("两个字符串存在差异\n");
	}
	return 0;
 } 
  • strncmp

相比strcmp增加了一个参数n,用于指定只对比前面的n个字符

二维数组

问题引出:存放单科的成绩用一个数组就可以,若要存放多个科目呢???

二维数组,我们通常也称它为矩阵,将二维数组写成行和列的形式方便我们理解,例:每一列都为一个数据种类,每一行都属于一个个体的数据

二维数组的定义:类型 数组名 [常量表达式] [常量表达式]

int a[6][6]//六行六列
char b[4][5]//四行五列
double c[3][4]//三行四列

在内存中的存放:

c语言内,c语言是线性的,二维数组的存放依然是线性的

例: 要定义一个四行五列的二维数组b 。首先,定义一个一维数组 b[0],b[1],b[2],b[3]为里面的元素,进而,每一个元素再存放一个一维数组,可以理解为数组的嵌套,它都是以线性的方式存放的,可以去查找图片配合理解。

二维数组的访问

  • 数组名 【下标】【下标】注意下标的取值范围,下标从0开始!!!
a[0][0];//访问a数组中第一行第一列的元素
b[1][3];//访问数组b中第2行第4列的元素

二维数组的初始化

若没有初始化,数组内道德值为随机的

  • 由于二维数组在内存中是线性存放的,因此可以将所有数据写在一个花括号内;
int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};

代码:

#include <stdio.h>
int main()
{
	int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i,j;
	for(i=0;i<3;i++)
	{
		for(j=0;j<4;j++)
		{
			printf("%d ",a[i][j]);
		}
		putchar('\n');
	}
	return 0;
 } 

输出:

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,7,8},
             {9,10,11,12}};//会更直观
  • 二维数组也可仅对部分元素赋初值:
int a[3][4]={{1},{3},{5}};

联系上一种情况,上句的意思是,将三行的每行第一个元素赋值为1,3,5,而其余没有被赋值的自动填充为0。

  • 如果希望整个二维数组初始化为0,那么直接在大括号里写一个0即可
  • C99同样增加了一种新特性:指定初始化的元素,这样就可以只对数组中的某些指定元素进行初始化赋值,而未被初始化的元素自动赋值为0
int a[3][4]={[0][0]=1,[1][3]=2,[2][3]=4};
  • 二维数组的初始化也能偷懒,让编译器根据元素的数量计算数组的长度。但只有第一维的元素个数可以不写,其它维的个数必须写上
int a[][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12};

二维数组的转置

#include <stdio.h>
int main()
{
	int a[3][4]={1,2,3,4,5,6,7,8,9,10,11,12};
	int i,j;
	for(j=0;j<4;i++)
	{
		for(i=0;j<3;j++)
		{
			printf("%d ",a[j][i]);//将ij调换即可完成
		}
		putchar('\n');
	}
	return 0;
 } 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值