//《C++程序设计题解与上机指导》chapter 6.12
#include<iostream>
using namespace std;
void sort(char *s[20]);
void main()
{ int i;
//p是数组独立开辟了内存空间
char a[10][20], *p[10];
//p不能指向a,p是一维数组,a是二维数组,而且p指向单元的类型是指向字符类型的指针类型,
//而a则是字符类型
cout<<"input 10 strings:"<<endl;
for(i=0; i < 10; i++)
{ cin>>a[i];
//这个地方是值拷贝,不是地址重新指向;对数组赋值,只能对每个元素逐一赋值
*(p + i) = a[i];
}
//p是数组独立开辟了内存空间,因此数组a的内容与p相互独立,a与p不是共享内存的关系
sort(p);
cout<<"Now, the sequence is:"<<endl;
//原先p[i]一一指向a[i],但是排序以后,p[i]指向的地址改变了,因此两者的输出结果不一样
cout<<"p"<<endl;
for(i=0; i < 10; i++)
cout<<p[i]<<" ";
cout<<endl;
cout<<"a"<<endl;
for(i=0; i < 10; i++)
cout<<a[i]<<" ";
cout<<endl;
}
void sort(char *s[20])
{ char temp[20], *pt = temp;
int i, j;
for(i=0; i < 9; i++)
for(j=0; j < 9 - i; j++)
//if(strcmp(s + j, s + j + 1)>0) 指针数组每个元素都是指针,指针只存放字符数组的首元素地址
//欲访问每个指针指向的数组,应该要加*,表示取值
if(strcmp(*(s + j), *(s + j + 1))>0)
{ strcpy(pt, *(s + j));
strcpy(*(s + j), *(s + j + 1));
strcpy(*(s + j + 1), pt);
}
/*
编译器总是要为函数的每个参数制作临时副本,数组作为参数,退化成为指针,指针参数s的副本是_s,编译器使 _s = s。如果函数体内的程序修改了_s的内容,就导致参数p的内容作相应的修改。这就是指针可以用作输出参数的原因。在本例中,_s申请了新的内存,只是把_s所指的内存地址改变了,但是s丝毫未变。
*/
//以下四行不能实现排序,因为以下改变的是指针数组p每个指针元素的指向
//而不是改变如上面的改变p每个指针元素的指向单元存储的内容
//必须强调,改变指针指向的地址和改变指针指向的单元内存储的值完全是两回事。
//改变指针变量的值(指针或者地址),只是改变指向关系,
//只有用符号*或者调用相关函数,才能改变对所指向单元的赋值
/**** { pt = *(s + j);
*(s + j) = *(s + j + 1);
*(s + j + 1) = pt;
} ****/
}
使用/**** ****/的内容实现不了对数组a的排序,原因是p为个指针数组,它里面的成员是指针,开始时 cin>>a[i];*(p + i) = a[i]; 这样p数组的每个元素指向字符数组的每个元素,与a[i]是一致的。sort(p);后,p数组的每个元素指向改变了,如原来p[0]指向的是a[0],现在p[0]可能指向的是a[9],p[0]只是改变了自己的指向,并没有改变a[0]的位置。没有sort(p)函数p[0]将第一个输出,有了sort(p);p[0]指向了p[9]将最后一个输出。