第四章:指针与字符串
字符串就是字符序列。它存储的是字节数组。一个特殊字符串结束符是用来标记字符串的结束。结束符用转义序列‘\0’表示。
定义字符串变量的方法
char *strptr = "Hello";
char strarray1[] ="Hello";
char strarray2[6] ="Hello";
char strarray3[4]= { 'a ', 'b ', 'c', 'd'};
printf("%s\n",strptr);//Hello
printf("%s\n",strarray1);//Hello
printf("%c\n",strarray2[4]);//o
printf("%c\n",strarray2[5]);//空白
仔细研究一下下面的结果吧
char strarray2[6] ="Hello1";
printf("%c\n",strarray2[4]);//o
printf("%c\n",strarray2[5]);//l
printf("%c\n",strarray2[6]);//H
printf("%c\n",strarray2[7]);//e
4.1内存中的字符串排列
通常情况下,字符串或者字符数组存储在连续的内存单元中
访问字符串元素
数组索引和指针运算都可以用来访问字符串元素
char*str="Hello pointer";
for(int i=0;i<strlen(str);i++)
{
printf("%c ",str[i]);
}
return 0;
}
在上述代码中,利用数组索引访问字符串中的字符。函数strlen(char*)用来返回字符串的长度。返回的长度不包括所有字符串中必有的最后一个空字符。
下面的代码使用临时字符指针变量char* ptr遍历整个字符串。该实例演示如何使用指针访问字符串的每个字符。
char*str="YOU ARE A DOG";
char*pointer=str;
while(*pointer!='\0')
{
printf("%c ",*pointer) ;
pointer++;
}
printf("%d",sizeof(str));//4,说明str就是一个指针变量
4.2 动态分配内存
注意:数组中分配内存给媳妇序列存储字符串时需要一个额外的空字符标记字符串的结尾
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <malloc.h>
int main(int argc,char* argv[])
{
char* src = "Hello Pointer";
char* dst= NULL;
dst =( char*)malloc(sizeof(char)* (strlen(src) + 1));
memcpy(dst,src,strlen(src));
for(int i=0;i<strlen(src);i++)
{
printf("%c ",dst[i]);
}
return 0;
}
字符串文本和常量
定义字符串时编译器自动在字符串结尾增加转义字符‘\0’。某些文献中字符串常量也叫作字符串文本。最有趣的事是从RO扇区分配内存给字符串常量。RO扇区是存储字符串文本和常量的只读数据区。存储在该区域的数据的生命周期为程序运行的整个生命周期,这也是存储在该区域的数据变量的生命期。
#include <stdio.h>
char* foo(void);
int main(int argc,char* argv[]){
char *m = foo();
printf("Printing local value of function foo = %s\n",m);
return 0;
}
char* foo(void){
char* str = "STRING";return str;
}
该程序始终打印“STRING”。虽然变量的 char * str为函数foo()的局部变量,但它在所有范围内均能被访问。如前所述,变量char* str是一个字符串文本或常量,它的内存是从RO扇区分配的,所以在程序运行的整个生命周期中都有效。
自然常量化为字符串文本的另一个重要特性。一旦字符串文本被初始化其值就不能在后面的阶段修改。字符串文本相当于const char*变量名,其中指针可被修改,但所指的值不能修改。
#include <stdio.h>
int main()
{
char *strliteral = "ADD" ;
printf("%c",strliteral[0]);
strliteral[0]= 'B';//修改第0个索引的值,不允许,//程序会产生分段错误
printf("%c",strliteral[0]);
strliteral++ ;//Allowed
return 0;
}
4.3 字符串操作
- scanf()函数中的“%s”是将输入字符串存储到变量的格式。
- 遍历字符串变量的每个索引是进行读数据或操作数据的最基本过程
- 字符串复制是将字符串变量所指向的某个内存位置的存储数据复制到另一个内存单元所指向的内存位置的操作。
4.4 字符串数组
字符串数组的元素是指向字符数组或字符串数组的指针。数组存储的每个字符串可以是不同长度。
字符串数组的声明
char str[6][7];
第五章 指针与多维数组
5.1数组排列
5.1.1 二维数组指针
对于二维数组
定义:intarr[][]
arr表示第一个元素的地址,也是第0行的起始地址
arr[0]+1;表示第一行第二个元素的地址
#include <iostream>
using namespace std;
int main()
{
int arr[5][5];
for (int i=0;i<5;i++){
for (int j=0;j<5;j++)
{
arr[i][j]=i*i+j*j;
}
}
cout <<"数组元素" << endl;
for (int i=0;i<5;i++){
for (int j=0;j<5;j++)
{
cout<<arr[i][j]<<"\t";
}
cout<<endl;
}
cout <<"数组首地址" <<arr << endl;
for(int i=0;i<5;i++)
{
cout<<"*******i="<<i<<"*******"<<endl;
cout << "arr+i\t"<<arr+i << endl;
cout << "arr[i]\t" <<arr[i] << endl;
cout << "*arr[i]\t" <<*arr[i] << endl;
cout << "&arr[i]\t" <<&arr[i] << endl;
cout<<endl;
for(int j=0;j<5;j++)
{
cout<<"*******i="<<i<<"*******"<<"j="<<j<<"\t"<<"arr[i]+j:\t"<<arr[i]+j<<"\t*(arr[i]+j)\t"<<*(arr[i]+j)<<endl;
// cout<<"*******i="<<i<<"*******"<<"j="<<j<<"\t"<<"*arr[i]+j\t"<<*arr[i]+j<<endl;
//cout<<arr[i]+j<<endl;
}
}
cout<< endl;
cout <<"数组指针访问数组" << endl;
int (*ptr)[5];//不能用 int*ptr[5]
// int*ptr[5];
ptr=arr;
for(int i=0;i<5;i++)
{ cout<<"*******i="<<i<<"*******"<<endl;
for(int j=0;j<5;j++)
{
cout<<"*******i="<<i<<"*******"<<"j="<<j<<"\t"<<"*ptr+j:\t"<<*ptr+j<<"\t*(*ptr+j)\t"<<*(*ptr+j)<<endl;
}
cout<<*ptr++<<endl;
}
return 0;
}
数组元素
0 1 4 9 16
1 2 5 10 17
4 5 8 13 20
9 10 13 18 25
16 17 20 25 32
数组首地址0x6dfe58
*******i=0*******
arr+i 0x6dfe58
arr[i] 0x6dfe58
*arr[i] 0
&arr[i] 0x6dfe58
*******i=0*******j=0 arr[i]+j: 0x6dfe58 *(arr[i]+j) 0
*******i=0*******j=1 arr[i]+j: 0x6dfe5c *(arr[i]+j) 1
*******i=0*******j=2 arr[i]+j: 0x6dfe60 *(arr[i]+j) 4
*******i=0*******j=3 arr[i]+j: 0x6dfe64 *(arr[i]+j) 9
*******i=0*******j=4 arr[i]+j: 0x6dfe68 *(arr[i]+j) 16
*******i=1*******
arr+i 0x6dfe6c
arr[i] 0x6dfe6c
*arr[i] 1
&arr[i] 0x6dfe6c
*******i=1*******j=0 arr[i]+j: 0x6dfe6c *(arr[i]+j) 1
*******i=1*******j=1 arr[i]+j: 0x6dfe70 *(arr[i]+j) 2
*******i=1*******j=2 arr[i]+j: 0x6dfe74 *(arr[i]+j) 5
*******i=1*******j=3 arr[i]+j: 0x6dfe78 *(arr[i]+j) 10
*******i=1*******j=4 arr[i]+j: 0x6dfe7c *(arr[i]+j) 17
*******i=2*******
arr+i 0x6dfe80
arr[i] 0x6dfe80
*arr[i] 4
&arr[i] 0x6dfe80
*******i=2*******j=0 arr[i]+j: 0x6dfe80 *(arr[i]+j) 4
*******i=2*******j=1 arr[i]+j: 0x6dfe84 *(arr[i]+j) 5
*******i=2*******j=2 arr[i]+j: 0x6dfe88 *(arr[i]+j) 8
*******i=2*******j=3 arr[i]+j: 0x6dfe8c *(arr[i]+j) 13
*******i=2*******j=4 arr[i]+j: 0x6dfe90 *(arr[i]+j) 20
*******i=3*******
arr+i 0x6dfe94
arr[i] 0x6dfe94
*arr[i] 9
&arr[i] 0x6dfe94
*******i=3*******j=0 arr[i]+j: 0x6dfe94 *(arr[i]+j) 9
*******i=3*******j=1 arr[i]+j: 0x6dfe98 *(arr[i]+j) 10
*******i=3*******j=2 arr[i]+j: 0x6dfe9c *(arr[i]+j) 13
*******i=3*******j=3 arr[i]+j: 0x6dfea0 *(arr[i]+j) 18
*******i=3*******j=4 arr[i]+j: 0x6dfea4 *(arr[i]+j) 25
*******i=4*******
arr+i 0x6dfea8
arr[i] 0x6dfea8
*arr[i] 16
&arr[i] 0x6dfea8
*******i=4*******j=0 arr[i]+j: 0x6dfea8 *(arr[i]+j) 16
*******i=4*******j=1 arr[i]+j: 0x6dfeac *(arr[i]+j) 17
*******i=4*******j=2 arr[i]+j: 0x6dfeb0 *(arr[i]+j) 20
*******i=4*******j=3 arr[i]+j: 0x6dfeb4 *(arr[i]+j) 25
*******i=4*******j=4 arr[i]+j: 0x6dfeb8 *(arr[i]+j) 32
指针数组访问数组
*******i=0*******
*******i=0*******j=0 *ptr+j: 0x6dfe58 *(*ptr+j) 0
*******i=0*******j=1 *ptr+j: 0x6dfe5c *(*ptr+j) 1
*******i=0*******j=2 *ptr+j: 0x6dfe60 *(*ptr+j) 4
*******i=0*******j=3 *ptr+j: 0x6dfe64 *(*ptr+j) 9
*******i=0*******j=4 *ptr+j: 0x6dfe68 *(*ptr+j) 16
0x6dfe58
*******i=1*******
*******i=1*******j=0 *ptr+j: 0x6dfe6c *(*ptr+j) 1
*******i=1*******j=1 *ptr+j: 0x6dfe70 *(*ptr+j) 2
*******i=1*******j=2 *ptr+j: 0x6dfe74 *(*ptr+j) 5
*******i=1*******j=3 *ptr+j: 0x6dfe78 *(*ptr+j) 10
*******i=1*******j=4 *ptr+j: 0x6dfe7c *(*ptr+j) 17
0x6dfe6c
*******i=2*******
*******i=2*******j=0 *ptr+j: 0x6dfe80 *(*ptr+j) 4
*******i=2*******j=1 *ptr+j: 0x6dfe84 *(*ptr+j) 5
*******i=2*******j=2 *ptr+j: 0x6dfe88 *(*ptr+j) 8
*******i=2*******j=3 *ptr+j: 0x6dfe8c *(*ptr+j) 13
*******i=2*******j=4 *ptr+j: 0x6dfe90 *(*ptr+j) 20
0x6dfe80
*******i=3*******
*******i=3*******j=0 *ptr+j: 0x6dfe94 *(*ptr+j) 9
*******i=3*******j=1 *ptr+j: 0x6dfe98 *(*ptr+j) 10
*******i=3*******j=2 *ptr+j: 0x6dfe9c *(*ptr+j) 13
*******i=3*******j=3 *ptr+j: 0x6dfea0 *(*ptr+j) 18
*******i=3*******j=4 *ptr+j: 0x6dfea4 *(*ptr+j) 25
0x6dfe94
*******i=4*******
*******i=4*******j=0 *ptr+j: 0x6dfea8 *(*ptr+j) 16
*******i=4*******j=1 *ptr+j: 0x6dfeac *(*ptr+j) 17
*******i=4*******j=2 *ptr+j: 0x6dfeb0 *(*ptr+j) 20
*******i=4*******j=3 *ptr+j: 0x6dfeb4 *(*ptr+j) 25
*******i=4*******j=4 *ptr+j: 0x6dfeb8 *(*ptr+j) 32
0x6dfea8
通过指针变量访问二维数组的索引
int (*ptr_1)[5];
int *dataptr;
ptr_1=arr;
for(int i=0;i<5;i++)
{ cout<<"*******i="<<i<<"*******"<<endl;
dataptr=(*ptr_1+i*5);
for(int j=0;j<5;j++)
{
cout<<"*******i="<<i<<"*******"<<"j="<<j<<"\t"<<"dataptr:\t"<<dataptr<<"\t(*dataptr)\t"<<*(dataptr)<<endl;
dataptr++;
}
}
*******i=0*******
*******i=0*******j=0 dataptr: 0x6dfe4c (*dataptr) 0
*******i=0*******j=1 dataptr: 0x6dfe50 (*dataptr) 1
*******i=0*******j=2 dataptr: 0x6dfe54 (*dataptr) 4
*******i=0*******j=3 dataptr: 0x6dfe58 (*dataptr) 9
*******i=0*******j=4 dataptr: 0x6dfe5c (*dataptr) 16
*******i=1*******
*******i=1*******j=0 dataptr: 0x6dfe60 (*dataptr) 1
*******i=1*******j=1 dataptr: 0x6dfe64 (*dataptr) 2
*******i=1*******j=2 dataptr: 0x6dfe68 (*dataptr) 5
*******i=1*******j=3 dataptr: 0x6dfe6c (*dataptr) 10
*******i=1*******j=4 dataptr: 0x6dfe70 (*dataptr) 17
*******i=2*******
*******i=2*******j=0 dataptr: 0x6dfe74 (*dataptr) 4
*******i=2*******j=1 dataptr: 0x6dfe78 (*dataptr) 5
*******i=2*******j=2 dataptr: 0x6dfe7c (*dataptr) 8
*******i=2*******j=3 dataptr: 0x6dfe80 (*dataptr) 13
*******i=2*******j=4 dataptr: 0x6dfe84 (*dataptr) 20
*******i=3*******
*******i=3*******j=0 dataptr: 0x6dfe88 (*dataptr) 9
*******i=3*******j=1 dataptr: 0x6dfe8c (*dataptr) 10
*******i=3*******j=2 dataptr: 0x6dfe90 (*dataptr) 13
*******i=3*******j=3 dataptr: 0x6dfe94 (*dataptr) 18
*******i=3*******j=4 dataptr: 0x6dfe98 (*dataptr) 25
*******i=4*******
*******i=4*******j=0 dataptr: 0x6dfe9c (*dataptr) 16
*******i=4*******j=1 dataptr: 0x6dfea0 (*dataptr) 17
*******i=4*******j=2 dataptr: 0x6dfea4 (*dataptr) 20
*******i=4*******j=3 dataptr: 0x6dfea8 (*dataptr) 25
*******i=4*******j=4 dataptr: 0x6dfeac (*dataptr) 32
5.1.2 三维数组
二维数组可以看作一维数组的叠加,三维数组可以看作二维数组的叠加