Linux嵌入式学习—c语言数组
一、一维数组
1.1一维数组的定义
定义一维数组,首先我们得先让计算机知道,哪些数据可以组成数组,一个数组中有多少元素(长度),以及数据 的类型。
所以在使用数组的时候,必须定义数组。
- 一维数组的一般形式
数据类型 数组名[元素个数];
例如:
a[5]
表示数组a中有10个元素,数组的元素长度为10。数组下标是从0开始的,a[0],a[1],a[2],a[3],a[4].没有数组元素a[5]
- int a[3+5];是正确的
- int a[n];是错误的,不允许对数组大小做动态定义。
以下是错误写法:
int n;
scanf("%d",&n);//临时输入数组大小
int a[n];
在定义完数组后,内存会划出一片连续的空间,存放一个有5个元素的数组。
#include<stdio.h>
int main()
{
int a[5];
//计算数组大小
//用sizeof(数组名)
printf("%d",sizeof(a));
return 0;
}
此时的空间大小为4*5=20字节
【1】对10个数组元素依次赋值为0,1,2,3,4,5,6,7,8,9,要求逆序输出。
- 十个元素且还是整型,所以我们确定数组的类型及长度int a[10];
- 依次赋值,可以考虑使用循环赋值,且赋值是从0依次增加1.
#include<stdio.h>
int main()
{
int a[10];
int i;
for(i = 0;i<10;i++) //对数组赋值,下标是从0开始的
a[i] = i;
for(i = 0;i<10;i++)//打印数组
printf("%d ",a[i]);
return 0;
}
1.2一维数组的初始化
- 定义数组就初始化。
int a[5] = {0,1,2,3,4};
//a[0]=0;a[1]=1;a[2]=2;a[3]=3;a[4]=4;
- 部分初始化,其余默认值为0。
int a[5]={0,1,2};
//a[0]=0;a[1]=1;a[2]=2;a[3]=0;a[4]=0
- 数组元素值全部为0。
int a[5]={0,0,0,0,0,0};
int a[5]={0};
- 对全部元素赋初值,可以不用写数组的长度。系统会根据数组中数据个数确定数组的长度
int a[]={1,2,3,4,5};
对于没有被初始化的数组,系统会自动初始化为0(数值型),‘\0’(字符型数组),NULL空指针(指针型数组)
1.3一维数组程序举例
用数组来处理Fibonacci数量问题
代码如下:
#include <stdio.h>
int main()
{
int i;
int f[20]={1,1};//对f[0]和f[1]赋初值为1,1 ,计算前20个数
for(i =2;i<20;i++)
f[i]=f[i-2]+f[i-1];//当i=2时,f[2]=f[0]+f[1];
for(i=0;i<20;i++)
{
if(i%5==0)//控制每行输出5个数
printf("\n");
printf("%12d",f[i]);
}
printf("\n");
return -1;
}
运行结果
1.4冒泡排序(从小到大排列)
每次将相邻的数字进行比较,把小的调到前面。
n个数字,则要进行n-1趟比较。(总的)
第1次的比较需要进行n-1趟,
如果有第j次则要进行n-j趟
代码:
#include <stdio.h>
int main()
{
int a[10];
int i,j,t;
printf("please 10 numbers:\n ");
for(i = 0;i<10;i++)//输入十个数据
scanf("%d",&a[i]);
for(i=0;i<10-1;i++)//n个数进行n-1趟比较
{
for(j=0;j<9-j;j++)//每一次的比较是n-j
if(a[i]>a[i+1])
{
t = a[i];
a[i] = a[i+1];
a[i+1] = t;
}
}
printf("the sort number:\n");
for(i=0;i<10;i++)
printf("%d ",a[i]);
printf("\n");
return -1;
}
结果:
二、二维数组
2.1二维数组的定义
二维数组常称为矩阵,常常用行和列来表示二维数组。
也常常称二维数组是由多个一维数组组成。
二维数组的定义:
数据类型 数组名[行][列]
元素个数=行x列
行序号和列序号都是从下标0开始的
例如:
int a[3][4];
//定义了一个类型为int的,3行4列的二维数组
其中每一行是由四个元素组成,每一行可以看成一维数组。
a[3][4];
a[0]a[1]a[2]是三个一维数组的名字
a[0]-----a[0][0] a[0][1] a[0][2] a[0][3]
a[1]-----a[1][0] a[1][1] a[1][2] a[1][3]
a[2]-----a[2][0] a[2][1] a[2][2] a[2][3]
注意:二维数组的各个元素在内存中是连续存放的,是线性的
2.2二维数组的初始化
- 直接赋值
a[3][4]={{1,2,3,4},{5,6,7,8},{9,10,11,12}};
- 不用内花括号,元素在内存中的排列顺序对各元素赋初值
a[3][4]={1,2,3,4,5,6,7,8,9,11,10,12};
- 对部分元素赋初值,其余元素自动为0.
a[3][4]={{1},{5},{9};
1 0 0 0
5 0 0 0
9 0 0 0
a[3][4]={{1},{},{9}};//对第2行不赋初值
- 行数不能省略,列数可以省略。系统会根据元素个数和二维的长度计算一维的长度
a[3][4]={1,2,3,4,5,6,7,8,9,11,10,12};
等价于
a[][4]={1,2,3,4,5,6,7,8,9,11,10,12};
2.3二维数组程序举例
1.将一个二维数组行和列互换,存到另外一个二维数组中。
a = [ 1 2 3 4 5 6 ] a=\begin{bmatrix} 1 & 2&3 \\ 4& 5&6 \end{bmatrix} a=[142536]
转置
b
=
[
1
4
2
5
3
6
]
b=\begin{bmatrix} 1 & 4 \\ 2& 5\\ 3&6 \end{bmatrix}
b=⎣⎡123456⎦⎤
#include<stdio.h>
int main()
{
int a[2][3] = {{1,2,3},{4,5,6}};
int b[3][2],i,j;
printf("arr a:\n");
for(i = 0;i<2;i++){//a数组每一行的元素
for(j=0;j<3;j++){//每一行的元素
printf("%5d",a[i][j]);//输出a数组的元素
b[j][i] = a[i][j];//把a数组的值赋值为b数组
}
printf("\n");
}
printf("arr b:\n");
for(i=0;i<3;i++){//打印b数组
for(j=0;j<2;j++){
printf("%5d",b[i][j]);
}
printf("\n");
}
}
2.有一个3x4的矩阵,求出值最大的那个元素值以及下标
#include<stdio.h>
int main()
{
int a[3][4]={{12,34,45,1},{54,90,32,9},{11,80,67,30}};
int i,j;
int max=a[0][0];//假设最大的是a[0][0]
int nrow,colum;//记录行号和列号
for(i=0;i<3;i++){
for(j=0;j<4;j++)
if(a[i][j]>max){
max=a[i][j];
nrow=i;
colum=j;
}
}
printf("max=%d\nrow=%d\ncolum=%d\n",max,nrow,colum);
return 0;
}
三、字符数组
字符型的数据是以ASCII码存放在存储单元的,一般只占一个字节。
字符串可以存放在字符串数组中。
3.1字符数组的定义和初始化
字符串数组和整数型数组的定义类似。
例如:char[10];
c[0]=‘I’;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 a[10]={'I',' ','A','M',' ','A',' ','B','O','Y'};
- 字符个数小于字符数组的长度,其余元素自动定为空字符(‘\0’)
char a[10]={'H','A','P','P','Y'};
- 字符数组可以省略长度,根据初值个数确定长度。
char a[]={'I',' ','A','M',' ','A',' ','B','O','Y'};
- 字符串常量初始化数组,也可以省略花括号
char a[]={"Happy"};//长度不是为5,而是6
char a[]="Happy";
/*=====等价于====*/
char a[]={'H','a','p','p','y'.'\0'};
- 也可以定义二维字符数组的初始化,(菱形)
char a[5][6]={{' ',' ','*'},{' ','*',' ',' ','*'},
{'*',' ',' ',' ',' ','*'},{' ','*',' ',' ', '*'},{' ',' ','*'}};
1.输出字符串
#include<stdio.h>
int main()
{
char a[10]={'I',' ','A','M',' ','A',' ','B','O','Y'};
int i;
for(i=0;i<10;i++)
printf("%c",a[i]); //字符输出用%格式
return 0;
}
2.输出一个菱形
#include<stdio.h>
int main()
{
char a[5][6]={{' ',' ','*'},{' ','*',' ',' ','*'},
{'*',' ',' ',' ',' ','*'},{' ','*',' ',' ', '*'},{' ',' ','*'}};
int i,j;
for(i=0;i<5;i++){
for(j=0;j<6;j++){
printf("%c",a[i][j]);
}
printf("\n");
}
return 0;
}
3.1.2字符串和字符数组的结束标志
在实际的应用中,我们更关注的是字符串的有效长度,并非是数组的长度。
例如:字符串长度与字符串的长度相等。
char a[15]={'i',' ','a','m',' ','a',' ','s','t','u','d','e','n','t','.'};
如果改为charca[100],那字符串的有效长度是多少呢?
c语言规定以字符’\0’作为字符串的结束标志,遇到’\0’,表示字符串结束。
注意:
1.在用字符数组存储字符串常量的时候,系统会自动加一个’\0’作为结束符
2.'\0’的ASCII码为0的字符,是一个空操作符,表示什么也不用做,只提供一个可以辨别的标志。
例如:
printf("Hello world! \n");
系统自动在’\n’的后面加上‘\0’的标志。作为字符串结束的标志,用printf打印输出的时候,每打印一个字符就检查是否是’\0’,如果是就停止打印。
和之前的初始化字符串数组一样
char a[]={"Happy"};//长度不是为5,而是6
char a[]="Happy";//系统会自动分配一个'\0'
/*=====等价于====*/
char a[]={'H','a','p','p','y'.'\0'};
Happygirl字符串的存储情况:
如果在Happygirl字符串前面输入welcome赋值给数组,如果不加’\0’的情况:就会输出welcomerl.新字符串和老字符串无法区分。
如果在welcome后面加一个’\0’就代替了’r’
而在输出字符串数组的时候,是遇到’\0’就停止输出,所以最后输出字符串的时候只输出welcom,而不是welcomel
3.2字符数组输入输出
字符输入输出有两种方式:
- 用%c逐个输入输出字符
例如:
char a[3]={'B','O','Y'};
int i;
for(i=0;i<3;i++)
printf("%c",a[i]);//逐个输出字符
- 用%s输入整个字符串
例如:
char a[10]={"world"};//字符串长度为5,加上'\0'为6个字节
printf("%s\n",a);//遇到'\0'就停止输出,就只输出world
注意:
- 输出的字符不包含’\0’,因为它是空操作符,只起标志作用
- printf(“%s”,数组名);是数组名,不是数组元素a[0]
- 无论数组长度多大,遇到’\0’就结束
3.用scanf输入字符串,输入的字符串长度应该小于字符串数组的长度
输入多个字符串的时候,应该以空格分隔。
如果输入的是字符数组名,不能加&,因为数组名代表数组的首地址。
例如:从键盘上输入a good boy
#include<stdio.h>
int main()
{
char s1[5],s2[5],s3[5];
scanf("%s%s%s",s1,s2,s3);
puts(s1);
puts(s2);
puts(s3);
return 0;
}
运行结果:
数组的状态:
如果改为:
#include<stdio.h>
int main()
{
char a[13];
scanf("%s",a);
puts(a);
return 0;
}
运行结果:
因为系统把空格字符串作为输入的字符串之间的分隔符,因此只把空格前的字符"a"送到a数组中,把“a”作为一个字符串处理,在后面加’\0’。
3.3使用字符串处理函数
3.3.1puts函数-输出字符串函数
遇到’\0’停止输出,且自动换行。
一般形式:
puts(数组名);
例如:
char a[]="welcome\nto\nChina";
puts(a);
输出结果:
welcome
to
China
3.3.2gets函数-输入字符串函数
一般形式:
gets获得的函数值是字符数组的起始地址
gets(数组名);
3.3.3strcat函数-字符串连接函数
3.3.3.1函数使用
一般形式:
strcat(字符数组1,字符数组2);
作用:把字符串2连接到字符串1的后面,结果放在字符数组1中,函数调用后得到一个函数值为字符数组1的地址。
注意:
- 字符数组1必须足够大;
- 在连接两个字符串的时候,字符数组1的’\0’取消,只保留字符数组2的’\0’.因为在打印的时候,遇到’\0’就结束打印,所以字符数组1的’\0’必须取消掉。
例如连接两个字符串:
#include<stdio.h>
#include<string.h>//引用头文件才可以使用strcat函数
int main()
{
char s1[30]="This is ";
char s2[]="an apple";
printf("%s",strcat(s1,s2));
return 0;
}
运行结果:
3.3.3.2函数原理
头文件:string.h
函数原型: char *strcat(char *dest,const char *src)
作用:把字符串src连接到字符串dest的后面
参数:src为原串的起始地址,dest为目标串的起始地址
返回值:目标串的起始地址
不用strcat函数实现字符串连接:
#include<stdio.h>
int main()
{
char s1[30]="This is ";
char s2[10]="an apple";
char *p,*q;
p=s1;
q=s2;
//while(*++p) ;
while(*p) p++;
while(*q){
*p++=*q++;
}
*p='\0';
printf("%s",s1);
return 0;
}
说明一下:
while(*p++)和while(*p) p++;和while(*++P)的区别
1.while(p++)表示:当p=0的时候,退出循环,p++任然执行,因为++是先赋值后运算。
2.while(p) p++;表示的意思是:当p=0的时候,退出while循环体,p++不在执行。
3.while(++p)表示:++优先级高于;先执行++p,在取值,当*p=0时,不再++。
3.3.4strcpy函数和strncpy函数-字符串复制函数
3.3.4.1函数使用
一般形式
strcpy(字符数组1,字符串2);
strcpy(str1,str2,n);
1作用:把字符串2复制到字符数组1中去。
2作用:把str2中的前n个字符复制到str1中。
注意:
- 字符数组1的空间必须足够大
- 字符数组1必须写成数组名的形式,字符串2可以是字符数组名,也可以是一个字符串常量。
- 需要对字符数组1的内容初始化或者赋值,否则在进行复制的时候,字符串未被复制的地方的内容是无法预知的。
- 字符数组名是一个地址常量,其值是不能改变的,不能直接用赋值语句的。
例如:
char a[10];
char b[]="today";
strcpy(a,b);//字符数组名
strcpy(a,"BOY");//字符串常量
char str1[20];
str1="good";//不能用赋值语句赋值
str1=str2;//也不能用数组名直接赋值
3.3.4.2函数原理
头文件:string.h
函数原型:char *strcpy(char *dest,const char *src)
作用:字符串的复制
参数:src为原串的起始地址,dest为目标串的起始地址
返回值:目标串的起始地址
例如:用程序实现strcpy函数功能。
#include<stdio.h>
int main()
{
char s1[50];
char s2[10]="an apple";
char *p,*q;
p=s1;
q=s2;
while(*q){
*p++=*q++;
}
*p='\0';
printf("%s",s1);
return 0;
}
3.3.5strcmp函数-字符串比较函数
3.3.5.1函数使用
一般形式
strcmp(字符串1,字符串2);
作用:从左到右逐个比较字符串的ASCII码,直到出现不同的字符或者’\0’为止。
(1)字符串1=字符串2,函数值为0
(2)字符串1>字符串2,函数值为一个正整数
(3)字符串1<字符串2,函数值为一个负整数
3.3.5.2函数原理
头文件:string.h
函数原型:int strcmp(const char *src,const char *dst)
作用:从左到右逐个比较字符串的ASCII码,直到出现不同的字符或者’\0’为止。
参数:s1和s2为字符串的起始地址。
返回值:
(1)字符串1=字符串2,函数值为0
(2)字符串1>字符串2,函数值为一个正整数
(3)字符串1<字符串2,函数值为一个负整数
例如:用程序实现strcmp函数功能。
#include <stdio.h>
int strcmp_new(const char* src, const char* dst)
//比较两个字符串每一个字符的大小,若相等则比较两者的下一个字符
{
int ret = 0;
while( !(ret = *(unsigned char*)src - *(unsigned char*)dst) && *dst)
{
src ++;
dst ++;
}
if( ret < 0) ret = -1;
else if(ret > 0) ret = 1;
return ret;
}
它的含义是如果两个字符串相等时,(!ret)就是非零,执行while里面的代码,当两个字符串都比较完了要退出时(&&str)或(&&dst)退出while循环;
当两个字符串相减不为0时,直接执行下面的if语句;
int main()
{
char str[10] = "an apple";
char str1[10] = "an Apple";
int ret1 = strcmp_new(str,str1);
printf("ret=%d\n", ret1);
getchar();
return 0;
}
3.3.6strlen函数-字符串长度函数
3.3.6.1函数使用
一般形式:
strlen(字符数组);
返回值为字符串的实际长度(不包括’\0’)
区分sizeof和strlen
- sizeof 计算的则是分配的数组所占的内存空间的大小,不受里面存储的内容影响,包括’\0’
- strlen 计算字符串的长度,不包括‘\0’
例如:
char a[]="abcdefg";
sizeof(a)sizeof(a[0])=8;计算的是数组的空间大小,包括'\0'
strlen(a)=7;//表示字符串长度,不包括'\0'
3.3.6.2函数原理
头文件:string.h
函数原型:size_t strlen(const char *s)
作用:计算字符串的实际长度,不包括’\0’
参数:s为字符串
返回值:字符串数组的长度,不包括’\0’
函数实现:
#include<stdio.h>
int main()
{
char s[]="abcdefg";
char *p;
p=s;
int count=0;
while(*p)
{
count++;
p++;
}
printf("%d",count);
return 0;
}
3.3.7strlwr函数-转化为小写的函数
3.3.7.1函数使用
一般形式
strlwr(字符串);
作用:把字符串中的大写转化为小写字母
3.3.7.2函数原理
头文件:string.h
函数原型:exter char *strlwr(char *str)
作用:把字符串中的大写转化为小写字母
参数:str为字符串
返回值:转化后的字符串的指针
函数实现:
大写字母的ASCII比小写字母的ASCII小32;
#include<stdio.h>
#include<string.h>
char* my_strlwr(char *str)
{
char *s;
s=str;
while(*s!='\0')
{
if(*s>='A' && *s<='Z')
{
*s+=32;
}
s++;
}
return s;
}
int main()
{
char str[10]="APPLE";
my_strlwr(str);
printf("%s",str);
return 0;
}
3.3.8strupr函数-转化为大写的函数
3.3.8.1函数使用
一般形式
strupr(字符串);
作用:把字符串中的小写转化为大写字母
3.3.8.2函数原理
头文件:string.h
函数原型:exter char *strupr(char *str)
作用:把字符串中的小写转化为大写字母
参数:str为字符串
返回值:转化后的字符串的指针
#include<stdio.h>
#include<string.h>
char* my_strlwr(char *str)
{
char *s;
s=str;
while(*s!='\0')
{
if(*s>='a' && *s<='z')
{
*s-=32;
}
s++;
}
return s;
}
int main()
{
char str[10]="apple";
my_strlwr(str);
printf("%s",str);
return 0;
}
3.3.9字符数组举例
题目:输入一行字符,统计有多少个单词,单词之间用空格隔开。
思路:根绝空格来判断是否有新单词的出现,逐个检查字符是否为空格,如果是则进行加一。
#include<stdio.h>
int main()
{
char str[50];
int word=0;//标志是否有新单词出现的标志
int sum=0;//用于计算单词个数
char *p;//使用指针指向字符串数组
gets(str);
p=str;
while(*p){
if(*p==' ')//表示没有出现新单词
{
word=0;
}else if(word==0){
//前一字符为空格word=0,新单词出现,sum+1,word=1;
word=1;
sum++;
}
p++;
}
printf("%d",sum);
return 0;
}