1.二维数组作为函数参数传入
静态数组(维数确定)
二维数组作为函数的参数,实参可以直接使用二维数组名,在被调用函数中可以定义形参所有维数的大小,也可以省略以为大小的说明。例如:
1 2 void find(char a[3 ][10 ]);void find (char a[ ][10 ]) ;
也可以使用数组指针来作为函数参数,例如:
1 void find (char (*p)[10 ]);
但是不能像下面这样使用,例如:
1 2 void find(char a[ ][ ]);void find (char a[3 ][ ]) ;
因为从实参传递来的是数组的起始地址,如果在形参中不说明列数,编译器将无法定位元素的的位置。
栗子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <stdio.h> #include <string.h> void range (char str[ ][100 ]) ;int main (void ) { char str[8 ][100 ]; int i; for (i=0 ;i<8 ;i++) gets(str[i]); range(str); for (i=0 ;i<8 ;i++) printf ("%s\n" ,str[i]); } void range (char str[ ][100 ]) { int i,j; char temp[100 ]; for (i=0 ;i<8 -1 ;i++) { for (j=0 ;j<8 -i-1 ;j++) { if (strcmp (str[j],str[j+1 ])>0 ) { strcpy (temp,str[j]); strcpy (str[j],str[j+1 ]); strcpy (str[j+1 ],temp); } } } }
动态数组(维数不确定)
如果不确定二维数组的维数的话,我们不能使用上面的方法,可以用下面的方法:
手工转变寻址方式
对于数组 int p[m][n];
如果要取p[i][j]的值(i>=0 && m<=0 && j>=0 && n<=0),编译器是这样寻址的,它的地址为:p + (i*n + j) ;
二维数组的定义并非一个确定的值,也就是动态数组,这时候我们如果像之前那样进行函数调用就会报错,错误提示为:
1 [Error] cannot convert 'int (*)[N]' to 'int**' for argument '2' to 'int threeOrder_evaluation(int, int**)'
1 void printf_int (int hhh[][Dim]) ;
所以我们只能这样来调用
1 void printf_int (int ** hhh) ;
C++ Code:动态分配数组内存的六种方法
1、利用“malloc-free”动态分配一维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 #include <iostream> #include <stdlib.h> using namespace std ;int main () { int len; int *p; cout <<"请输入开辟动态数组的长度:" <<endl ; cin >>len; p = (int *)malloc (len*sizeof (int )); cout <<"请逐个输入动态数组成员:" <<endl ; for (int i=0 ; i<len; ++i) { cin >>p[i]; } cout <<"您输入的动态数组为:" <<endl ; for (int i=0 ; i<len; ++i) { cout <<p[i]<<" " ; } free (p); }
2、利用“malloc-free”动态分配二维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 #include <iostream> #include <stdlib.h> using namespace std ; int main () { int row,col; int **p; cout <<"请输入开辟动态数组的行 & 列:" <<endl ; cin >>row>>col; p = (int **)malloc (row*sizeof (int *)); for (int i=0 ; i<row; ++i) { *(p+i)=(int *)malloc (col*sizeof (int )); } cout <<"请逐个输入动态数组 各行各列 成员:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; ++j) { cin >>p[i][j]; } cout <<"您输入的动态数组 各行各列 成员如下:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; ++j) { cout <<p[i][j]; } for (int i=0 ; i<row; ++i) { free (*(p+i)); } }
3、利用“new-delete”动态分配一维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 #include <iostream> using namespace std ;int main () { int len; cout <<"请输入开辟数组的长度:" <<endl ; cin >>len; int *p = new int [len]; cout <<"请逐个输入数据:" <<endl ; for (int i=0 ; i<len; ++i) { cin >>p[i]; } cout <<"您分配的动态数组为:" <<endl ; for (int i=0 ; i<len; ++i) { cout <<p[i]<<" " ; } delete []p; }
4、利用“new-delete”动态分配二维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 #include <iostream> using namespace std ;int main () { int row,col; cout <<"请输入开辟数组的行 & 列:" <<endl ; cin >>row>>col; int **p = new int *[row]; for (int i=0 ; i<row; ++i) { p[i] = new int [col]; } cout <<"请逐个输入 各行各列 数据:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; ++j) { cin >>p[i][j]; } cout <<"您分配的动态数组为:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; ++j) { cout <<p[i][j]<<"" ; } delete []p; }
5、利用“new-delete”动态分配二维数组:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 #include <iostream> #include <vector> using namespace std ;int main () { int row,col; cout <<"请输入行 & 列:" <<endl ; cin >>row>>col; vector <vector <int > > p(row,vector <int >(col)); cout <<"请逐一输入 各行各列 数据:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; j++) { cin >>p[i][j]; } cout <<"您输入的数据:" <<endl ; for (int i=0 ; i<row; ++i) for (int j=0 ; j<col; j++) { cout <<p[i][j]<<" " ; } }
6、利用while的极其简单输入实现求和、求平均之类算法:
1 2 3 4 5 6 7 8 9 10 11 12 13 #include <iostream> using namespace std ;int main () { int sum=0 ,value=0 ; cout <<"请输入求和数字,以*号作为结束;" while (cin >>value) sum += value; cout <<"您输入数据之和为:" <<sum<<endl ; }
————————————————
版权声明:本文为CSDN博主「Errors_In_Life」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/Errors_In_Life/article/details/78889951
2.求逆矩阵
行列式的计算方法
1.对角线法
对角线法也是三阶行列式计算使用最广泛的方法
▍ 对角线法适用于二、三阶行列式,对于更高阶的行列式暂时未找到规律
2.代数余子式法
3.等价转化法
4.逆序法
总结
本文讲述了四种行列式的计算方法:
▍其中对角线法,是使用最简单、最广泛的方法
▍代数余子式法和等价转化法,在特定情况下能极大程度上简便运算,但需要读者对行列式进行灵活地观察
▍逆序数法,是一种更加基础的方法,使用起来比较复杂
3.函数返回一个数组,二维数组
与其他高级语言相比,c语言,c++ 最大的不方便之处就是 函数只能返回一个数值。若要返回一个数组 ,必须用到指针以及动态分配内存。
方法之一:返回一个结构体,结构体里面包括一个数组。
因为结构体运行效率略慢,这个方法我干脆不用了。
方法之二:利用指针函数,并结合动态内存。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 int *fun () {声明一个动态数组 a; return a;} void main () {用指针调用函数 int *p=fun(); 释放该指针 free (p); (相当于释放了指针函数里面的动态数组) }
举例:下面程序返回一个一维数组
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 #include "stdio.h" #include "stdlib.h" int * Max (int *arr,int n) { int *a=(int *)malloc (2 *sizeof (int )); int maxNum=0 ,maxIndex,i; for (i=0 ;i<n;i++) if (arr[i]>maxNum) {maxNum=arr[i];maxIndex=i+1 ;} a[0 ]=maxNum;a[1 ]=maxIndex; return a; } void main () { int a[2 ]={5 ,2 }; int *b=Max(a,2 ); int i; for (i=0 ;i<2 ;i++) printf ("b[%d]=%d\n" ,i,b[i]); free (b); }
这个程序中的max函数不仅能够返回一个数组的最大值,还能够显示这个最大值在数组中的位置。
下列程序返回一个二维数组,求出一个二维数组各行的最大值以及所在位置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include "stdio.h" #include "stdlib.h" int **Max (int **arr,int n,int m) { int **data; data=(int **)malloc (n*sizeof (int *)); for (int i=0 ;i<n;i++) data[i]=(int *)malloc (2 *sizeof (int )); for (int i=0 ;i<n;++i) { int maxNum=0 ; for (int j=0 ;j<m;++j) { if (*((int *)arr+m*i+j)>maxNum) { maxNum=*((int *)arr+m*i+j); data[i][0 ]=maxNum;data[i][1 ]=j; } } } return data; } void main () { int a[2 ][3 ]={5 ,2 ,4 ,6 ,3 ,9 }; int **b=Max((int **)a,2 ,3 ); for (int i=0 ;i<2 ;i++) { printf ("the maximum num for row %d is %d\n" ,i+1 ,b[i][0 ]); printf ("the maximum num for row %d is in %d" ,i+1 ,b[i][1 ]+1 ); printf ("\n" ); } for (int i=0 ;i<2 ;i++) free (b[i]); free (b); }
4.头文件
#include<stdlib.h>
#include<math.h>
1、 三角函数
double sin(double);正弦
double cos(double);余弦
double tan(double);正切
2 、反三角函数
double asin (double); 结果介于[-PI/2,PI/2]
double acos (double); 结果介于[0,PI]
double atan (double); 反正切(主值),结果介于[-PI/2,PI/2]
double atan2 (double,double); 反正切(整圆值),结果 介于[-PI,PI]
3 、双曲三角函数
double sinh (double);
double cosh (double);
double tanh (double);
4 、指数与对数
double frexp(double value,int exp);这是一个将value值拆分成小数部分f和(以2为底的)指数部分exp,并返回小数部分f,即f 2^exp。其中f取值在0.5~1.0范围 或者0。
double ldexp(double x,int exp);这个函数刚好跟上面那个frexp函数功能相反,它的返回值是x*2^exp
double modf(double value,double *iptr);拆分value值,返回它的小数部分,iptr指向整数部分。
double log (double); 以e为底的对数
double log10 (double);以10为底的对数
double pow(double x,double y);计算x的y次幂
float powf(float x,float y); 功能与pow一致,只是输入与输出皆为单精度浮点数
double exp (double);求取自然数e的幂
double sqrt (double);开平方根
5 、取整
double ceil (double); 取上整,返回不比x小的最小整数
double floor (double); 取下整,返回不比x大的最大整数,即高斯函数 [x]
6 、绝对值
double fabs (double);求实型的绝对值
double cabs(struct complex znum);求复数的绝对值
7 、标准化浮点数
double frexp (double f,int *p); 标准化浮点数,f = x * 2^p,已知f求x,p (x介于[0.5,1])
double ldexp (double x,int p); 与frexp相反,已知x,p求f
8 、取整与取余
double modf (double,double*); 将参数的整数部分通过指针回传,返回小数部分
double fmod (double,double); 返回两参数相除的余数
9 、其他
double hypot(double x,double y);已知直角三角形两个直角边长度,求斜边长度
double ldexp(double x,int exponent);计算x*(2的指数幂)
double poly(double x,int degree,double coeffs []);计算多项式
int matherr(struct exception *e);数学错误计算处理程序
5.关于模取余
1 2 3 4 5 6 7 8 9 10 11 #include <iostream> using namespace std ;int main () { cout <<3 %2 <<endl ; cout <<-3 %2 <<endl ; cout <<3 %-2 <<endl ; cout <<-3 %-2 <<endl ; return 0 ; }
多重for循环优化,提升运行效率
在循环次数较少的时候一般不会发现for循环的写法会对效率产生多大问题,但一旦循环次数较多,比如说上万,循环层数较多,效率问题就非常明显了,我是在做一个数据量非常大有三层for循环的项目的时候,为显示曲线出来太花费时间,客户体验会非常不好,才研究这个情况的,事实证明,优化后的多重for循环提升了一大半的效率,是不是很神奇。
当然,本文也有借鉴其他同胞的方法。
实例化变量放在for循环外,减少实例化次数,尽量只实例化一次;
普通变量 改为 寄存器变量
i++ 改为 ++i
1 2 3 int i=0, j; j=++i; //前置版本,运算对象先自增1,然后将改变后的对象作为求值结果,再赋值给j; j=i++; //后置版本,先赋值给j;再运算对象自增1,但求值结果是运算对象改变之前那个值的副本.
C++Primer 中解释:前置版本的递增运算符避免了不必要的工作,它把值加1后直接返回改变了的运算对象。与之相比,后置版本需要将原始值存储下来以便于返回这个未修改的内容,如果我们不需要修改前的值,那么后置版本的操作就是一种浪费。
for(int i = 0; i<50; i++)
循环条件使用<要快于<=,>和>=同理;
把外层可以计算的尽可能放到外层,减少在内层的运算,有判断条件的语句和与循环不相关的操作语句尽量放在for外面;
应当将最长的循环放在最内层,最短的循环放在最外层 ,以减少CPU跨切循环层的次数;
采用的是行优先访问原则,与元素存储顺序一致。
对于一个可结合和可交换的合并操作来说,比如整数的加法或乘法,
我们可以通过将一组合并操作分割成 2 个或更多的部分,并在最后合并结果来提高性能。
原理:
普通代码只能利用 CPU 的一个寄存器,分割后可以利用多个寄存器。
当分割达到一个数量时,寄存器用完,性能不再提升,甚至会开始下降。
用代码来描述,如下:
1 2 3 4 5 6 7 8 9 10 { res = res OPER i; } { res1 = res1 OPER i; res2 = res2 OPER (i+1 ); }
int 整数加法,性能测试结果对比如下:
整数的加法,普通代码运行 26s,循环分割后,18s。
浮点数计算的性能提升,明显大于整数,乘法的性能提升,略大于加法。