c++基础(3)数组函数预处理

数组

用一段连续空间 存放相同类型的变量 这样的容器(结构)叫数组。

数组的下标是从0开始。
假如数组有n个元素:
下标范围:0~n-1
元素范围:arr[0]~arr[n-1]

一维数组

定义数组的步骤

数组名 和 [] 表示数组
将数组的个数 放入[]里面
用元素的类型 定义一个变量
从上 往下 替换。

定义一个数组 有5个元素 每个元素为int: int a[5],数组名a,元素个数是5,元素类型为int
定义一个数组 有5个元素 每个元素为int *  :int *a[5]
定义一个数组 有5个元素 每个元素为数组,该数组有10个元素每个元素为int : int a[5][10]
定义一个数组 有5个元素 每个元素为函数的入口地址,该函数有两个int型形参,int返回值类型
a[5]--*a[5]--(*a[5])(int,int)--int (*a[5])(int,int)

一维数组的初始化

全部元素 初始化

如果数组的全部元素 都初始化 可以省略[]的数值
如果省略了[]里面数值 数组的元素个数 就由初始化的元素个数确定

部分元素 初始化:未被初始化的部分 自动补0,按顺序初始化。

int a[5]={0};//将第0个元素初始化为0 其他未被初始化自动补0
int a[5]={1,2,3,4,5}//全部初始化
int a[5]={1,2,3,}部分初始化

一维数值数组的元素操作

#include <iostream>
#include<bitset>
using namespace std;

int main()
{
    int a[5]={0};
    int n=sizeof(a)/sizeof(a[0]);   //数组总大小/数组元素大小=元素个数
    int i=0;
    for(i=0;i<n;i++)     //从键盘输入元素的值
    {
        cout<<"给a["<<i<<"]赋值"<<endl;
        cin>>a[i];
    }
    for(i=0;i<n;i++)      //对一维数组进行遍历
    {
        cout<<a[i]<<"\t";
    }
    cout<<endl;
    return 0;
}

二维数值数组

a[3][4]
3:3行,0,1,2
4:4列,0,1,2,3

二维数值数组的初始化

分段初始化

//完全初始化
int arr[3][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
//如果完全初始化 只能省略行数,列数不可省略
int arr[][4]={ {1,2,3,4}, {5,6,7,8}, {9,10,11,12} };
//部分初始化
int arr[3][4]={ {1,2}, {5,6}, {9,10,11} };

连续初始化

/完全初始化,arr[3][4],12个元素挨个初始化
int arr[3][4]={ 1,2,3,4, 5,6,7,8, 9,10,11,12};
//如果完全初始化 只能省略行数,列数不可省略
int arr[][4]={1,2,3,4, 5,6,7,8, 9,10,11,12};
//部分初始化
int arr[3][4]={ 1,2, 5,6, 9,10,11};

二维数值数组的元素操作

#include <iostream>
#include<bitset>
using namespace std;

int main()
{
    int a[2][3]={0};
    int row=sizeof(a)/sizeof(a[0]);//行数
    int col=sizeof(a[0])/sizeof(a[0][0]);//列数
    int i=0,j=0;
    for(i=0;i<row;i++)  //赋值
    {
            for (j=0;j<col;j++)
            {
            cout<<"给arr["<<i<<"]["<<j<<"]赋值"<<endl;
            cin>>a[i][j];
            }
    }
    cout<<"遍历元素"<<endl;
    for(i=0;i<row;i++)
    {
            for(j=0;j<col;j++)
            {
            cout<<a[i][j]<<" ";
            }
    }
    cout<<endl;
    return 0;
}

求每一行的平均数

#include <iostream>
#include<bitset>
using namespace std;

int main()
{
    int a[5][4]={
        {56,75,78,89},
        {89,98,76,67},
        {88,99,77,66},
        {67,78,89,90},
        {98,97,96,95}
    };
     int row=sizeof(a)/sizeof(a[0]);//行数
     int col=sizeof(a[0])/sizeof(a[0][0]);//列数
     float scoreAvg[5]={0.0f};       //定义一个一维数组,平均数为float类型
     int i=0,j=0;
     for(i=0;i<row;i++)
     {
         float sum=0;
         for(j=0;j<col;j++)
         {
             sum=sum+a[i][j];
         }
         scoreAvg[i]=sum/col;//sum是float型,与col int型运算结果是float型
     }
     for (i=0;i<row;i++)  //遍历scoreAvg数组
     {
         cout<<scoreAvg[i]<<endl;
     }


    return 0;
}

一维字符数组初始化

逐个元素初始化

char arr[5]={'h','e','l','l','o'};//''描述的是字符,这里有5个字节

以字符串的方式 初始化 一维字符数组

"“描述的是字符串, 比如字符串"hello”, 编译器会自动在字符串的末尾 添加’\0’字符 作为字符串的结束标

char arr[6]="hello";//""描述的是字符串, 编译器会自动在字符串的末尾 添加'\0'字符 作为字符串的结束标记,这里有5+1个字节

一维字符数组的遍历

#include <iostream>
#include<string.h>
using namespace std;

int main()
{
    char a[32]={"\0"};
    cout<<"输入字符串"<<endl;
    /*cin获取字符串 遇到空格或回车 结束输入
     *cin.getline获取带空格的 字符串*/
    cin.getline(a,sizeof(a));
    int i=0;
    for(i=0;i<sizeof(a);i++)   //遍历字符串
    {
        cout<<a[i];
    }
    cout<<endl;
    cout<<a<<endl;        //遍历字符串
    i=0;
    while (a[i]!='\0') {    //取得字符串字符个数,不包括\0
        i++;
    }
    cout<<i<<endl;
    cout<<strlen(a)<<endl;  //取得字符串字符个数,不包括\0
    return 0;
}

#include <iostream>
#include<string.h>
using namespace std;

int main()
{

    char b[32]={"hell\0wrold"};//使用cout直接输出字符串,遇到'\0'会结束。(遍历字符串)
    cout<<b<<endl;
    return 0;
}

遍历二维字符数组

#include <iostream>
#include<string.h>
using namespace std;
int main()
{
    char arr[5][32]={"\0"};
    int n=sizeof(arr)/sizeof(arr[0]);
    cout<<"输入5个字符串"<<endl;
    int i=0;
    for(i=0;i<n;i++){
        cout<<"输入第"<<i<<"个字符串"<<endl;
        cin>>arr[i];      //从键盘获取字符串
    }
    for(i=0;i<n;i++){       //遍历字符串
        cout<<"第"<<i<<"个字符串是:"<<arr[i]<<endl;
    }
    return 0;
}

函数

函数是c语言的功能单位,实现一个功能可以封装一个函数来实现。
定义函数的时候一切以功能为目的,根据功能去定函数的参数和返回值
需要传哪些数据给函数?(实参)
函数的功能代码(函数体)如何实现?
函数需要返回啥类型的数据?(函数的返回值类型)

函数的分类

定义角度:

库函数(c++语言库)、自定义函数、系统调用(内核提供给用户的函数接口)

有无参数:参数是函数外部数据 到 函数内部的 桥梁

无参的函数:不能将函数外部的数据 传递 给函数内部
有参的函数:通过参数 将函数外部的数据 传递到函数内部

函数的定义

实现函数体,确定函数名,函数的形参、函数的返回值类型

int my_add(int x, int y) 		//x,y是形参,定义的时候形参不会开辟空间,int是定义返回值的类型
							//函数调用的时候 才会为形参 开辟空间 保存实参的值
{
return x + y;//return 返回函数运算结果 结束当前函数,
}

函数声明

先调用函数 后定义函数 需要提前函数声明。或者函数在外部需要声明函数。

函数声明:告知编译器 该函数的函数名是啥 有几个形参 返回值类型是啥

函数的调用

一般调用格式是:函数名(实参);

大量调用函数 会发生 “出入栈”的开销

函数内部如果要修改外部的变量的值,需要传入外部变量的地址

#include <iostream>
#include<string.h>
using namespace std;
extern int my_add(int x, int y);  //函数声明
int main()
{
    int a=0,b=0;
    cout<<"输入第一个数"<<endl;
    cin>>a;
    cout<<"输入第二个数"<<endl;
    cin>>b;
    int add=my_add(a,b);          //函数调用,a,b是实参
    cout<<"和:"<<add<<endl;
    return 0;
}
int my_add(int x,int y)            //函数定义
{
    return x+y;
}

数组作为函数的参数

数值数组作为函数的参数,函数内部 可以 操作(读写) 外部数组的元素。

#include <iostream>
#include<string.h>
using namespace std;
extern void inputIntArr(int arr[],int n);  //函数声明,extern内部函数可省略
void printIntArr(int arr[],int n);             //函数声明
void sortIntArr(int arr[],int n);           //函数声明
int main()
{
    int arr[5]={0};
    int n=sizeof(arr)/sizeof(arr[0]);
    inputIntArr(arr,n);    //从键盘获取元素值
    sortIntArr(arr, n);    //排序
    printIntArr(arr,n);    //遍历
    return 0;
}
void inputIntArr(int arr[],int n)//相当于void inputIntArr(int *arr,int n)
{
    int i=0;
    for (i=0;i<n;i++)
    {
        cout<<"输入第个"<<i<<"元素"<<endl;
        cin>>arr[i];
    }
}
void sortIntArr(int arr[],int n)//相当于void sortIntArr(int *arr,int n)
{
    int i=0,j=0;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n-1;j++)
        {
           if(arr[j]>arr[j+1])
           {
               int tem=arr[j];
               arr[j]=arr[j+1];
               arr[j+1]=tem;
           }

        }
    }
}
void printIntArr(int arr[],int n) //相当于void printIntArr(int *arr,int n)
{
    int i=0;
    for (i=0;i<n;i++)
    {
        cout<<arr[i]<<endl;
    }
}

说明:arr是数组的名字也是数组的地址,函数中的形参int arr[]=int *(arr+0)=int *arr,所以数组作为实参也是传的地址,所以函数内部 可以 操作(读写) 外部数组的元素

给函数传一维数组

void fun(int p[])//形式1
void fun(int *p)//形式2

给函数传二维数组

void fun( int p[][4] )//形式1
void fun( int (*p)[4] )//形式2

传指针数组

void fun(char **q)

void fun(char *q[])

字符数组作为函数的参数

#include<iostream>
#include<string.h>
using namespace std;
int len_str(char str[]);
void my_str(char a[], int n);
int main()
{
    char str[32]="\0";
    int n=sizeof(str);
    my_str(str,n);
    int a=len_str(str);
    cout<<a<<endl;
   return 0;
}
void my_str(char a[], int n)
{
    cout<<"输入一个字符串"<<endl;
    cin.getline(a,n);
    cout<<a<<endl;
}
int len_str(char str[])
{
    return strlen(str);
}

预处理

进程:可执行文件 从运行到结束 整个动态的过程 就叫进程。(占内存空间)
在32位平台 每一个进程 占4G空间(虚拟空间)

内存分区

堆区:使用malloc,calloc,realloc,free,new,delete动态申请。可读可写

栈区:局部变量,函数的形参,返回值。可读可写

全局区:普通全局变量,静态全局变量,静态局部变量。可读可写

文字常量区:数值常量,字符常量,字符串常量,符号常量。只读

代码区:代码的二进制指令。只读

普通局部变量

定义形式:在{}里面定义的 普通变量 叫普通局部变量

作用范围:所在的{}复合语句之间有效
生命周期:所在的{}复合语句之间有效
存储区域:栈区

普通局部变量 不初始化 内容 不确定
普通局部变量 同名 就近原则(尽量别同名)

void func()
{ //复合语句
	int num = 10; //num 局部变量
	{
		int num = 20; //data 局部变量
		cout<<num<<endl;//20 就近原则
	}
	cout<<num<<endl;//10
}

普通全局变量

定义形式:在函数外定义的普通 变量

作用范围:当前源文件以及其他源文件 都有效。
生命周期:整个进程。
存储区域:全局区
注意事项:
1、全局变量不初始化 内容为0
2、全局变量 和 局部变量 同名 优先选择局部变量。

int data = 10; //普通全局变量
void func()
{
int data = 20;//普通局部变量
cout<<data<<endl;//20
cout<<::data<<endl;//10,通过作用域访问外部的data
}

3、其他源文件 使用全局变量 必须对全局变量 进行extern声明。(变量的使用所在的源文件)extern 声
明外部可用。该变量或函数 来自于其他源文件。

1.cpp
//extern 声明data为int类型 来之其他源文件
extern int data;//声明变量来自于其他源文件(2.cpp)
void add_data(void)
{
data = data+100;
return ;
}
2.cpp
extern void add_data(void);//声明函数来自于其他源文件(1.cpp)
int data = 10; //普通全局变量
int main()
{
add_data();
cout<<"data="<<data<<endl;
}

静态局部变量

作用范围:所在的{}复合语句之间有效
生命周期:整个进程有效
存储区域:全局区
注意事项:
1、静态局部变量不初始化 内容为0
2、静态局部变量 整个进程 都存在(第一次定义有效)

void fun04()
{
static int num=10;//不加static修饰,多次调用函数num一直是11
num++;
cout<<"num = "<<num<<endl;
}
int main()
{
fun04();//num = 11
fun04();//num = 12
fun04();//num = 13
fun04();//num = 14
}

静态全局变量

定义形式:在函数外 加static修饰定义的变量 就是静态全局变量

作用范围:只能在当前源文件使用 不能在其他源文件使用。
生命周期:整个进程
存储区域:全局区
注意事项:
1、静态全局变量不初始化 内容为0
2、静态全局变量 只能在当前源文件使用

int data3 = 10;//普通全局变量
static int data4 = 20;//静态全局变量
void test()
{
}

全局函数

函数默认 都为全局函数

全局函数:在当前源文件 以及其他源文件 都可以使用
如果其他源文件使用需要 extern对全局函数 进行声明

静态函数

加static修饰的函数

静态成员 只能在当前源文件用,其他源文件调用不了此函数

头文件

头文件包含:在预处理 结果 将头文件的内容 原封不动的 包含在 目的文件中

#include <head.h> <>包含系统头文件

<>从系统指定目录 寻找head.h头文件

#include “head.h” " "包含自定义头文件

“ ”先从当前目录 寻找head.h头文件 如果找不到 再到系统指定的目录下寻找

#define 宏

编译四阶段:预处理、编译、汇编、链接

使用关键字 define 定义 叫宏

宏的作用范围:是从定义处开始 到 当前文件结束 都有效

#undef可以结束宏的作用域

宏 没有作用域的限制 只在当前源文件 有效

#define ST 123 (宏定义)
在预处理结果 使用123替换所有出现ST的位置 (宏展开)
不要再宏后加;分号
宏尽量大写和普通变量区分开

不带参数的宏

#define ST 123
#define STR "hello"
#define NUM 100

带参数的宏(宏函数)

#define MY_ADD(a, b) a+b
cout<<MY_ADD(10,20);//10+20

宏的参数不能有类型

#define MY_ADD(int a, int b) a+b  //err

宏不能保证参数的完整性

#define MY_MUL(a, b) a *b
cout<<MY_MUL(10, 20); //10*20
cout<<MY_MUL(10 + 10, 20 + 20); //10 + 10*20 + 20 == 230

可以使用()的形式 让带参数的宏 具备一定的完整性

#define MY_MUL(a, b) a *b
#define MY_MUL2(a, b) ((a) * (b))
cout<<MY_MUL(10, 20); //10*20
cout<<MY_MUL(10 + 10, 20 + 20); //10 + 10*20 + 20 == 230
cout<<MY_MUL2(10 + 10, 20 + 20);//((10 + 10) * (20 + 20))==800

宏不能作为结构体、类的成员

宏函数和普通函数

函数有作用域的限制,可以作为类的成员
宏函数没有作用域限制,不能作为类的成员

带参宏的形参不需要类型

带参函数的形参需要类型

带参宏调用多少次就展开多少次,不需要压栈弹栈,浪费空间节省时间

带参函数代码只有一份,存在代码区,调用去代码区取指令,需要压栈弹栈,浪费时间节省空间

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值