一、数组
1、数组
(1)、数组属于构造数据类型
(2)、数组的特点
只能存放一种类型的数据,比如int类型的数组、float类型的数组。数据称为“元素”,元素有顺序之分,每个元素都有一个唯一的下标(索引),从0开始
//数组的初始化和遍历
#include <stdio.h>
int main()
{
//正确的初始化方式
/*
int age[5]={10,9};代表给前两个角标处赋值
int age[50]={[2]=34,[3]=56};代表给2和3位置赋值
int age[]={1,2,3};代表该数组长度为3
int age['s']={1,2};
也可以先声明再初始化:
int age[3];
age[0]=2;
age[1]=3;
age[2]=45;
*/
printf("----------------------------------------\n");
//错误的初始化方式
/*
int age[]; 这是错误的,不明确数组长度
int age[3];
age={1,2,3};这是错误的,大括号只能在声明时这样定义。而且,数组名代表的是一个内存地址
*/
printf("----------------------------------------\n");
/*
数组长度为变量时
int i=5;
int age[i]={1,2,3};//这是错误的,要想在定义数组的同时进行初始化,
数组元素个数必须是常量或者常量表达式
int age[i];
age[0]=2;
age[2]=4;//这样初始化就是正确的
*/
printf("----------------------------------------\n");
//遍历数组
int ages[]={23,12,34,43,22,11};
//C语言数组木有像java中length属性,所以计算数组长度可以用数组总字节数除以
//每个元素所占字节数,也就是sizeof(ages)/sizeof(int)
for(int i=0;i<sizeof(ages)/sizeof(int);i++)
{
printf("%d\t",ages[i]);
}
printf("\n");
return 0;
}
(3)、数组的内存存储细节
数组名就代表数组地址,所以&array和array是一样的。寻址过程中,数组和数组之间是先从高位分配,但是个元素之间则是从地位分配.
#include <stdio.h>
int main()
{
//定义两个数组
int ages[3]={1,2,3};
char c[2]={78,56};
//打印数组字节数
printf("ages的长度是%ld个字节\nages的长度是%ld个字节\n\n",sizeof ages,sizeof c);
//打印两个数组地址
printf("ages的地址是%p\nc的地址是%p\n",ages,c);
//打印两个数组中个元素的地址
for(int i;i<3;i++)
{
printf("ages[%d]的地址是:%p\n",i,&ages[i]);
}
printf("\n\n");
for(int i;i<2;i++)
{
printf("c[%d]的地址是:%p\n",i,&c[i]);
}
return 0;
}
//输入3个人的成绩并计算平均值
#include <stdio.h>
int main()
{
//定义1个长度为3的数组
int ages[3];
int sum=0;
//循环输入3个成绩
for(int i;i<3;i++)
{
printf("请输入第%d个同学的成绩,按回车键结束\n",i+1);
scanf("%d",&ages[i]);
sum+=ages[i];
}
//输出平均值
printf("平均值是%0.3f",sum/3.0);
return 0;
}
(4)、数组与函数
基本数据类型作为形参是值传递,数组则是地址传递。数组传递时,会被当成指针类型,指针在64位编译器下长度均为8个字节
//输入3个人的成绩并计算平均值
#include <stdio.h>
int maxOfArray(int array[],int length);
int main()
{
//定义1个长度为3的数组
int ages[]={425,1,992,90};
//调用函数求最大值,传入数组长度参数
printf("zuida值是%d\n",maxOfArray(ages,sizeof ages/sizeof(int)));
return 0;
}
//定义一个函数求数组中的最大值,length为数组元素个数
int maxOfArray(int array[],int length)
{
//sizeof array; 的结果在64位编译器下永远是8
int max=array[0];
for(int i=0;i<length;i++)
{
//先选定【0】为目标挨个去比较,谁大就换谁
max=max<array[i]?array[i]:max;
}
return max;
}
(5)、二维数组
二维数组是一个特殊的一维数组:它的元素是一维数组。其长度就是所有一维数组之和。
二、字符串
(1)、每个字符串的尾部有一个隐藏的字符'\0',ASCII码值是0,代表空。它是字符串的技术标记。
C语言中木有String,字符串用字符数组来表示。
(2)、字符串的占位符是%s
#include <stdio.h>
int main()
{
//字符串初始化
/*
下面两句的内存分布大体一致,当然地址值不同
char name[10]={'i','t','\0'};
char name[10]={'i','t',0};//\0的ASCII值就是0
char name[10]="jack";//比较常用
char name[]="sd";
char name[10]={'i','t'};//也算是字符串,因为【2】之后都是默认为0
char bane[]={'s','t'};//严格来讲这不是字符串,因为木有结束符0
*/
char name[]="it";
name[0]='l';
printf("%lu\n",sizeof name);//结果是3,别忘了结束符0
printf("name is %s\n",name);//占位符 %s
char name2[]={'w','e'};
//%s会从当前这个name2的首地址往外输出,至到遇到‘\0’为止
printf("name2 is %s\n",name2);//所以此时输出结果为welt
//结果是elt,因为此时将name2[1]的地址传给了%s,将从name2[1]开始输出直到遇见'\0'为止。
printf("name2 is %s\n",&name2[1]);
char name3[]="wer\0try";
char name4[]={'a','s'};
printf("name3 is %s\n",name3);//结果为wer
printf("name4 is %s\n",name4);//结果为aswer
return 0;
}
(3)、strlen函数
该函数代表计算字符串长度,字节数,而不是字数。
该函数从传入的字符串首地址开始计算,直到遇到'\0'为止,字节数不包含'\0'
该函数声明在string.h文件中。
#include <stdio.h>
#include <string.h>
int main()
{
char name[]="哈哈it";
printf("字节数是%lu\n",strlen("wer\0try"));//结果为3
printf("name字节数是%lu\n",strlen(name));//结果为8
char name1[]={'2'};
//从name1首地址开始计算,直到遇到0为止.所以会计算完name。
printf("name1字节数是%lu\n",strlen(name1));//结果是9
char c[]={0};
printf("name1字节数是%lu\n",strlen(c));//结果是0
return 0;
}
/*编写一个函数char_contains(char str[],char c),如果字符串str中包含字符c则返回数值1,
否则返回数值0*/
#include <stdio.h>
#include <string.h>
int charConts(char array[],char c);
int charConts1(char array[],char c);
int main()
{
char c[]="sdoiuiygsfsgvfdgbfrbf";
printf("%d\n", charConts(c,'s'));
printf("%d\n", charConts1("sdfghjk",'s'));
return 0;
}
//方法一:利用strlen函数算字符串长度
int charConts(char array[],char c)
{
for(int i=0;i<strlen(array);i++)
{
if(array[i]==c)
return 1;
}
return 0;
}
//方法二:根据判断各角标位置上的元素是否为0来判断字符串长度
int charConts1(char array[],char c)
{
int i=-1;
while(array[++i])
{
if(array[i]==c)
return 1;
}
return 0;
}
(4)、字符串数组
//几种初始化方式
char names[2][10] = { {'J','a','y','\0'}, {'J','i','m','\0'} };
char names2[2][10] = { {"Jay"}, {"Jim"} };
char names3[2][10] = { "Jay", "Jim" };
三、指针 (1)、定义的格式
类名标识符 *指针变量名; 比如:int *p
指针就一个作用:能够根据一个地址值,访问对应的存储空间
#include <stdio.h>
int main()
{
int a=10;
//声明一个指针变量并进行初始化,此时p指向了变量a
//数据类型int表示p只能指向该类型的变量
//指针变量只能存储地址,前面的*只是一个象征,代表P是指针类型。
int *p=&a;
*p=89;//此时的*代表访问p指向的存储空间中的值
printf("%d\n", a);//89
a=90;
printf("%d\n",*p);//90
return 0;
}
/*
void change(int n)函数调用完毕后,改变实参的值
*/
#include <stdio.h>
void change(int *n,int number);
int main()
{
int a=10;
change(&a,999);
printf("%d\n",a);//999
return 0;
}
void change(int *n,int number)
{
//number代表要变成的值
*n=number;
}
定义变量int *p时的*仅仅是个象征,没有其他特殊含义,可以把(int *)看成是一个整体,也就是p的类型可以是 int *。*p=90;这的*是访问变量p指向的存储空间。
int **p;是个二级指针,就是指向指针的指针。
(2)、二级指针
#include <stdio.h>
int main()
{
int a=10;
int *p;
p=&a;
//二级指针
int **p1=&p;
//*(*p1)=*p=a
**p1=34;
printf("%d\n",a);//999
return 0;
}
(3)、清空指针
p=0;或者p=null;
后者较专业
练习:
//定义一个函数同时实现和、差、乘积
#include <stdio.h>
int test(int i,int j,int *cha ,int *ji)
{
*cha=i-j;
// *ji=i*j;
return i+j;
}
int main()
{
int a=10;
int b=7;
int sum;
int cha;
int ji;
sum=test(a,b,&cha,&ji);
printf("sum---%d\ncha---%d\nji---%d\n",sum,cha,ji);
return 0;
}
(4)、细节
#include <stdio.h>
int main()
{
int a=2;
char c=1;
int *p=&c;
//p是int类型的指针,此时c的地址赋给了p,所以*p会从c的地址开始读取4个字节
printf("*p---%d\n",*p);//结果是513
return 0;
}
赋值也是一样的道理,*p=10,也是从首地址读取4个字节进行赋值。