C++学习笔记三
C++数字
C++数学运算
C++内置了丰富的数学函数:
log(a) :返回参数a的自然对数;
pow(a,b):返回a^b次方;
hypot(a,b):a,b为直角边,返回斜边c的数值;
sqrt(a) :返回a的平方;
abs(int):返回整数的绝对值;
fabs(2.3):返回浮点数的整数值;
floor(a): 返回≤a的最大整数;
#include<iostearm>
#include<cmath>
using namespace std;int main()
{short s = 10;int i = -100;long l = 1000000;float f = 23.2;double d = 13.232;cout << "abs(i) = " << abs(i) << endl;
cout << "pow(i,s) = " << pow(i,s) << endl;
cout << "floor(f) =" << floor(f) << endl;
cout << "hypot(l,d) = " << hypot(l,d) <<endl;return 0;}
C++随机数
关于随机数生成器,有两个相关的函数。一个是 rand(),该函数只返回一个伪随机数。生成随机数之前必须先调用 srand() 函数。
#include <iostream>
#include <ctime>
#include <cstdlib>using namespace std;int main ()
{int i,j;// 设置种子srand( (unsigned)time( NULL ) );/* 生成 10 个随机数 */for( i = 0; i < 10; i++ ){// 生成实际的随机数j= rand();cout <<"随机数: " << j << endl;}return 0;
}
C++数学常数
#include<iosteram>
#include<cmath>
#include<numbers>
using namespace std;int main()
{cout << "pi:" << numbers::pi << endl;//πcout << "e:" << numbers::e << endl;//自然底数ecout << "phi" << numberss::phi << endl;//黄金比例return 0;}
C++数组
数组的声明并不是声明一个个单独的变量,比如 number0、number1、...、number99,而是声明一个数组变量,比如 numbers,然后使用 numbers[0]、numbers[1]、...、numbers[99] 来代表一个个单独的变量。数组中的特定元素可以通过索引访问。
所有的数组都是由连续的内存位置组成。最低的地址对应第一个元素,最高的地址对应最后一个元素。
double balance[10]:balance是一个可用数组,可以容纳10个类型为double的数字;
初始化数组
可以逐个初始化数组,
balance[4] = 30.8;(将数组中的第五个元素赋值为30.8)
也可以使用初始化语句
double balance[5] :{2.3 ,43.5, 3.5, 35.4,66.6};
如果省略掉数组的大小,则数组的大小为初始化时元素的个数,如下:
double balance[] = {1000.0, 2.0, 3.4, 7.0, 50.0};
访问数组元素
double salary = balance[9]; 将数组中的第九个元素赋值给salary变量。
#include<iostearm>
using namespace std;#include<iomanip>
using std::setw;int main()
{int n[10];for(int i = 0; i <10; i++)//初始化数组{n[i] = i + 100;}cout << "element" << setw(13) << "value" << endl;//这里 setw(13) 表示让紧随其后输出的 "Value" 占用 13 个字符的宽度。for(int j = 0; j < 10; j++){cout << setw(7) << j << setw(13) << n[j] << endl;//setw(7) 表示让 j(数组的索引)的输出占用 7 个字符宽度。}return 0 ;}
多维数组
int threedim[5][12][3];创建了一个三维的整数数组;
初始化二维数组
//这是一个三行四列的二维数组,进行初始化
int a[3][4] = { {0, 1, 2, 3} , /* 初始化索引号为 0 的行 */{4, 5, 6, 7} , /* 初始化索引号为 1 的行 */{8, 9, 10, 11} /* 初始化索引号为 2 的行 */
};//内部嵌套括号可选,下面与上面等同
int a[3][4] = {0,1,2,3,4,5,6,7,8,9,10,11};
访问二维数组:int salary = a[1][3];代表获取第二行第四个元素
#include <iostream>
using namespace std;int main ()
{// 一个带有 5 行 2 列的数组int a[5][2] = { {0,0}, {1,2}, {2,4}, {3,6},{4,8}};// 输出数组中每个元素的值 for ( int i = 0; i < 5; i++ )for ( int j = 0; j < 2; j++ ){cout << "a[" << i << "][" << j << "]: ";cout << a[i][j]<< endl;}return 0;
}
指向数组的指针
runoobAarray 是一个指向 &runoobAarray[0] 的指针,即数组 runoobAarray 的第一个元素的地址。因此,下面的程序片段把 p 赋值为 runoobAarray 的第一个元素的地址:
double *p;
double runoobAarray[10];p = runoobAarray;
使用数组名作为常量指针是合法的,反之亦然。因此,*(runoobAarray + 4) 是一种访问 runoobAarray[4] 数据的合法方式。
一旦把第一个元素的地址存储在 p 中,就可以使用 *p、*(p+1)、*(p+2) 等来访问数组元素。
#include<iostearm>
using namespace std;int main(){double runoobAarary[5] = {12.3,23.2,23.6,74.8,94.9};double *p;p = runoobAarary;cout << "使用指针的数组值" << endl;for(int i = 0; i < 5; i++){cout << "*( p +" << i << ") :" ;cout << *(p + i) << endl;}cout << "使用 runoobAarray 作为地址的数组值 " << endl;for(int i = 0; i < 5; i++){cout << "*( runoobAarray +" << i << "):" ;cout << *(runoobAarray + i) << endl;}}
传递数组给函数
C++ 传数组给一个函数,数组类型自动转换为指针类型,因而传的实际是地址
有以下三种方式
//1,形参是一个指针
void myFunction(int *param)
{
.
.
.
}//2,形参是一个已定义大小的数组
void myFunction(int param[10])
{
.
.
.
}//3,形参是一个未定义大小的数组
void myFunction(int param[])
{
.
.
.
}
以下为例子:
//定义函数
double getAverage(int arr[], int size)
{int i, sum = 0; double avg; for (i = 0; i < size; ++i){sum += arr[i];}avg = double(sum) / size;return avg;
}//调用上述函数
#include <iostream>
using namespace std;double getAverage(int arr[], int size);int main ()
{int balance[5] = {1000, 2, 3, 17, 50};double avg;// 传递一个指向数组的指针作为参数avg = getAverage( balance, 5 ) ;// 输出返回值cout << "平均值是:" << avg << endl; return 0;
}
从函数返回数组
C++ 不允许返回一个完整的数组作为函数的参数。但是可以通过指定不带索引的数组名来返回一个指向数组的指针。
如果想要从函数返回一个一维数组,必须声明一个返回指针的函数
int* myfunction(){...}
int* myfunction()
{static int myarray[3] = {1,2,3}return myarray;
}
#include<iostearm>
#include<cstdlib>
#include<ctime>using namespace std;//要生成和返回随机数的函数
int* getrandom()
{static int r[10];//设种子
srand((unsigned)time(NULL));
for(int i = 0; i<10; ++i)
{r[i] = rand();cout << r[i] << endl;
}return r;}//调用上面函数
int main()
{int* p;p = getrandom;for(int i = 0; i<10; i++)
{cout << "*(p +" << i << "):";cout << *(p + i) << endl;
}return 0;}
C++字符串
C风格和c++风格字符串都可使用
C风格字符串
下面的声明和初始化创建了一个 RUNOOB 字符串。由于在数组的末尾存储了空字符,所以字符数组的大小比单词 RUNOOB 的字符数多一个。
char site[5] = {'b', 'l', 'u', 'e', '/0' };
char site[] = "blue";
C++中有大量的函数用来操作以NULL结尾的字符串:
#include<iosteram>
#include<string>using namespace std;int main()
{char str1[13] = "runobb";char str2[13] = "google";cahr str3[13];int len;strcpy(str3, str1);cout << "strcpy(str3, str1) : " << str3 << endl;strcat(str1, str2);cout <<"strcat(str1, str2) : " << str1 << endl;len = strlen(str1)cout << "strlen(str1)" << len << endl;return 0; }
C++中的string类
#include <iostream>
#include <string>using namespace std;int main ()
{string str1 = "runoob";string str2 = "google";string str3;int len ;// 复制 str1 到 str3str3 = str1;cout << "str3 : " << str3 << endl;// 连接 str1 和 str2str3 = str1 + str2;cout << "str1 + str2 : " << str3 << endl;// 连接后,str3 的总长度len = str3.size();cout << "str3.size() : " << len << endl;return 0;
}
C++指针
每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。
#include <iostream>using namespace std;int main ()
{int var1;char var2[10];cout << "var1 变量的地址: ";cout << &var1 << endl;cout << "var2 变量的地址: ";cout << &var2 << endl;return 0;
}
int *ip; /* 一个整型的指针 */
double *dp; /* 一个 double 型的指针 */
float *fp; /* 一个浮点型的指针 */
char *ch; /* 一个字符型的指针 */
使用指针时会频繁进行以下几个操作:定义一个指针变量、把变量地址赋值给指针、访问指针变量中可用地址的值。这些是通过使用一元运算符 * 来返回位于操作数所指定地址的变量的值。
#include <iostream>using namespace std;int main ()
{int var = 20; // 实际变量的声明int *ip; // 指针变量的声明ip = &var; // 在指针变量中存储 var 的地址cout << "Value of var variable: ";cout << var << endl;// 输出在指针变量中存储的地址cout << "Address stored in ip variable: ";cout << ip << endl;// 访问指针中地址的值cout << "Value of *ip variable: ";cout << *ip << endl;return 0;
}//产生以下结果
Value of var variable: 20
Address stored in ip variable: 0xbfc601ac
Value of *ip variable: 20
NULL指针
在变量声明的时候,如果没有确切的地址可以赋值,为指针变量赋一个 NULL 值是一个良好的编程习惯。赋为 NULL 值的指针被称为空指针。NULL 指针是一个定义在标准库中的值为零的常量。
#include<iostearm>
using namespace std;int main()
{int *ptr = NULL;cout << "ptr的值(地址形式)为 : " << ptr;return 0;}
指针的算术运算
加法运算:可以对指针进行加法运算。当一个指针p加上一个整数n时,结果是指针p向前移动n个元素的大小。例如,如果p是一个int类型的指针,每个int占4个字节,那么p + 1将指向p所指向的下一个int元素。
减法运算:可以对指针进行减法运算。当一个指针p减去一个整数n时,结果是指针p向后移动n个元素的大小。例如,如果p是一个int类型的指针,每个int占4个字节,那么p - 1将指向p所指向的前一个int元素。
指针与指针之间的减法运算:可以计算两个指针之间的距离。当从一个指针p减去另一个指针q时,结果是两个指针之间的元素个数。例如,如果p和q是两个int类型的指针,每个int占4个字节,那么p - q将得到两个指针之间的元素个数。
指针与整数之间的比较运算:可以将指针与整数进行比较运算。可以使用关系运算符(如<、>、<=、>=)对指针和整数进行比较。这种比较通常用于判断指针是否指向某个有效的内存位置。
在C++中,指针是一个变量,它存储一个内存地址。递增一个指针意味着将指针指向下一个内存位置,这通常是指向下一个数组元素。递增一个指针会根据指针所指向的数据类型自动调整指针的值。例如,如果指针指向一个 int 类型的数组元素,那么递增指针将使其指向下一个 int 元素。
#include<iostearm>
using namespace std;int main()
{int arr[] = {1, 2, 3, 4, 5};int *ptr = arr;cout << "指针当前指向的数值: " << *ptr << endl;ptr++;cout << "递增指针后指向的数值 : " << *ptr << endl;return 0;
}
指针的比较操作可以用于确定两个指针是否指向相同的位置、一个指针是否指向的位置在另一个指针之前或之后等。在比较指针时,一定要确保不是空指针,否则会导致未定义行为。
1.相等性比较用于检查两个指针是不是指向同一个位置
#include <iostream>int main() {int a = 10;int b = 20;int* ptr1 = &a;int* ptr2 = &a;int* ptr3 = &b;// 比较指针是否相等if (ptr1 == ptr2) {std::cout << "ptr1 和 ptr2 指向相同的位置" << std::endl;} else {std::cout << "ptr1 和 ptr2 指向不同的位置" << std::endl;}if (ptr1 != ptr3) {std::cout << "ptr1 和 ptr3 指向不同的位置" << std::endl;} else {std::cout << "ptr1 和 ptr3 指向相同的位置" << std::endl;}return 0;
}
2. 关系比较用于确定一个指针是否指向的位置在另一个指针之前或之后。这通常在指针指向同一个数组的元素时有意义。
#include <iostream>int main() {int arr[] = {10, 20, 30, 40, 50};int* ptr1 = &arr[1]; // 指向数组的第二个元素int* ptr2 = &arr[3]; // 指向数组的第四个元素// 比较指针的相对位置if (ptr1 < ptr2) {std::cout << "ptr1 指向的元素在 ptr2 指向的元素之前" << std::endl;} else {std::cout << "ptr1 指向的元素不在 ptr2 指向的元素之前" << std::endl;}if (ptr2 > ptr1) {std::cout << "ptr2 指向的元素在 ptr1 指向的元素之后" << std::endl;} else {std::cout << "ptr2 指向的元素不在 ptr1 指向的元素之后" << std::endl;}return 0;
}
指针和数组
#include<iostearm>
using namespace std;
const int MAX = 3;int main()
{int var[MAX] = {10, 100, 1000};int *ptr;ptr = var;for(int i = 0; i< max; i++)
{cout << "var[" << i << "] 内存地址为 "cout << ptr << endl;cout << "var[" << i << "] 的数值为 "cout << *ptr << endl;ptr++
}return 0;}
指针和数组并不是完全互换的。
#include <iostream>using namespace std;
const int MAX = 3;int main ()
{int var[MAX] = {10, 100, 200};for (int i = 0; i < MAX; i++){*var = i; // 这是正确的语法var++; // 这是不正确的}return 0;
}
把指针运算符 * 应用到 var 上是完全可以的,但修改 var 的值是非法的。这是因为 var 是一个指向数组开头的常量,不能作为左值。
由于一个数组名对应一个指针常量,只要不改变数组的值,仍然可以用指针形式的表达式。例如,下面是一个有效的语句,把 var[2] 赋值为 500:*(var + 2) = 500;
C++指针数组
int *ptr[MAX]; 在这里,把 ptr 声明为一个数组,由 MAX 个整数指针组成。因此,ptr 中的每个元素,都是一个指向 int 值的指针。
#include <iostream>using namespace std;
const int MAX = 3;int main ()
{int var[MAX] = {10, 100, 200};int *ptr[MAX];for (int i = 0; i < MAX; i++){ptr[i] = &var[i]; // 赋值为整数的地址}for (int i = 0; i < MAX; i++){cout << "Value of var[" << i << "] = ";cout << *ptr[i] << endl;}return 0;
}
#include <iostream>using namespace std;
const int MAX = 4;int main ()
{const char *names[MAX] = {"Zara Ali","Hina Ali","Nuha Ali","Sara Ali",};for (int i = 0; i < MAX; i++){cout << "Value of names[" << i << "] = ";cout << names[i] << endl;}return 0;
}
指向指针的指针
一个指向指针的指针变量必须如下声明,即在变量名前放置两个星号。例如,下面声明了一个指向 int 类型指针的指针:int **var;
#include<iostearm>
using namespace std;int main(){int var;int *ptr;int **pptr;var = 3000;ptr = &var;//获取VAR的地址pptr = &ptr;//获取ptr的地址cout << "var的数值为: " << var << endl;cout << "*ptr的数值为: " << *ptr << endl;cout << "**pptr的数值为: " << **pptr << endl;return 0;
}
C++传递指针给函数
只需要简单声明函数的参数类型为指针即可
#include <iostream>
#include <ctime>using namespace std;// 在写函数时应习惯性的先声明函数,然后在定义函数
void getSeconds(unsigned long *par);int main ()
{unsigned long sec;getSeconds( &sec );//*par要求传入变量为地址// 输出实际值cout << "Number of seconds :" << sec << endl;return 0;
}void getSeconds(unsigned long *par)
{// 获取当前的秒数*par = time( NULL );return;
}