本次记录部分为C语言的数组以及字符串以及指针等相关内容;这部分知识需要多记忆以及和之前学的c++类比记忆。
数组:
一维数组:
数组是具有一定顺序关系的若干个变量的集合,组成数组的各个变量称为数组的元素, 要求各个元素的数据类型要相同,用数组名和下标确定,可以是一维的也可以是多维的。
是C语言提供的几种基本的数据结构之一,他在计算机内存中是连续的
一般形式如下: <储存类型><数据类型><数组名>[<表达式>]
在内存中形式表示为:
注意点:1.数组名表示内存首地址,是地址常量,编译时分配的是连续的内存空间。
2.C语言对数组不做越界检查。
3.引用问题: 数组必须先定义再引用,只能逐个引用元素。
一维数组的初始化:
1,在定义数组时,为数组元素赋初值,
2,数组不初始化,其元素为随机数, static数组元素不做初始化,系统会自动赋零值。也可以只为部分元素赋初值。
练习题:冒泡排序。
代码如下:
#include<stdio.h>
int main ()
{
int a[]={22,3,45,12,55,33,1},i,n;
int j,temp;
n=sizeof(a)/sizeof(int);
for(i=0;i<n;i++)
{
printf("%d\ ",a[i]);
}
printf("\n");
//´Ó´óµ½Ð¡ÅÅÐò
for (i=0;i<n-1;i++)
{
for(j=0;j<n-1-i;j++)
{
if(a[j]>a[j+1])
{
temp=a[j+1];
a[j+1]=a[j];
a[j]=temp;
}
}
}
for(i=0;i<n;i++)
{
printf("%d\ ",a[i]);
}
return 0;
}
结果:
二维数组:
定义方式:
int a[2][4];
char[2][4];
元素个数= 行数*列数;
二维数组的存放方式:
因为内存是一维的,所以二维数组的存放时行序优先的,
二维数组的初始化:
初始化:1.分行初始化 2.按照元素排列的顺序初始化,
多维数组:
类比二维一维数组 学习与使用。
字符数组和字符串:
字符数组:
字符数组是元素的数据类型为字符类型的数组。
char ch[4];
字符数组的初始化:
逐个字符赋值:
char ch[5]= {'h','e','l','l','o'};
char ch[6]="hello";
char ch[6]={"hello"}
字符串数组;
C语言中没有字符串常量, 所以用字符数组处理字符串,字符串结束用 '\0'表示;
练习题: 输入一个字符串,并将其逆序输出,
#include <stdio.h>
#include <stdlib.h>
#define N 20
int main()
{
int i;
char str[N]={0};
gets(str);
for(i=N-1;i>=0;i--)
{
putchar(str[i]);
}
return 0;
}
字符串函数:
C语言库中有些常用的字符串处理的函数需要记录:
头文件:#include<string.h>
1.strlen ,求字符串长度函数。
格式:strlen(字符数组)
功能:计算字符串长度 返回值:返回字符串实际长度,不包括'\0'在内
\xhh 表示十六进制数代表的符号
\ddd 表示八进制的
2.strecpy,字符串拷贝函数。
格式:strcpy(字符串1,字符串2);
功能:将字符串2拷贝到字符串1中
返回值:返回字符数组1的首地址
说明:
1.字符数组1必须足够大
2.拷贝时 ‘\0’ 一同拷贝
3.strcat,字符串连接函数。
格式:stracat(字符数组1,字符数组2)
功能:把字符数组2连接到字符数组1后面
返回值:返回字符数组1的首地址
说明:
字符数组1必须足够大
连接前,两串均以 '\0' 结束,连接后,串 1的 '\0' 取消,新串最后加 ‘\0’
4.strcmp,字符串比较函数。
格式:strcmp(字符串1,字符串2)
功能:比较两个字符串
比较规则:对两串从左向右逐个字符比较(ASCII),直到遇到不同字符或 '\0'为止
返回值:返回int型整数
1.若字符串1 < 字符串2,返回负整数
2.若字符串1 > 字符串2,返回正整数
3.若字符串1 = 字符串2,返回零
字符串扩展用法:
暂时用的较少,先记录,
指针
指针可以说是C语言和c++最重要也是区别与其他语言的核心。
使用C语言的指针可以
1.使程序简洁,紧凑,高效。
2.有效的表达复杂的数据结构。
3.动态分配内存,
4,得到一个多余的函数返回值。
指针概念:
在C语言中,内存单元的地址称为指针,专门用来存放地址的变量,有时对地址,指 针和指针变量不区分,统称指针。(地址==指针)。
指针变量的说明 一般形式:<储存类型><数据类型>* <指针变量名>
例如: char *p;
int *a;
(注意理解下面这这句话)
指针的存储类型是指针变量本身存储类型。
在我的理解中,指针本身没有类型,在今后自己读代码和写代码时可以把它理解为一串数字,一串对应的内存地址的数据,
指针说明时指定的数据类型不是指针变量本身的数据类型,而是指针目标的数据类型,简 称为指针的数据类型。
注意 *和&在这部分的理解与使用 *是定义指针,以及取指针对应储存的值,而&是取地址。
指针的含义:
指针指向的内存区域中的数据称为指针的目标。
引入指针要注意程序中的px 、*px 和 &px 三种表示方法的不同意义,
设px为一个指针,
则: px ,指针变量,它的内容是地址量
*px,指针所指向的对象,它的内容是数据
&px,指针变量占用的存储区域的地址,是一个常量。
NULL指针;(了解)
指针的赋值运算:
1.把一个普通变量的地址赋值给一个具有相同类型的指针
int a=5;
int* p;
p = &a;
2.把一个已有地址的指针变量赋值给相同数据类型的另一个指针变量,
int a,*p1,*p2;
p1 = &a;
p2 = p1;
3.把一个数组的地址赋值给具有相同类型的指针。
int a[23], *pa;
pa = a;
指针的运算:
指针运算是以指针变量所存放的地址量作为运算量而进行的运算。
指针运算的实质就是地址的计算 。
指针运算的种类是有限的,它只能进行赋值运算、算数运算和关系运算。
注意不同类型的两个指针实行加减法的整数运算是没有意义的。
px+n表示的实际位置的地址量是:
(px)+sizeof(px的类型) * n
px-n表示的实际位置的地址是:
(px)-sizeof(px的类型) * n 、
两个指针相减运算
px-py运算的结果是两个指针指向的地址位置之间相隔数据的个数。
因此两个指针相减不是两个指针持有的地址值相减的结果。
两个指针相减的结果值不是地址量,而是一个整数值,表示两指针之间相隔数据的个 数。
用一个程序举例比较好理解。
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[5]={1,2,3,4,5};
int *pa,*pb;
pa = a;
printf("%p %d \n",a,*a);
pb = pa +2;
printf("%p %d \n",pa,*pa);
printf("%p %d \n",pb,*pb);
int pc=pb-pa;
printf("%p %d \n",pc,pc);
return 0;
}
指针和数组:
C语言中数组的指针是数组在内存中的起始地址。 数组元素的地址是指数组元素在内存 中的起始地址。
一维数组的数组名为一维数组的起始地址。
设指针变量px的地址值等于数组指针x(即指针变量指向数组的首元素)则:
x[i],(px+i),(x+i)和px[i] 具有完全相同的功能,:访问数组的第i+1个元素。
程序举例:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int a[5]={1,2,3,4,5,6,7,8,9,10};
int *pa,*pb,n;
n = sizeof(a)/sizeof(int);
pa = a;
printf("%p %d \n",a,*a);
printf("%p %d \n",pa,*pa);
pb = pa +2;
printf("%p %d \n",pb,*pb);
int pc=pb-pa;
printf("%p %d \n",pc,pc);
int i ,*p;
p=a;
for( i=0;i<n;i++)
{
printf("%d %d %d %d ",a[i],*(p+i),*(a+i),p[i]);
printf("\n");
}
return 0;
}
指针和二维数组:
在C语言中,二维数组的元素连续储存,按行优先存。
可以把二维数组看成由多个一维数组组成的,
比如:int a[3][3],这个二维数组含有三个元素 a[0],a[1],a[2]
元素 a[0],a[1],a[2] 都是一维数组名。
值得注意的是:二维数组名代表的是二维数组的起始地址 ,数组名加一,代表移动一行元素,因此:二维数组名常被称为行地址。
行指针:
存储行地址的指针变量,叫做行指针变量,
举例形式:
int a[2][3]; int (*p)[3];
注意: 方括号中的常量表达式表示指针加1,移动几个数据。
当用行指针操作二维数组时,表达式一般写成1行的元素个数,即列数。
字符指针和字符串:
C语言中通过使用字符数组来处理字符串。
通常把char 数据类型 的指针变量称为字符指针变量
初始化字符指针是吧内存中字符串的首地址赋予指针,并不是把字符串赋值到指针中。
char str[]="hello world";
char* p =str;
注意:当一个字符指针指向一个字符串常量时,不能修改指针指向的对象的值。
练习题目:不使用任何字符串函数,实现字符串函数连接功能。
程序:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char ch[100] = "welcome";
char* p = "hello world!";
int i = 0;
char *a;
a = p;
while(*(ch+i) != '\0')
{
i++;
}
while(*p != 0 )
{
*(ch+i)= *p;
p++;
i++;
}
puts(ch);
puts(a);
return 0;
}
指针数组与多级指针:
所谓的指针数组是指由若干个具有相同储存类型和数据类型的 指针变量构成的集合。
一般说明形式:
<储存类型><数据类型>*< 指针数组名>[<大小>]
指针数组名代表该指针数组的起始地址。
声明一个指针数组:
double* pa2[2],a[2][3];
void指针:
void指针是一种不确定数据类型的指针变量,它可以通过强制类型转换让该变量指向任何数据类型的变量。
一般形式为: void *<指针变量名称>
对于void指针,在没有进行强制类型转换的时候,不能进行任何指针的算术运算,
本次学习记录结束。