c++数组学习

C++中数组定义及初始化

一、一维数组

  1. 静态 int array[100];   定义了数组array,并未对数组进行初始化
  2. 静态 int array[100] = {1,2};  定义并初始化了数组array
  3. 动态 int* array = new int[100];  delete []array;  分配了长度为100的数组array 
  4. 动态 int* array = new int[100](1,2);  delete []array; 为长度为100的数组array初始化前两个元素

二、二维数组

  1. 静态 int array[10][10];  定义了数组,并未初始化
  2. 静态 int array[10][10] = { {1,1} , {2,2} };  数组初始化了array[0][0,1]及array[1][0,1]
  3. 动态 int (*array)[n] = new int[m][n]; delete []array;
  4. 动态 int** array = new int*[m]; for(i) array[i] = new int[n];  for(i) delete []array[i]; delete []array;    多次析构
  5. 动态 int* array = new int[m][n];  delete []array;      数组按行存储

三、多维数组

  int* array = new int[m][3][4];    只有第一维可以是变量,其他维数必须是常量,否则会报错

      delete []array;       必须进行内存释放,否则内存将泄漏

 

 

四、数组作为函数形参传递

  1. 一维数组传递:
    1.   void func(int* array);
    2.   void func(int array[]);    
  2. 二维数组传递:
    1.   void func(int** array);
    2.   void func(int (*array)[n]);

数组名作为函数形参时,在函数体内,其失去了本身的内涵,仅仅只是一个指针,而且在其失去其内涵的同时,它还失去了其常量特性,可以作自增、自减等操作,可以被修改。

 

五、字符数组

char类型的数组被常委字符数组,在字符数组中最后一位为转移字符'\0'(也被成为空字符),该字符表示字符串已结束。在C++中定义了string类,在Visual C++中定义了Cstring类。

字符串中每一个字符占用一个字节,再加上最后一个空字符。如:

char array[10] = "cnblogs";

虽然只有7个字节,但是字符串长度为8个字节。

 

也可以不用定义字符串长度,如:

char array[] = "cnblogs";

 

 

 

 

 

 

 

 

 

 

 

 

C语言char*字符串数组和unsigned char[]数组的相互转换

 

【规则】  
1  、  string  为普通类型,不是数组型,只是其内容为字符串;  
2  、  ’a’  和  ”a”  的区别:  ’a’  为字符,  ”a”  为字符串;单引号只能定义一个字符,双引号可以定义多个字符,即字符串。  
3  、指针可以通过加减、自加减改变其值,数组不可以。  
4  、以数组定义的字符串可以修改其中的字符,以指针定义的字符串不能修改其中的字符。  
  
 例如:
 char a[]=”hello”;
 cout<<a;               //输出 hello
 cout<<*(a+1);      //输出 e,即数组a的第2个字符,即a[1]
 cout<<a[1];          //输出 e,即数组a的第2个字符,与上同
 cout<<*a++;        //错误,规则3,数组名是常量,不可以改变其值
 cout<<*a;            //输出 h,即数组a的第一个字符
 cout<<a;              //输出hello
 *a=”L”;            //错误,规则2,*a为字符,”L”为字符串,不匹配
 *a=’L’;            //正确,规则4,将数组第一个字符修改为L
 cout<<a;              //输出 Lello
 a[2]=’6’;          //正确,规则4,将数组第3个字符修改为’6’
 cout<<a;              //输出 Le6lo
  
 char *a="hello";
 cout<<a;            //输出 hello
 cout<<*(a+1);    //输出 e,即字符串a的第2个字符
 cout<<a[1];        //输出 e,即字符串a的第2个字符,这里也可以视为数组a
 cout<<*a++;      //输出 h,,规则3,即先计算*a,再使a=a+1
 cout<<*a;          //输出 e,因上一行中a已经自加1
 cout<<a;            //输出 ello,因为指针a已经发生变化,指向了下一个地址,即指向以e开头的字符串
 *a=’L’;         //错误,规则4,不能修改指针定义的字符串的字符。
                            //【注意】此处编译可通过,运行时会出错,提示“不能写入”
 a[2]=’6’;      //错误,规则4,不能修改指针定义的字符串的字符。


1、以字符串形式出现的,编译器会在结尾自动添加\0,思考,为什么?

  存在的C语言方法,如strlen(s),计算字符串的长度,其中s指针。strlen要计算字符串长度,必须知道哪里是结尾,因此使用\0表示结尾。只有字符数组才有\0的概念,其它类型(int)的数组没有这个概念。因为其他类型的数组或者指针,没有strlen这种方法。

  那么问题来了,int数组如何计算长度呢?如int a1 = {3,7,9,};

  使用sizeof(a1)/sizeof(int)。

2、数组可以在栈上分配,也可以在堆上分配,但必须指定大小。

  char a1[100]; //在栈上分配

  char* pa = new char[100];// 在堆上分配,返回首元素的地址

3、char a1[] = "abc"; 相当于在栈顶分配4个字节,分别放上a,b,c,\0,等价于char a1 ={'a','b','c','\0'};

4、char* pa = "abc"; 分析一下就知道,pa是char指针,"abc"是一个文本字符串,显然类型不吻合,需要适配。可认为编译器做了下面的事情:在常量区分配4个字节,分别放上a,b,c,\0,然后把a的地址返回给pa。

  注意:文本字符串放在常量区,是不可修改的,试图修改,运行异常。那么在思考一下,既然右边是const,而pa并没有限定为const char*,按道理赋值失败。为什么可以成功?

  可以认为在C语言中,到处充斥着这样的代码。为了兼容,必须允许。但是,我们应该写const char* pa ="abc"; 这样的话,试图修改pa的内容,编译报错。

5、char a1[] = "abc", 等价于char a1[] = {'a','b','c','\0',}; strlen(a1)等于3,长度不包括\0

  假如这样写 char a1[] = {'a','b','c',}; strlen(a1)是多少? 答案不确定,因为strlen一直找到\0才认为是结尾。
6、 char a1[] = "abc"; 下面的结果分别是什么?

  cout<<&a1[0]<<endl;

  cout<<a1<<endl;

  输出相同,都是数组元素的第一个地址。

7、char* pa = "abc"; 下面的结果分别是什么?

  cout<<&pa<<endl;

  cout<<&pa[0]<<endl;

  cout<<pa<<endl;

  第一行输出pa在栈上的地址,第二行和第三行输出相同,都是首地址。pa是指针,就是指向首个元素的地址。

8、char a1[5]; 数组名是个指针常量,不能修改指向。

9、char* pa = "abc"; 可认为pa是个指向常量的指针。

10、下面的结果,违反直觉,按道理第4行,第5行应该输出地址。但是却输出指向的字符串。这有一定的合理性,我们打印char指针,往往是要看指向的内容,而不是要看地址是多少。而且cout很容易做到,只要遇到\0就结束。那么问题来了,我想看地址怎么办?使用int强制转化为地址。

1  char a1[]="abc";
2  char* pa="def";
3 
4  cout<<a1<<endl; //输出abc
5  cout<<pa<<endl; //输出def
6 
7  cout<<(int)a1<<endl; // 输出a1地址
8  cout<<(int)pa<<endl; // 输出pa地址

11、

1  char p[]="abcde";
2  char* p2="abcde";
3 
4  cout<<sizeof(p)<<endl; //数组大小为6
5  cout<<sizeof(p2)<<endl; // 指针大小为4
6 
7  cout<<strlen(p)<<endl; // 长度为5
8  cout<<strlen(p2)<<endl; // 长度为5

    1. #include <iostream>
    2. #include <string>
    3. using namespace std;
    4.  
    5. void convertUnCharToStr(char* str, unsigned char* UnChar, int ucLen)
    6. {
    7. int i = 0;
    8. for(i = 0; i < ucLen; i++)
    9. {
    10. //格式化输str,每unsigned char 转换字符占两位置%x写输%X写输
    11. sprintf(str + i * 2, "%02x", UnChar[i]);
    12. }
    13. }
    14.  
    15. void convertStrToUnChar(char* str, unsigned char* UnChar)
    16. {
    17. int i = strlen(str), j = 0, counter = 0;
    18. char c[2];
    19. unsigned int bytes[2];
    20.  
    21. for (j = 0; j < i; j += 2)
    22. {
    23. if(0 == j % 2)
    24. {
    25. c[0] = str[j];
    26. c[1] = str[j + 1];
    27. sscanf(c, "%02x" , &bytes[0]);
    28. UnChar[counter] = bytes[0];
    29. counter++;
    30. }
    31. }
    32. return;
    33. }
    34.  
    35. int main()
    36. {
    37. unsigned char src[6] = {0x12, 0x32,0x56,0x78,0x90,0xab};
    38. char buffer[20];//维数定义些
    39. convertUnCharToStr(buffer, src, 6);
    40. printf("%s\n", buffer);
    41.  
    42.  
    43. unsigned char dst[6];
    44. int len = strlen(buffer);
    45. cout << len << endl;
    46. convertStrToUnChar(buffer, dst);
    47.  
    48. int i = 0;
    49. for(i = 0; i < 6; i++)
    50. {
    51. printf("%x ", dst[i]);
    52. }
    53. cout << endl;
    54.  
    55.  
    56. return 0;
    57. }
posted @ 2021-01-05 11:07  Yalamo  阅读(145)  评论(0)    收藏  举报