P30 数组

数组:构造类型之一,连续存放

int arr[M] = {1,2,3};
	printf("%d\n",sizeof(arr));
	printf("arr = %p\n",arr);  //arr是个常量 不能无条件出现在等号左边。 
	for(int i=0;i<M;i++)
	{
		printf("%p-->%d\n",&arr[i],arr[i]);
	}	
int arr[] = {1,2,3,4,5,6};
printf("%d\n",sizeof(arr)/sizeof(arr[0]));

数组:在内存当中是连续存放的内存空间,数组存储的类型是一致的。

一维数组

1、一维数组如何定义

[存储类型] 数据类型 标识符[下标]

2、初始化

不进行初始化、全部初始化、部分初始化(没初始化的都为0)、static(全部为0)

3、元素引用

数组名[下标]

4、数组名

数组名是表示地址的常量,也是整个数组的起始位置。

5、数组越界

数组越界不检查,是因为有指针偏移这个机制。a[i] = *(a+i);

1、斐波那契数列前十项 ,并且逆序存放

#include "stdio.h"
#include "stdlib.h" 
#define M 3
#define N 10
static void fibonacci(void)
{
	int i,j,temp; 
	int fib[10] ={1,1};
	int arr[] = {1,2,3,4,5,6};
	printf("%d\n",sizeof(arr)/sizeof(arr[0]));
	for(int i = 2;i<=9;i++)
	{
		fib[i] = fib[i - 1] + fib[i - 2];
	}
	for(i=0;i<=9;i++){
		printf("%d ",fib[i]);
	}
	printf("\n");
	
	i = 0;
	j = sizeof(fib)/sizeof(fib[0])-1;
	while(i<j)
	{
		temp = fib[i];
		fib[i] = fib[j];
		fib[j] = temp; 
		i++;
		j--;
	}
	for(i=0;i<=9;i++){
			printf("%d ",fib[i]);
		}
}

2、数据排序:冒泡,选择,快速排序

static void sort1(void)
{
	int temp;
	int a[N] = {12,8,45,30,98,67,2,7,68,11};
	for(int i=0;i<=9;i++)
	{
	printf("%d ",a[i]);
	} 
	printf("\n");
	for(int i=0;i<N-1;i++)
	{
		for(int j = 0;j<N-1-i;j++)
		{
			if(a[j]>a[j+1])
			{
				temp = a[j];
				a[j] = a[j+1];
				a[j+1] = temp;				
			}
		}
	}
		for(int i=0;i<=9;i++)
		{
		printf("%d ",a[i]);
		} 
} 

快速排序

static void sort2(void)
{
	int i,j,k,temp;
	int a[N] = {12,8,45,30,98,67,2,7,68,11};
	for(i=0;i<sizeof(a)/sizeof(a[0]);i++)	
	printf("%d ",a[i]);	
	printf("\n");
	for(i=0;i<=N-1;i++)
	{
		k = i;
		for(j = i + 1 ;j<N;j++)
		{
			if(a[j]<a[k])
				k = j;
		}
		if(i != k)
		{
			temp = a[i];
			a[i] = a[k];
			a[k] = temp;	
		}
	}
	for(i=0;i<sizeof(a)/sizeof(a[0]);i++)	
	printf("%d ",a[i]);	
	printf("\n");
}

3、进制转换

static void base_convert(void)
{
	int i=0,num,base;
	int n[128];
	printf("please enter the convert num :");
	scanf("%d",&num);
	printf("please enter the base:");
	scanf("%d",&base);	
	do
	{
		n[i] = num%base;
		num = num/base;
		i++;
	}while(num != 0);
	for(i--;i>=0;i--)
	{
		if(n[i]>=10)
		printf("%c",n[i] - 10 +'A');
		else
		printf("%d",n[i]);	
	}
}

4、删除法求质数

static void primer(void)
{
	char primer[1001] = {0};
	for(int i=2;i<=1001;i++)
	{
		if(primer[i] == 0)
		{
			for(int j = i*2;j<=1001;j+=i)
			{	
				primer[j] = -1;	
			}			
		}
	}
	for(int i=2;i<=1001;i++){
		if(primer[i] == 0)
		{
			printf("%d ",i);	
		}
	}		
}
int main()
{
	//fibonacci();
	primer();
	return 0;
} 

二维数组

二维数组

1、定义、初始化
[存储类型] 数据类型 标识符 [行下标][列下标]
存储机制:按照行顺序存储。
只有行号可以省略,列号不可以省略。
arr是个常量 不能无条件出现在等号左边。

#include "stdio.h"
#include "stdlib.h" 
#define  M 2
#define  N 3
int main()
{
	int a[M][N] = {{1,2,3},{4,5,6}};
	//int a[M][N] = {1,2,3,4,5,6};
	int i, j;
	printf("a = %p\n",a);
	for(i=0;i<M;i++)
	{
			for(j=0;j<N;j++)
			{
				printf("%p --> %d\n ",&a[i][j],a[i][j]);
			}
			printf("\n");
	}
	
	return 0;
} 

在这里插入图片描述
2、元素引用
数组名[行标][列标]
3、存储形式
顺序存储、按行存储。
4、深入理解二维数组
多个一维数组组成的连续存储的空间。
a+1的跳转不是跳转一个整型 a相当于行指针,跳过了N个整型的距离。

int a[M][N] = {{1,2,3},{4,5,6}};
	//int a[M][N] = {1,2,3,4,5,6};
	int i, j;
	printf("a = %p\n",a);
	printf("a + 1 = %p\n",a+1);
	for(i=0;i<M;i++)
	{
			for(j=0;j<N;j++)
			{
				printf("%p --> %d\n ",&a[i][j],a[i][j]);
			}
			printf("\n");
	}
	
	return 0;

在这里插入图片描述

练习

1、行列互换

int i,j;
static void test(void)
{
	int a[M][N] = {{1,2,3},{4,5,6}},b[N][M];
		for(i=0;i<M;i++)
		{
			for(j=0;j<N;j++)
			{
				printf("%d ",a[i][j]);
				b[j][i] = a[i][j];
			}
			printf("\n");
		}
			for(i=0;i<N;i++)
			{
				for(j=0;j<M;j++)
				{
					printf("%d ",b[i][j]);		
				}
				printf("\n");
			}
}

2、求最大值及其所在位置

static void test2(void)
{
	int a[M][N] = {32,4,23,89,9,7};
	int i,j;
	int max = a[0][0],row = 0,cloum = 0;
	for(i=0;i<M;i++)
	{
		for(j=0;j<N;j++)
		{	
			if(max<a[i][j])
			{
				max=a[i][j];
				row = i;
				cloum = j;
			}
		}
	}
	printf("max : a[%d][%d] = %d\n",row,cloum,max);
	
}

3、求各行和各列的和

static void test3(void)
{
	int a[5][4] = {{1,2,3},{4,5,6},{7,8,9},{10,11,12}};
	for(int i=0;i<4;i++)
	{
		for(int j=0;j<3;j++)
		{
			a[4][3] +=a[i][j];
			a[4][j] +=a[i][j];
			a[i][3] +=a[i][j];  
		}
	}
	for(int i=0;i<5;i++)
	{
		for(int j=0;j<4;j++)
		{
			printf("%4d ",a[i][j]);
		}
		printf("\n");
	}
}

4、矩阵乘积

static void test4(void)
{
	int i,j,k;
	int a[M][N] = {1,2,3,4,5,6};
	int b[N][K] = {1,0,0,1,1,0};
	int c[M][K] ;
	for(i=0;i<M;i++)
	{
		for(j=0;j<K;i++)
		{
			for(k = 0;k<N;k++)
			{
				c[i][j]	+= a[i][k]*b[k][j];
			}			
		}
	}
	for(i=0;i<M;i++)
	{
		for(j=0;j<K;j++)
			printf("%4d",c[i][j]);
		printf("\n");
	}	
}

p38

字符数组

1、定义,初始化,存储特点
[存储类型] 数据类型 标识符 [下标]
单个字符初始化、字符串常量初始化

static void test5(void)
{
	char str[3] = {'a','b','c'};
	//在存储的最后一位会有一个尾 \0 
	for(int i=0;i<N;i++)
	{
		printf("%c",str[i]);		
	}
	printf("\n");
  gets(str);//从标准输入中获取字符串,但是不检查数组越界现象,使用危险。 
	puts(str);
}

2、输入输出

static void test5(void)
{
	char str[3] = {'a','b','c'};
	//在存储的最后一位会有一个尾 \0 
	for(int i=0;i<N;i++)
	{
		printf("%c",str[i]);		
	}
	printf("\n");
//	gets(str);//从标准输入中获取字符串,但是不检查数组越界现象,使用危险。 
//	puts(str);
	scanf("%s",str); //含有回车、空格、Tab无法获取。 
	printf("%s",str);	
}

3、常用函数

strlen&sizeof
strcpy&stcncpy
strcat&strncat
strcmp&strncmp

static void test6(void)
{
	#define STRSIZE 32
	char str[STRSIZE]	= "hello\0abc";
	char str1[]	= "hello";	
	printf("%d\n",strlen(str));//以尾0作为结束计算串的大小。 
	printf("%d\n",sizeof(str));//传参传进来真正所带的字节数。 
	strcpy(str,"abcde");
	strncpy(str,"abcde",STRSIZE);
	puts(str);	
	strcat(str1," ");
	strcat(str1,"world");//把尾0去掉,然后补充新串补上尾0
	strncat(str1,"abcde",STRSIZE);//最多从source中取N个字节,然后追加,没有N个的话,取到尾0为止 ,总的大小不会超过STRSIZE 
	puts(str1);
	printf("%d\n",strcmp(str,str1));//比较结果是ASCII值,大的返回正,小的返回负,相等返回0
	printf("%d\n",strncmp(str,str1,5));//比较前N个字符 
	//&strncmp
}

P40 练习题

1、计算输入的有多少个字符串。

static void test7(void)
{
	char str[128];
	int count = 0,flag = 0;
	gets(str);
	for(int i=0;str[i]!='\0';i++)
	{
		if(str[i] == ' ')
		{
			flag = 0;
		}
		else 
			if(flag == 0)
			{
					count++;
					flag = 1;
			}
	}
	printf("count = %d\n",count);
}

指针与变量

1、变量与地址的关系
变量名:用户对某一个内存空间的抽象表示。
指针就是地址,指向某一个地址值。
2、指针与指针变量
指针指向某一个地址值,指针变量:一个能够保存地址的变量,保存着指针。

static void test8(void)
{
	int i = 1;	 	 
	int *p = &i;  //类型是int* ,指针存放的是变量的地址  
	int **q = &p;
	printf("sizeof(i) = %d\n",sizeof(i));//整形所占大小	
	printf("sizeof(p) = %d\n",sizeof(p));//指针所占大小,
	//不管什么类型的指针,在固定平台都占用固定字节大小 
	printf("i  = %d\n",i);
	printf("&i = %d\n",&i);//i的地址 
	
	printf("p  = %d\n",p);//有他自己的地址,独立的空间 
	printf("&p = %d\n",&p);//指针p的地址 
	printf("*p = %d\n",*p);//访问i
	
	printf("q  = %d\n",q);//有他自己的地址,独立的空间 
	printf("*q = %d\n",*q);//存放指针p的地址 
	printf("**q = %d\n",**q);//访问i	
}

在这里插入图片描述
3、直接访问&间接访问
直接访问:系统直接读取变量所在的地址的数据。
间接访问:系统通过调用c所在的地址,之后再读取地址存储的数据。
4、空指针&野指针
空指针:int *p = null;
野指针:没有确定指针的指向,指针定义出来就要赋值初值,没有初值就定义为空。
5、空类型的指针
void *q = NULL;//百搭数据类型
6、定义&初始化&书写规则

在这里插入图片描述

P44

7、指针运算

取地址&,取*,关系运算,++,–

static void test10(void)
{
	int a[] = {5,1,7,2,8,3};
	int y;
	int *p = &a[1];
	y = (*--p)++;
	printf("y = %d\n",y);
	printf("a[0] = %d\n",a[0]);	
} 

8、指针与数组

(1)指针与一维数组

static void test9(void)
{
	int a[3] = {1,2,3};
	int *p = a;
	int i;
	//p和a的区别就是,p是变量,a是常量。 
// a[i]:a[i]=*(a+i) = *(p+i) = p[i];
// &a[i]:&a[i]=a+i = p+i= &p[i];
	printf("%p,%p \n",a,a+1);
	printf("%p,%p \n",p,p+1);		
	for(i=0;i<sizeof(a)/sizeof(a[0]);i++)
	{
		printf("%p -> %d \n",a+i,a[i]);
		printf("%p -> %d \n",p+i,a[i]);	
		printf("%p -> %d \n",p+i,*(p+i));
		printf("\n");						
	}		
}

在这里插入图片描述
(2)指针与二维数组

static void test11(void)
{
	int a[2][3] = {1,2,3,4,5,6};
	int i,j;
	int *p = *a;
	int (*q) [3] = a;//指针数组 

	printf("%p  %p ",a,a+1);
	printf("%p  %p ",q,q+1);
	for(i=0;i<2;i++)
	{
		for(j=0;j<3;j++)
		{	
			printf("%p->%d ",*(a+i)+j,*(*(a+i)+j));	
			//printf("%p->%d ",&a[i][j],a[i][j]);
		}
		printf("\n");	
	}		
}

P47

(3)指针与字符数组

static void test12(void)
{
	char str[] = "i love china!";
	char *p = str + 7;
	puts(str);
	puts(p);
}

static void test12(void)
{
	char *str = "hello";
	printf("%d %d\n",sizeof(str),strlen(str));
	//strcpy(str,"world");//错误赋值方式,企图用world覆盖str串常量。 
	str = "world";  //指针,放弃指向hello的字符串,转向指向world的串。 
	puts(str); 

//	char str[] = "hello";
//	printf("%d %d\n",sizeof(str),strlen(str));
//	//str = "world";//错误,不能给常量赋值。
//	strcpy(str,"world");//正确赋值方式,连续的存储空间。 
//	puts(str); 

//	char str[] = "i love china!";
//	char *p = str + 7;
//	puts(str);
//	puts(p);
}

9、const与指针

static void test13(void)
{
/*
	const int a;
	int const a;
	区分命名:1、看const开始念,const在前的是 常量指针,否则是指针常量。
					2、	const int *p;	常量指针:指针指向可以发生变化,但是这块空间的数值是无法变化的。 
							int const *p;
	int *const p;   指针常量:指针的指向永远不能变化,但是这块空间的数值是可以变化的。 
	const int *const p; 
*/
	#define PI 3.14   //宏最大的缺点不检查语法。
	const float pi = 3.14; //需要当前的变量值一直保持不变,const使得变量常量化,优点是检查语法。 
	
//	const float *p = &pi;//企图通过指针来给pi重新赋值。 
//	*p = 3.14159;
//	printf("%f\n",pi);
	
	//常量指针 
//	int i = 1;
//	int j = 100;
//	const int *p = &i;//指针指向可以发生变化,但是这块空间的值是无法变化的。 
//T	i  = 10;
//F	*p = 10;
//T p = &j;

	//指针常量
//	int i = 1;
//	int j = 100;
//	int *const p = &i;//指针指向可以发生变化,但是这块空间的值是无法变化的。 
//T *p = 10;	对 
//F	p = &j;		企图给指针常量赋值,错 
	int i = 1;
	int j = 100;
	const  int *const p = &i;
//F p = &i;
//F *p = 10;
	printf("%d\n",*p);	
} 

P48

10、指针数组与数组指针

数组指针:指向数组的一个指针。数据类型 (*指针名)[下标]。
如: int (*p)[3]; -> type name ; --> int[3] *p;
p+1操作 一下子移动3个int类型。

static void test11(void)
{
	int a[2][3] = {1,2,3,4,5,6};
	int i,j;
	int *p = *a;
	int (*q) [3] = a;//指针数组 
	printf("%p  %p ",a,a+1);
	printf("%p  %p ",q,q+1);
	for(i=0;i<2;i++)
	{
		for(j=0;j<3;j++)
		{	
			printf("%p->%d ",*(a+i)+j,*(*(a+i)+j));	
			//printf("%p->%d ",&a[i][j],a[i][j]);
		}
		printf("\n");	
	}		
}

指针数组:[存储类型] 数据类型 * 数组名[长度]
如:int *arr[3];-> TYPE NAME;–>int *[3] arr;

//数组指针:选择排序办法 
static void test14(void)
{
	int i,j,k;
	char *name[5] = {"follow me","basic","great","fortran","computer"}; //指针数组 
	char *temp;
	for(i=0;i<5-1;i++)
	{
		k = i;
		for(j = i + 1; j < 5;j++)
		{
			if(strcmp(name[k],name[j])>0)
			{
				k = j;
			}	
		}
		if(k!=i)
		{
			temp 	= name[i];
			name[i] = name[k];
			name[k] = temp;	
		}
	}
	for(int i=0;i<5;i++)
	{
		puts(name[i]);	
	} 
}

11、多级指针

以一级指针类推。

Logo

更多推荐