前言
本周主要学习了数组和指针,还学习了函数的部分内容,下面是对本周内容的总结,大多以程序为例。
数组
数组的概念
- 由相同类型的多个元素所组成的一种复合数据类型
- 在工程中同时定义多个相同类型的变量时,重复定义,可以使用数组
#include <stdio.h>
int main()
{
// 申请4块连续的空间取名ch存放"ABC\0"
// 把这4块空间称为数组
char ch[4] = "ABC";
printf("c[0]=%c\n",ch[0]);// 将ch第0块空间的内容输出
printf("c[1]=%c\n",ch[1]);// 将ch第1块空间的内容输出
printf("c[2]=%c\n",ch[2]);// 将ch第1块空间的内容输出
// 将数组ch的第二块内存的数据给c
char c = ch[2];
printf("%c\n",c);
char buf[5];
// %p为输出地址
printf("buf addr : %p\n",buf);
printf("buf[0] addr : %p\n",&buf[0]);
buf[0] = 'r';
buf[1] = 'o';
buf[2] = 's';
buf[3] = 'e';
buf[4] = '\0';
// %s是输出字符串
printf("%s\n",buf);
return 0;
}
- 数组定义
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 申请5块连续的空间,将a称为数组
int a[5];
// 将这5块空间逐一赋值,注意,数组下标从0开始
a[0] = 1;
a[1] = 20;
a[2] = 30;
a[3] = 40;
a[4] = 50;
//a[5] = 60; // 越界,无法使用
printf("%d\n",a[4]);
// 循环给数组a赋值
for(int data = 10,i = 0; i < 5; i++,data+=10)
{
a[i] = data;
}
// 遍历输出
for(int i = 0; i < 5; i++)
{
printf("%d\n",a[i]);
}
return 0;
}
- 初始化:在定义的时候赋值,称为初始化
// 正常初始化
int a[5] = {100,200,300,400,500};
int a[5] = {100,200,300,400,500,600}; // 错误,越界了
int a[ ] = {100,200,300}; // OK,自动根据初始化列表分配数组元素个数
int a[5] = {100,200,300}; // OK,只初始化数组元素的一部分
// 不能在使用变长数组的情况下初始化数组
int a[size] = {1,2,3};//编译出错
// 变长数组只能先定义再使用
int a[size]; // 正确的
a[0] = 10;
#include <stdio.h>
int main(int argc, char const *argv[])
{
// 定义数组并初始化
int Array[5] = {10,25,31,48,60};
printf("%d\n",Array[2]);
// 初始化的时候确定数组空间大小
int Array0[] = {10,20,39};
printf("%d\n",Array0[2]);
// 初始化一部分空间,剩余的空间默认初始化为0
int Array1[10] = {68,70};
// 定义数组并清空数组
int Array2[10] = {0};
// 变长数组
int len = 3;
// 错误,初始化的时候,数组大小必须为常量
//int Array3[len] = {100,200,300};
// 哪怕不确定len的大小,但是可以确定Array3的空间最小值为一个
// int类型的空间,所以至少可以存放一个int类型的数据
int Array3[len];
Array3[0] = 100;
printf("Array3[0] = %d\n",Array3[0]);
return 0;
}
- 如果是定义的时候初始化,但是初始化列表个数小于数组的大小,那么无论这个数组是全局变量还是局部变量,没有赋值的成员都是0
int array[3];// 局部变量为随机数,全局变量为0
int array[3] = {0};//清空数组
测量数组的总大小:sizeof(array)
测量数组元素个数:sizeof(array)/sizeof(array[0])
数组元素的引用
int a[5]; // 有效的下标范围是 0 ~ 4
a[0] = 1;
a[1] = 66;
a[2] = 21;
a[3] = 4;
a[4] = 934;
a[5] = 62; // 错误,越界了
a = 10; // 错误,不可对数组名赋值
字符数组
#include <stdio.h>
int main(int argc, char const *argv[])
{
char str1[4] = {'a','b','c','\0'};
char str2[4] = {"abc"};
char str3[4] = "abc"; //常用
str1[1] = 'd';
printf("%s\n",str1);
printf("%s\n",str2);
printf("%s\n",str3);
return 0;
}
练习:
定义一个char str[6] = {‘h’,‘e’,‘I’,‘l’,‘o’};/把这个数组的内存图画出来,并且把数组的名字的地址,还有每个元素的地址都打印出来,每个元素的地址相差几个字节?
#include <stdio.h>
int main(int argc, char const *argv[])
{
char str[6] = {'h','e','l','l','o','\0'};
printf("str addr %p\n",str);
printf("str[0] addr %p\n",&str[0]);
printf("str[1] addr %p\n",&str[1]);
printf("str[2] addr %p\n",&str[2]);
printf("str[3] addr %p\n",&str[3]);
printf("str[4] addr %p\n",&str[4]);
printf("str[5] addr %p\n",&str[5]);
printf("%c\n",*(str+0));
printf("%c\n",*(str+1));
printf("%c\n",*(str+2));
printf("%c\n",*(str+3));
printf("%c\n",*(str+4));
printf("%c\n",*(str+5)); // 0
return 0;
}
数组偏移量
int Array[6] = {10,20,30,40,50,60};
// 数组地址偏移量
// 000000000061FE04,000000000061FE04
printf("%p,%p",&Array[1],&Array[0]+1);
数组元素地址解引用
int a = 10;
printf("%d\n",a);
printf("%p\n",&a);
// * 表示将地址里面的内容取出,我们把它称为解引用
printf("%d\n",*(&a));
//--------------------------
char Array[5] = {'j','a','c','k'};
printf("%c\n",Array[0]);
printf("%c,%c\n",*(Array+0),*(&Array[0]));
printf("%c,%c\n",*(Array+1),*(&Array[1]));
printf("%c,%c\n",*(Array+2),*(&Array[2]));
printf("%c,%c\n",*(Array+3),*(&Array[3]));
练习2:
定义一个整型数组,存储从键盘上获取的多个整型数据(比如输入 10 40 23 13),输入-1输入完成,并打印出这一排数据的最小值和最大值
#include <stdio.h>
int main(int argc, char const *argv[])
{
int array[100] = {0};
int count = 0;
while (1)
{
scanf("%d",&array[count]);
if(array[count] == -1)
{
break;
}
count++;
}
// 将-1从数组剔除
// i--是将i所指向的空间压缩一个类型空间
array[count] = 0;
// 找最大值和最小值
// 假设array[0]最大值与最小值
int max_value = array[0];
int min_value = array[0];
// 遍历比较替换
for(int i = 0; i < count; i++)
{
if(max_value < array[i])
{
max_value = array[i];
}
if(min_value > array[i])
{
min_value = array[i];
}
}
printf("max_value : %d\n",max_value);
printf("min_value : %d\n",min_value);
return 0;
}
字符串常量
printf("%s\n","hello");
printf("'h' addr:%p\n","hello");
printf("'e' addr:%p\n","hello" + 1); //地址+1
printf("'o' addr:%p value:%c\n","hello" + 4,*("hello" + 4)); //地址+1
printf("%d\n", sizeof("abcd")); // 此处 "abcd" 代表整个数组
printf("%p\n", &"abcd"); // 此处 "abcd" 代表整个数组
printf("%c\n", "abcd"[1]); // 此处 "abcd" 代表匿名数组的首元素地址
匿名数组
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char array[5] = "jack";
char array1[5] = "rose";
printf("%c\n",array[1]);
// "jack"是匿名数组
printf("%c\n","jack"[1]);
printf("array addr : %p",array);
printf("array1 addr : %p\n",array1);
printf("jack addr : %p\n","jack");
printf("array msg : %s\n",array);
printf("jacl msg : %s\n","jack");
printf("%c\n","rose"[0]);
printf("%c,%c\n",*("rose"+1),"rose"[1]);
printf("%ld\n",sizeof("rose"));
printf("%d\n",strlen("rose"));
char Array[10] = {0};
// 计算实际空间的大小
printf("%ld\n",sizeof(Array));
// 计算数组里面的内容大小遇到'\0'结束
// 计算时间的数组内容大小
printf("%d\n",strlen(Array));
return 0;
}
多维数组(二维数组)
#include <stdio.h>
int main(int argc, char const *argv[])
{
//只有一个【】的数组称为一维数组
char name[5]= "jack";
char name1[5] = "rose";
char name2[5] = "ken";
//有两个【】的数组称为二维数组
//二维数组初始化
//第一个【3】表示字符串的个数,表示这个数组能存放3个字符串
//第二个【5】表示每个字符串最大的长度位5字节
char Name[3][5] = {"jack","rose","ken"};
//定义二维数组
char buf[2][3];
return 0;
}
二维数组解引用
// 二维数组初始化字符串
char buf1[2][5] = {"jack","rose"};
printf("%s,%s\n",&buf1[0][0],buf[0]);
printf("%s,%s\n",&buf1[1][0],buf[1]);
// 取二维数组中的某个字符
printf("%c,%c,%c,%c\n",buf1[0][1],*(&buf1[0][1]),*(buf1[0]+1),*(*(buf1+0)+1));
printf("%c,%c,%c,%c\n",buf1[1][2],*(&buf1[1][2]),*(buf1[1]+2),*(*(buf1+1)+2));
数组地址偏移
#include <stdio.h>
int main()
{
char Names[3][5] = {"jack","rose","ken"};
// printf("Names[0] %p,%p\n",Names[0],&Names[0][0]);
// printf("Names[1] %p,%p\n",Names[1],&Names[1][0]);
// printf("Names[2] %p,%p\n",Names[2],&Names[2][0]);
// Names[0]相当于&Names[0][0]
printf("Names[0]+1=%p,%p\n",Names[0]+1,&Names[0][1]);
printf("Names[0][0]:%c,%c\n",Names[0][0],*(Names[0]+0));
printf("Names[0][2]:%c,%c\n",Names[0][2],*(Names[0]+2));
printf("&Names[0]+1=%p,%p\n",&Names[0]+1,&Names[1]);
printf("*(&Names[0]+1)=%c,%c\n",*(&Names[0]+1)[0],*(&Names[1])[0]);
printf("*(&Names[0]+1)=%c,%c,%c,%c\n",(*(&Names[0]+1))[1],(*(&Names[1]))[1],
*(*(&Names[0]+1)+1),*(*(Names+1)+1));
printf("%c,%c,%c,%c\n",Names[2][2],*(Names[2]+2),(*(Names+2))[2],*((*(Names+2)+2)));
return 0;
}
数组万能拆解法
int a[4]; // 第2部分:a[4]; 第1部分:int
int b[3][4]; // 第2部分:b[3]; 第1部分:int [4]
int c[2][3][4]; // 第2部分:c[2]; 第1部分:int [3][4]
int *d[6]; // 第2部分:d[6]; 第1部分:int *
int (*e[7])(int, float); // 第2部分:e[7]; 第1部分:int (*)(int, float)
指针
取址符
- 每个变量都是一块内存,都可以通过取址符 & 获取其地址
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
printf("0x%p\n",&a);
int buf[5] = {1,2,3,4,5};
printf("0x%p\n",&buf); //&buf+1
printf("0x%p\n",buf); //buf+1,加1后不一样
return 0;
}
指针基础
- 指针:就是用于存放地址的变量
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a = 10;
// 定义指针p指向a
int *p = &a;
printf("%p,%p\n",&a,p);
//通过p将a的内容输出
int data = *p;//*p是解引用
//解引用的意思是获取p所指向的空间里面的内容
printf("%d\n",data);
char buf[] = "jack";
char *ptr = buf;// &buf[0];
printf("%s\n",buf);
printf("%s\n",ptr);
return 0;
}
指针尺寸
#include <stdio.h>
int main(int argc, char const *argv[])
{
int *int_porint;
char *char_porint;
printf("%ld,%ld\n",sizeof(int_porint),sizeof(char_porint));
return 0;
}
野指针与空指针
#include <stdio.h>
int main(int argc, char const *argv[])
{
int *int_porint = NULL; //野指针,不能操作,NULL的类型是void*(0)
char *char_porint = NULL;//如果定义的指针暂时不用应该指向NULL地址
//printf("%d\n",*int_porint);//使用野指针会出现段错误,内存泄漏
printf("%ld,%ld\n",sizeof(int_porint),sizeof(char_porint));
return 0;
}
数组指针(二维数组指针)
#include<stdio.h>
int main(int argc, char const *argv[])
{
int array[3][5] = {
{10,20,30,40,50},
{11,22,33,44,55},
{110,120,130,140,150}
};
int (*p)[5]= array;
printf("%d\n",p[1][2]);
printf("%d\n",(*(p+1))[2]);
printf("%d\n",*((*(p+1))+2));
return 0;
}
指针数组
#include <stdio.h>
int main(int argc, char const *argv[])
{
//定义指针数组,数组存放的数据是地址
int *buf[5];
int a = 10;
int a1 = 20;
int a2 = 30;
buf[0] = &a;
buf[1] = &a1;
buf[2] = &a2;
printf("%d\n",*(buf[1]));
return 0;
}
char型指针
定义:
char * = "abcd";// 不妥
const char *p = "abcd";//不能通过p修改字符串数据
char buf[10] = "jack";// 将jack内容放到buf这块空间
char *p = buf;// p存放buf的地址
char *p1 = "jack";//p1存放“jack”的地址,jack为常量
void//不确定类型
//void a = 10;
//auto是根据赋值的值,自动识别数据类型
auto a = 10;
printf("%ld\n",sizeof(a));
auto a1;// 不能确定a1的类型
printf("%ld\n",sizeof(a1));
练习:字符串逆序输出
#include <stdio.h>
#include <string.h>
int main(int argc, char const *argv[])
{
char buf[] = "abcdef";
//scanf("%s",ch);
int len = strlen(buf);
char temp[len];
for(int i = 0,j = len -1;i<len;i++,j--)
{
temp[i] = buf[j];
}
printf("%s\n",temp);
return 0;
}
const型指针
#include <stdio.h>
int main(int argc, char const *argv[])
{
//修饰p指针指向区域为字符串常量
//不能通过p修改字符串里面的内容
const char *p = "jack";
//*p = 'r';
char const *p1 = "jack";
p1 = p;//正确
printf("%s\n",p);
char *const q = "jack";
//*q = 'r';//不会报错
//const修饰的是q本身,所以q不能指向其他地址
//q = "rose"
return 0;
}
函数
返回类型 函数名称(参数1,参数2,.......)
{
函数体
return 返回值;
}
#include <stdio.h>
/*
*swap:交换两个数值
*/
//形参的作用是接收实参数据
//实参是真实的数据,形参是一块空间,里面没有有效的数据
void swap(int *a,int *b)// 形参
{
int temp = *a;
*a = *b;
*b = temp;
printf("%d,%d\n",*a,*b);
}
int main(int argc, char const *argv[])
{
int a = 10,b = 20;
swap(&a,&b); // 实参
printf("after(%d,%d)\n",a,b);
return 0;
}
//字符串去空格
#include
int main(int argc, char const *argv[])
{
char buf[100] = {0};
int len = 0; // scanf遇到空格结束,不会拿空格
while((buf[len++] = getchar()) != '\n');
for(int i = 0; i < len; i++)
{ // 找空格
if(buf[i] == ' ')
{
for(int j = i; j < len; j++)
{
buf[j] = buf[j+1];
}
}
}
printf("%s",buf);
return 0;
}
函数模块化处理
1.一个工程应该是有多个c文件以及头文件组成
2.c文件用于存放自己封装的函数接口或者动静态库
3.头文件用于存放函数的而声明以及各种结构体、宏、枚举的定义
冒泡函数的封装流程
1.创建工程文件目录用于存放项目
2.再在此工程目录下创建bubble.c main.c bubble.h
1.bubble.c是存放冒泡算法
2.main.c值函数实现
3.bubble.h是冒泡算法的函数声明
3.在此工程创建bubble.c 添加以下内容
#include <stdbool.h>
#include <stdio.h>
bool bubble(int *array, int lenght)
{
if(array == NULL || lenght <= 0)
{
return false;
}
for(int i = 0; i < lenght-1; i++)
{
for(int j = 0; j < lenght-i-1; j++)
{
if(array[j] > array[j+1])
{
int temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
}
}
}
return true;
}
4.创建main.c添加以下内容
#include <stdio.h>
#include <stdbool.h>
#include "bubble.h"
int main(int argc, char const *argv[])
{
int array[] = {5,4,3,2,1};
int len = sizeof(array) / sizeof(array[0]);
bubble(array, len);
for(int i = 0; i < len; i++)
printf("%d\t",array[i]);
printf("\n");
return 0;
}
- 创建bubble.h添加以下的内容
bool bubble(int *array, int lenght);
- 编译成程序
编译程序不能使用快捷键,需要命令编译
gcc main.c bubble.c -o main.exe
执行程序
./main.exe
以上就是我对本周学习内容的总结,本周所学的知识对我来说还需要更多时间消化理解,对于指针部分的内容掌握还不是很牢固,需要多加练习才行。