Array of Strings in C++
在C++中有3中方法可以创建Array of Strings
- 使用二维数组(C/C++)
1.1 用字符数组表示的字符串
字符数组的初始化有两种
第一种初始化方式必须要为'\0'分配空间,也就是说, 用一个字符串初始化字符数组时,字符数组除了要保存这个字符串以外,还必须要保存至少一个'\0',char str2[6]="china"; char str3[5] = {'c','h','i','n','a'};
第二个初始化方式是用每一个单独的字符去初始化字符数组,在这种情况下不需要保存'\0', 只要满足字符数组的空间>=所要分配的字符大小即可。注意:字符数组的赋值不能用一个字符串赋值,而只能使用单个字符去对数组元素一一赋值。
在C语言中还可以用字符指针指向字符串:
str指向的是大小为5字节的内存空间,在这个空间中没有'\0',这个空间的首地址保存在str1中。char *str1="china";
不同于字符数组,对字符指针可以使用字符串整体赋值:
str1 = ”I love China";
char color[][10] = {"blue","Red","orange","yellow"};
1.2 用二维数组表示多个字符串
char color[][10] = {"blue","Red","orange","yellow"};//sizeof(color) = 40
for(int i = 0; i < 4;i++) cout<<color[i]<<endl;
//由于C/C++的多维数组是行优先,所以color数组的元素分布如下:
b l u e \0 \0 \0 \0 \0 \0 R e d \0 \0 \0 \0 \0 \0 \0 o r a n g e \0 \0 \0 \0 y e l l o w \0 \0 \0 \0 color[i]就是第i行的字符串的首地址。
输出是
这种方法的缺点:
- Number of Strings and Size of String – both the values are fixed.
- A 2D array is allocated, whose second dimension is equal to maximum sized string which causes wastage of space.
- 使用string(C++)
#include<bits/stdc++.h>
using namespace std;
int main()
{
// Initialize String Array
string colour[4] = {"Blue", "Red", "Orange", "Yellow"};
// Print Strings
for (int i = 0; i < 4; i++)
cout << colour[i] << "\n";
}
这种方法的缺点:
Array is of fixed Size
- 使用vectors(C++) STL Container Vector can be used to dynamically allocate Array.
// C++ program to demonstrate vector of strings using #include<bits/stdc++.h> using namespace std; int main() { // Declaring Vector of String type vector <string> colour; // Initialize vector with strings using push_back // command colour.push_back("Blue"); colour.push_back("Red"); colour.push_back("Orange"); colour.push_back("Yellow"); // Print Strings stored in Vector for (int i=0; i<colour.size(); i++) cout << colour[i] << "\n"; }
从以上3点来看,vector应该是c++中创建字符串数组最好的方法了
注意:‘\0'在C语言中是 字符串结束符,所以只有数组在处理字符串时才会用多余的一个字节来保存它,在其他情况(非字符数组)下,数组不会保存它
Array Decay in C++
What is Array Decay?
数组退化是指数组丢失了数组元素的类型和数组的大小。这通常发生在向函数按值传递或传递指针参数时,结果就是仅仅把实参的首地址传给了形参的数组,这时数组就退化为一个指针,数组的大小也会变成指针的大小而不是原数组的大小。
举个简单的例子:
输出#include <iostream> using namespace std; void findSize(int arr[]) { cout << sizeof(arr) << endl; } int main() { int a[10]; cout << sizeof(a) << " "; findSize(a); return 0; }
40 8d
// C++ code to demonstrate array decay #include<iostream> using namespace std; // Driver function to show Array decay // Passing array by value void aDecay(int *p) { // Printing size of pointer cout << "Modified size of array is by " " passing by value: "; cout << sizeof(p) << endl; } // Function to show that array decay happens // even if we use pointer void pDecay(int (*p)[7]) { // Printing size of array cout << "Modified size of array by " "passing by pointer: "; cout << sizeof(p) << endl; } int main() { int a[7] = {1, 2, 3, 4, 5, 6, 7,}; // Printing original size of array cout << "Actual size of array is: "; cout << sizeof(a) <<endl; // Calling function by value aDecay(a); // Calling function by pointer pDecay(&a); return 0; }
输出
Actual size of array is: 28 Modified size of array by passing by value: 8 Modified size of array by passing by pointer: 8
How to prevent Array Decay?一个典型的解决办法就是把数组大小也作为一个参数传给函数,并且对数组参数不要用sizeof。
另外一个解决办法就是把数组按引用传递给函数,这样就避免了数组转化为指针,也就避免了退化。比如
// C++ code to demonstrate prevention of // decay of array #include<iostream> using namespace std; // A function that prevents Array decay // by passing array by reference void fun(int (&p)[7]) { // Printing size of array cout << "Modified size of array by " "passing by reference: "; cout << sizeof(p) << endl; } int main() { int a[7] = {1, 2, 3, 4, 5, 6, 7,}; // Printing original size of array cout << "Actual size of array is: "; cout << sizeof(a) <<endl; // Calling function by reference fun(a); return 0; }
其它知识点:
- 数组指针:int (*t)[N] 表示一个数组指针,它的意思是,t是一个指向 在内存中连续存储的 N个int数据所组成的 块的指针,N必须与实参二维数组的列值相同。先看小括号得知t是一个指针,往右看得知它指向的是数组,再看最左边,数组元素是int型的。(所有的指针都可以这么解读,包括函数指针)
- 指针数组 :int (*t)[N] 表示t是一个数组,其中的元素是int*类型。
- 数组引用:int (&t)[N] 表示t是一个数组的引用,其它的意义同数组指针,可以作为其它数组的呃别名。
How to find size of array in C/C++ without using sizeof ?
举例:// C++ program to find size of an array by using a
// pointer hack.
#include <bits/stdc++.h>
using namespace std;
int main()
{
int arr[] = {1, 2, 3, 4, 5, 6};
int size = *(&arr + 1) - arr;
cout << "Number of elements in arr[] is "
<< size;
return 0;
}
在解释原理之前,先说明
arr与&arr的区别
如果分别打印arr和&arr的值,你会发现这两者的值是一样的:
printf("array=%p : &array=%p\n", array, &array);
printf("array+1 = %p : &array + 1 = %p", array+1, &array+1);
然而将它们分别加1以后的值就不一样了,这是因为
arr与&arr虽然都指向相同的地址,但是地址的类型是不同的。
- arr指向的是数组内的第一个元素的首地址,该元素类型是int,所以arr+1相当于第一个元素的首地址加4
- &arr指向的是整个数组的首地址,类型是数组,所以&arr+1就相当于数组的首地址加数组的大小(单位是byte,本例是24=0x18)
原理:
&arr ==> Pointer to an array of 6 elements. [See this for difference between &arr and arr] (&arr + 1) ==> Address of 6 integers ahead as pointer type is pointer to array of 6 integers. *(&arr + 1) ==> Same address as (&arr + 1), but type of pointer is "int *".类型转化 *(&arr + 1) - arr ==> Since *(&arr + 1) points to the address 6 integers ahead of arr, the difference between two is 6. 利用指针减法