数组

一组有相同数据类型的结构,数据的有序集合,通过下标区分不同变量

  • 减少变量数量
  • 统一的数组名易于理解和使用
  • 可利用循环语句对数组元素进行操作

一维数组

类型名 数组名[常量表达式(数组长度)] ,如int a[10],下标是从0开始的,比如这个例子的下标就是0-9

C++不允许用变量作为数组长度

1
2
3
4
5
6
7
8
9
10
11
/*利用循环语句实现*/
#include <iostream>
using namespace std;

int main(){
int i,a[10];
for(i=0;i<=9;i++)a[i] = i+1; //使a[0]的值为1,后面的类似
for(i=9;i>=0;i--)cout<<a[i]<<" "; //逆序输出
cout<<endl;
return 0;
}

需要注意的是,若只定义而不赋值,那么数组内的每个元素值都是不确定的

定义初始化示例:int a[10]= {0,1,2,3,4,5,6,7,8,9};

也可以只给部分元素赋值:int a[10] = {0,1,2,3,4};(此时后5个元素默认为0)

也可以不指定数组长度:int a[ ] = {1,2,3,4,5};此时系统会根据{}内的元素个数自动定义长度

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
/*数组的输入*/
int main(){
int i;float x[10];
for(i=0;i<10;i++)cin>>x[i];
}
/*数组的输出*/
for(i=0;i<10;i++){
if(i%5==0)cout<<endl; //一行输出5个
cout<<x[i]<<" ";
}
/*利用一维数组,实现求平均值函数定义*/
float average(float x[],int n)
{ float s=0;int i;
for(i=0;i<n;i++)
s+=x[i];
return(s/n);
}
/*利用一维数组,实现求最大值定义*/
float max(float x[],int n)
{ float m;int i;
m=x[0];
for(i=1;i<n;i++)
if(m<x[i]) m=x[i];
return(m);
}

求斐波那契数列

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<iomanip>
using namespace std;

/*方法一 : 函数+循环*/
int fibonacci(int n)
{ int y;
if (n==1) y=1;
else if(n==2) y=1;
else y=fibonacci(n-1)+fibonacci(n-2);
return y;
}
int main()
{ int n,i;
cout<<"n=(3-50):";cin>>n;
for(i=1;i<=n;i++)
{ cout<<setw(8)<<fibonacci(i); //输出内容< 设置宽度(8):用空格填充剩余位置,默认右对齐
if(i%5==0) cout<<endl;
}
cout<<endl;
}
/*方法二 : 数组*/
int main()
{ int i;int f[20]={1,1};
for(i=2;i<20;i++)
f[i]=f[i-2]+f[i-1];
for(i=0;i<20;i++)
{ if(i%5==0) cout<<endl;
cout<<setw(8)<<f[i]; }
cout<<endl;
return 0; }

排序

将一组无序的数据按照某种(从小到大或从大到小)顺序重新排列的过程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
/*交换法排序,两两依次比较*/
for(i = 0; i < n - 1; i++) {
for(j = i + 1; j < n; j++) {
if(a[i] > a[j]) {
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
}
/*冒泡排序*/
for(j=0; j<9; j++)
{
for(i=0; i<9-j; i++)
{
if (a[i]>a[i+1])
{
t=a[i];
a[i]=a[i+1];
a[i+1]=t;
}
}
}

查找

从一组数中找出指定的数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/*顺序查找:从表的一端开始逐个进行记录的关键字和给定值的比较*/
// arr=数组,n=数组长度,target=查找目标
int sequentialSearch(int arr[], int n, int target) {
for (int i = 0; i < n; i++) {
if (arr[i] == target) return i; // 找到目标,返回下标
}
return -1; // 未找到,返回-1
}
/*折半查找:适用于采用顺序存储结构的有序表,每次将待查记录所在区间缩小一半*/
int binarySearch(int arr[], int n, int target) {
int left = 0, right = n - 1; // 初始化左右边界
while (left <= right) {
int mid = left + (right - left)/2; // 计算中间下标(避免溢出)
if (arr[mid] == target) return mid; // 找到目标,返回下标
else if (arr[mid] < target) left = mid + 1; // 目标在右半区
else right = mid - 1; // 目标在左半区
}
return -1;
}

二维数组

类型名 数组名【常量表达式【常量表达式】

如:float a【3】【4】,b【5】【10】,就是定义了两个二维数组,数组a是一个具有三行四列的二维数组

数组各个元素在内存中的存放顺序是: 先行后列

可将其理解为有三个元素a[0]、a[1]、a[2],每一个元素是一个包含4个元素的一维数组。

三维及以上的数组称为多维数组

在引用时可以用 a【2-1】【2*2-2】 = 1,等价于a[1] [2]

数组元素可以被赋值,如 b[1] [2]=a[2] [3]/2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*将一个2×3的二维数组a的行和列元素互换,存到一个3×2的二维数组b中*/
#include <iostream>
using namespace std;
int main()
{
int a[2][3]= {{1,2,3},{4,5,6}};//按行给二维数组全部元素赋初值,对部分元素赋初值一般按行
int b[3][2],i,j;
cout<<"array a:"<<endl;
for (i=0; i<=1; i++) {
for (j=0; j<=2; j++) {
cout<<a[i][j]<<" "; //输出a[i][j] 元素
b[j][i] = a[i][j]; //遍历数组a的同时赋值到数组b
}
cout<<endl;
} //for循环结束
cout<<"array b:"<<endl;
for (i=0; i<=2; i++)
{
for(j=0; j<=1; j++){
cout<<b[i][j]<<" "; //按行输出b数组中各元素
cout<<endl; //换行
20 }
21 return 0;
22 }

做函数参数

1)用数组元素做函数实参(与变量相同)

[!NOTE]

只是单向的值传递(实参→形参),实参和形参分别为不同的内存地址;

形参的值在函数中如何改变不影响实参。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/*有一个3×4的矩阵,要求编程序求出其中值最大的那个元素的值,以及其所在的行号和列号。*/
int max_value(int x, int max){
if(x>max)return x;
else return max;
}
int main(){
int max,i,j,row=0,column=0;
int[3][4]={{12,223,45,6},{15,18,19,22},{1,15,12,55}};
max=a[0][0];
for(i=0;i<=2;i++){
for(j=0;j<=3;j++){
max = max_value(a[i][j],max);
if(max==a[i][j])max=a[i][j];
row=i;
coulum=j;
}
}
cout<<"max="<<max<<",rouw="<<row<<",column="<<coulmn<<endl;
return 0;
}

2)用数组名做实参和形参(传递的数组起始地址)

[!NOTE]

实参数组与形参数组的名字可以不一样,但需要都是数组

实参数组名后不需括号,只需数组名;

形参数组名后需要括号,但大小可以不定义

形参数组与实参数组共享同一个内存空间,形参数组元素值的改变也即是实参数组元素值的改变。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*有一个3×4的矩阵,求矩阵中所有元素中的最大值。要求用函数处理。*/
1 #include <iostream>
2 using namespace std;
3 int max_value(int array[3][4]); //函数声明
4 int main()
5 {
6 int a[3][4]={{5,12,23,56},{19,28,37,46},{-12,-34,6,8}};
7 cout<<"max value is: "<< max_value(a) <<endl;
8 return 0;
9 }
10 int max_value(int array[3][4])
11 {
12 int i,j,max;
13 max = array[0][0];
14 for( i=0; i<3; i++)
15 for(j=0; j<4; j++)
16 { if(array[i][j]>max)
17 max = array[i][j];
18 }
19 return max; //返回最大值
20 }

字符数组

:用于存放字符型数据的数组。

char 数组名 [常量表达式] [常量表达式] ;

一维字符数组:存放一个字符串(每个数组元素存放一个字符)

二维字符数组:存放多个字符串(每一行是一个字符串)、

定义数组大小时至少留出一个字符空间存放结束标记【对于字符串常量,系统会自动在所有字符的后面加一个’\0’作为结束符,然后再把它存储在字符数组中】,初始化未指定的数组元素为’\0’

字符数组的输入输出可以有两种方法:

  1. 逐个字符输入输出:char c[10];for( int i=0 ; i<10 ; i++ ) cin >> c[i];
  2. 将整个字符串一次输入或输出:char str[10];cin>>str;cout<<str;

输入字符串时应格外小心, 保证字符串的长度小于字符数组的长度。

用函数实现输入输出

1
2
3
4
5
6
7
8
9
10
11
12
13
14
/*以C语言为例,%c: 输入/输出一个字符;%s: 输入/输出一个字符串*/
//用scanf函数输入字符串时,会以"空格"键或回车键作为字符串的输入结束符号。
scanf("%c", &str[0]); //输入一个字符给元素str[0]
scanf("%s", str); //输入一个字符串给数组str
printf("%s", str); //输出数组str,输出到末尾或遇到'\0'
/*以下是专用输入方式,输入过程中,遇回车符" Enter " 结束,并将其转换为'\0' 存入字符串尾部*/
char ch,zh[15];
ch = getchar();
gets(zh);
// fgets(zh, sizeof(zh), stdin); 改成fgets形式可以避免溢出
putchar();
putchar(zh[1]);
puts(zh);
//C++的话直接就cin,cout了,直接又省事

字符串处理函数

字符串处理函数是放在函数库中的,调用时使用 #include <cstring>

  • 字符串连接函数strcat【函数原型:strcat(char[],const char[])】

将第2个字符数组中的字符串连接到第1个字符数组的字符串的后面

连接后的字符串放在第一个字符数组中。

第2个字符数组被声明为const,以保证该数组中的内容不会在函数调用期间被修改。

1
2
3
4
5
char str1[30]= "People's Republic of ";
char str2[ ]= "China";
strcat( str1, str2 ); //调用strcat函数
cout << str1 << endl; //输出: People's Republic of China
cout << str2 << endl; //输出: China
  • 字符串复制函数strcpy【strcpy( char[ ], const char[ ])】

将第2个字符数组中的字符串复制到第1个字符数组中去,将第1个字符数组中的相应字符覆盖

第1个字符串后面剩余的部分保持不变,可以用strcpy函数指定将一个字符串中前若干个字符复制到一个字符数组中去。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstring>
using namespace std;
int main( )
{ char a1[20] , a2[20] = "China", a3[20] = "HaiNan" ;
strcpy( a1, a2);
strcpy(a2, a3,2); //作用是将a3中前面2个字符复制到a2中去
strcpy(a3, "BeiJing" );
cout << "a1= " << a1 << endl; //输出:a1= China
cout << "a2= " << a2 << endl; //输出:a2= Haina
cout << "a3= " << a3 << endl; //输出:a3= BeiJing
return 0;
}
/*注意!!!*/
char str1[10] , str2[10];
str1= "China"; //错误,不能将一个字符串常量赋给一个字符数组
str1= str2; //错误,不能将一个字符数组的内容赋给另一个字符数组
char str[10] = "China" //✔
  • 字符串比较函数strcmp【int strcmp(const char[ ], const char[ ]);】

函数不改变两字符串的内容,因此两个参数都加上const。

常见形式:if(strcmp(str1,str2)>0) cout<<”yes”;

比较两个字符串。按ASCII码值从左向右逐字符比较,直到出现不同字符,或字符串结束,或遇到’\0’ 为止

字符串1等于字符串2,函数值 = 0;

如果字符串1大于字符串2,函数值 > 0 ( 1 );

如果字符串1小于字符串2,函数值 < 0 ( -1 )。

  • 字符串长度函数strlen【strlen(const char[ ])】

测试字符串长度的函数(有效字符),返回字符串长度值,不包括’\0’ 。

1
2
strcpy( str, "hello\0world" );
cout << strlen(str); //输出5
  • 其他常用:trstr函数:字符串查找 strtok函数:字符串分解

字符串类与字符串变量

C++提供的新数据类型:string类型
[!IMPORTANT]

string str ; str = "China"; 是正确的,因为string类型的变量可以直接赋值,要与前面的字符数组区分好,string类型更方便、更安全,string类型的变量存储字符串长度不限

它是在C++标准库中声明的一个字符串类(class),用这种类可以定义对象,使用时必须用#include<string>

  • 定义字符串变量【string 变量名;】

string string2 = "China";定义string2同时对其初始化

字符数组s1和s2的值在定义时分配内存后就不能变了,是常量;

可以用一个字符串变量给另一个字符串变量赋值,两字符串长度可以不同

  • 字符串复制直接用赋值号:string string1, string2;string1 = string2;
  • 字符串连接直接用加号:string1= string1 + string2;
  • 字符串比较直接用关系运算符cout << (string1 > string2); // 输出 true (1)
  • 也可以用string定义字符串数组,如string name[5]= {"Zhang", "Li", "Sun", "Wang", "Tan"};

string字符串数组中包含若干个元素,每个元素相当于一个字符串变量

不要求每个字符串元素具有相同的长度,即使对同一个元素而言,它的长度也是可以变化的

串数组中的每一个元素的值只包含字符串本身的字符,而不包括’\0’。

string类定义的每一个变量自身值的长度是固定不变的