C语言基础入门——一维数组,字符数组


往期回顾

整型   int  4个字节
浮点型  float 4个字节
字符型  char 1个字节

system的使用:

函数原型:
包含在头文件stdlib.h中

int system(const char * command)

system(“pause”)可以实现冻结屏幕,便于观察程序的执行结果
system(“CLS”)可以实现清屏操作。

" "与’ '的区别:

单引号引起来的一个字符实际上代表一个整数,整数值对应于该字符在编译器采用的字符集中的序列值。因此,对于采用ASCII字符集的编译器而言,'a’的含义是0141(八进制)或者97(十进制)严格一致。

双引号引起来的字符串,代表的是一个指向无名数组起始字符的指针,该数组被双引号之间的字符以及一个额外的二进制值为零的字符’\0’初始化

一、一维数组

1.1 数组的定义

引言:
  某班学生的学习成绩、一行文字、一个矩阵等数据的特点如下:
(1)具有相同的数据类型
(2)使用过程中需要保留原始数据

C语言为了方便操作这些数据,提供了一种构造数据类型——数组.所谓数组,是指一组具有相同数据类型的数据的有序集合。

 1.1.1 数组定义表达式

一维数组的定义格式为:

类型说明符 数组名[常量表达式]int a[10];

定义了一个整型数组,数组名为a,它有10个元素。

 1.1.2 数组声明规则

  (1)遵循标识符命名规则;
  (2)在定义数组时,需要指定数组元素的个数,方括号中的常量表达式用来表示元素的个数,即数组的长度;
  (3)常量表达式中可以包含常量和符号常量,但不能包含变量。也就是说,C语言不允许对数组的大小做动态定义,即数组的大小不依赖于程序运行过程中变量的值。

 1.1.3 错误示范

int n;	//这是声明变量n,并不是声明数组
scanf("%d,&n");	//在程序中临时输入数组的大小
int a[n];
float a[0];  //数组大小为0没有意义
int b(2)(3);  //不能使用圆括号
int k=3,a[k];	//不能用变量说明数组大小

1.2 数组在内存中的存储

  语句int mark[100];定义的一维数组 mark在内存中的存放情况如图所示
一维数组mark在内存中的存放

每个元素都是整型元素,占用4字节;
数组元素的引用方式是“数组名[下标]",所以访问数组 mark中的元素的方式是mark[0],mark[1]…, mark[99]。
注意
没有元素mark[100],因为数组元素是从0开始编号的.

 1.2.1 一维数组的初始化

  • 在定义数组时对数组元素赋值
int a[10]={0,1,2,3,4,5,6,7,8,9};x
  • 可以只给一部分元素赋值
int a[10]={0,1,2,3,4};
定义a数组有10个元素,但花括号内只提供5个初值,这表示只给前5个元素赋初值,后面5个元素的值为0
  • 若要一个数组中全部元素的值为0,可写成
int a[10]={0,0,0,0,0,0,0,0,0,0};int a[10]={0};

+在对全部数组元素赋初值,数据个数已经确定,因此可以不指定数组长度

int a[]={1,2,3,4,5};

 1.2.2 举个例子

#include <stdio.h>
#include <stdlib.h>
//一维数组的传递,数组长度无法传递给子函数
//C语言的函数调用方式是值传递
void print(int b[],int len)
{
	int i;
	for(i=0;i<lenn;i++)
	{
		printf("%3d",b[i]);
	}
	b[4]=20;	//子函数中修改数组元素
	printf("\n");
}
//数组越界
//一维数组的传递
#define N 5
int main()
{	
	int j=10;
	int a[5]={1,2,3,4,5};//定义数组时,数组长度必须固定
	int i=3;
	a[5]=20;//越界访问
	a[6]=21;
	a[7]=22;
	print(a,5);
	printf("a[4]=%d\n",a[4]);	//a[4]发生改变
	system("pause");

在这里插入图片描述

解释:
  先定义的变量j的地址大于后定义的变量i的地址,所以先定义的变量放在高地址,后定义的变量放在低地址。其实每个函数开始执行时,系统会为其分配对应的函数栈空间,而变量j、变量a、变量i都在 main函数的栈空间中,由于后定义的变量在上面,因此这种效果称为栈向上增长。
  在监视窗口中输入sizeof(a),可以看到数组a的大小为20字节,计算方法其实就是sizeof(int)*5:数组中有5个整型元素,每个元素的大小为4字节,所以共有20字节.访问元素的顺序是依次从a[0]到a[4], a[5]=20,a[6]=21均为访问越界.下图也显示了代码运行情况,从中看出,执行到第26行时,数组 a与变量j中间的8字节的保护空间已被赋值(微软公司的编译器在不同的变量间设置了保护空间),而执行到第27行时,变量j的值被修改了,这就是访问越界的危险性——未对变量j赋值,其值却发生了改变!
在这里插入图片描述
数组访问越界的错误提醒:
Run-Time Check Failure #2 - Stack around the variable ‘a’ was corrupted.

注意
 数组在传递时,元素个数传递不过去,如果想知道数组里面有多少个元素,一开始传递的时候,再写一个int len;
在这里插入图片描述

二、字符数组

2.1 字符数组的定义及初始化

初始化字符数组时,一定要让字符数组的大小比看到的字符串的长度多
 字符数组的定义方法:

char c[10];

字符数组的初始化可以采用以下方式:

  • 对每个字符的单独赋值进行初始化
c[0]="1";c[1]=" ";c[2]="a";c[3]="m";c[4]="";c[5]="h";c[6]="a";c[7]="p";c[8]="p";c[9]="y";
  • 对整个数组进行初始化:
char c[10]={"I","a","m","h","a","p","p","y"}

但是,一般不用以上两种初始化方式,因为字符数组一般用来存取字符串,通常采用的初始化方式时cahr c[10]=“hello”。因为c语言规定字符串的结束标志为’\0’,而系统会对字符串常量自动加一个‘\0’.
为了保证处理的方法一致,一般会人为地在字符数组中添加‘\0’,所以字符数组存储的字符串长度必须比字符数组少一个字节。
举个例子
char c[10]最长存储9个字符,剩余的一个字符用来存储’\0’

字符数组初始化及传递

#include <stdio.h>
#include <stdlib.h>
void printf(char c[])
{
	int i=0;
	while(c[i])
	{
		printf("%c",c[i]);
		i++;
	}
	printf("\n");
}
//字符数组存储字符串,必须存储结束符'\0'
//scanf读取字符串时使用%s
int main()
{
	char c[5]={"h","e","l","l","0"};
	char d[5]="how";
	printf("%s---%s\n",c,d);//会发现打很多“烫”字
	scanf("%s%s",c,d);
	printf("%s---%s\n",c,d);
	print(c);
	system("pause");
	return 0;
}

输出结果如下:
在这里插入图片描述
为什么对数组赋值“hello”却打印出很多“烫”字?
因为printf通过%s打印字符串时,原理是依次输出每个字符,当读到结束符’\0’时,结束打印;
scanf通过%s读取字符串时,对c和d分别输入“are”和“you”(中间记得加空格),scanf在使用%s读取字符串时,会忽略空格和回车。

字符数组的数组名里村的就是字符数组的起始地址

2.2 gets函数与puts函数

 2.2.1 gets函数

引言:
gets函数类似于scanf函数,用于读取标准输入。
通过上面我们已经知道scanf函数在读取字符串时遇到空格就认为读取结束,这样没办法把一行带空格的字符串存入到一个数组中,所以当输入字符串存在空格时,我们需要使用gets函数进行读取。

 gets函数格式如下:

char *gets(char *str);

原理:gets函数从STDIN(标准输入)读取字符并把他们加载到str(字符串)中,直到遇到换行符(\n)或达到EOF。
注意:gets遇到\n后,不会存储\n,而是将其翻译为空字符’\0’

 2.2.2 puts函数

引言:
puts函数类似于printf函数,用于输出标准输出
puts输出的就是字符串,printf可以支持多种格式输出
 puts函数格式如下:

int puts(char *str);

2.3 str系列字符串操作函数

str 系列字符串操作函数主要包括strlen、strcpy、strcmp、strcat等;

(1)strlen函数用于统计字符串长度,不考虑后面的\0;
(2)strcpy函数用于将某个字符串复制到字符数组中
(3)strcmp函数用于比较两个字符串的大小,相等返回为0,若前面字符串大于后面的字符串,则返回为1,反之,为-1;比较的是对应字符的ASCII码值
(4)strcat函数用于将两个字符串连接到一起;

#include <string.h>
size_t strlen(char *str);
char *strcpy(char *to,const char *from);
int strcmp(const char *str1,const char*str2);
char *strcat(char *str1,const char *str2);

对于传参类型char*,直接放入数组的数组名即可

str系列字符串操作函数的使用!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int mystrlen(char [])
{
	int i=0;
	while(c[i++]);
	return i-1;
}
//strlen统计字符串长度
int main()
{
	int len;//用于存储字符串长度
	char c[20];
	char d[100]="world";
	while(gets(c)!=NULL)
	{
		puts(c);
		len=strlen(c);
		printf("len=%d\n",len);
		len=mystrlen(c);
		printf("mystrlen len=%d\n",len);
		strcat(c,d);
		strcpy(d,c);//c中的字符串复制给d
		puys(d);
		printf("c?d %d\n",strcmp(c,d));
		puts(c);
	}
	system("pause");
	return 0;
}
  •  通过gets函数循环读取字符串的目的是,方便不断地输入不同的字符串并查看程序的执行效果,并在修改程序中的某部分后能够以多种输入进行测试,如果要结束循环,按ctrl+z。
  •  strcpy函数用来将字符串中的字符逐个地赋值给目标字符数组。例如我们将c复制给d,就是将c中地每个字符依次赋值给d,也会将结束符赋值给d。
    注意,目标数组一定要大于字符串大小,即sizeof(d)>strlen©,否则会造成访问越界。
  •  strcmp函数用来比较两个字符串的大小,由于字符数组c中的字符串与d相等,所以这里的返回值为0。
    如果c中的字符串大于d,那么返回值为1;如果c中的字符串小于d,那么返回值为-1,如何比较两个字符串的大小呢?

从头开始,比较相同位置字符的ASCII码值,若发现不相等则直接返回,否则接着往后比较。

举个例子
strcmp(“hello”,“how”)的返回值是-1,即hello<how。因为第一个字符h相等,接着比较第二个位置的字符,e的ASCII码值小于o的,然后返回-1。
 strcat函数用来将一个字符串接到另一个字符串的末尾。

举个例子
字符数组c中存储的是hello,我们将d中的world与c拼接,最终结果是helloworld。
注意目标数组必须大于拼接后的字符串大小,即sizeof©>strlen(“helloworld”).

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值