线性表 顺序表 稀疏矩阵 字符串
DESCRIPTION
第二章 数组. 线性表 顺序表 稀疏矩阵 字符串. 一、线性表. 线性表 相同数据类型的元素的有限序列 叫线性表。 ( a 1 , a 2 , … ,a n-1 , a n ) a 1 为 首元 , a n 为 末元 , n 叫 线性表的 长度 a i 的 后继 是 a i+1 , i=1, …,n-1. a n 没有后继 。 a i 的 前驱 是 a i-1 , i=2, …,n. a 1 没有前驱 。 a i 可以是基本数据类型也可以是 struct 类型。 没有数据的线性表叫 空表 。空表的长度 n=0 。. - PowerPoint PPT PresentationTRANSCRIPT
线性表线性表顺序表 顺序表 稀疏矩阵稀疏矩阵字符串字符串
一、线性表线性表 相同数据类型的元素的有限序列 叫线性表。 ( a1, a2, … ,an-1, an )a1 为首元, an 为末元, n 叫线性表的长度 ai 的后继是 ai+1, i=1, …,n-1. an 没有后继。ai 的前驱是 ai-1, i=2, …,n. a1 没有前驱。ai 可以是基本数据类型也可以是 struct 类型。没有数据的线性表叫空表。空表的长度 n=0 。a1 a2 a3 a4 a5 a6
线性表是最简单的也是最基本的数据结构。
线性表可以用来构造字符串,集合,栈,队列,用来排序。
线性表可以顺序表示用一组地址连续的存储单元一次存储数据元素。
线性表也可以用线性链表表示。
二、顺序表——线性表的顺序表示
可以用通用数组定义通用线性表。
通用数组是可变长度的数组,也叫安全数组。
类模版 通用数据类型//array.h 例 . 通用数组 抽象数组类型 template <class T>
class Array
{ T *alist; // 指针数据 表示一个数组 int size; // 表示数组长度 public:
Array(int s=50) // 构造函数 Array(const Array<T>&X); // 拷贝构造函数 ~Array( ){delete[ ] element;} // 析构函数 Array<T>&operator=(const Array<T>&X);// 赋值函数重载 T& operator[ ](int i) ; // 一元运算 [ ] 重载 下标函数 operator T*( )const; // 强制类型转换 , 将当前 // 对象变成指向它的首地址的指针, int ArraySize( )const; // 取数组长 void Resize(int sz); // 数组长重定义 friend ostream& operator<<(ostream&, const Array<T>&);
// 输出操作重载 } ;
#include <array.h>
template<class T>class SeqList{ Array<T>listitem; //list storage array int size; public: SeqList(void); // constructor 构造函数 // list access methods 线性表的访问操作 int ListSize(void) const; // 取线性表的长 int ListEmpty(void)const; // 问表是否空表 int Find (T& item) const; // 查找一个元素 T GetData(int pos) const; // 取线性表中元素
// list modification methods 线性表的修改操作
void Insert(const T& item);// 表尾插入元素 void Insert(const T& item , int i); // 在第 i 个位插入一个新元素 void Delete(const T& item);// 删除一个元素 T DeleteFront(void); // 删除首元 void ClearList(void); // 清空};
// constructor. set size to 0
template<class T>SeqList<T>::SeqList(void): listite
m(size),size(0) { }
// return number of elements in list
template<class T>int SeqList<T>::ListSize(void) const{ return size;}
// tests for an empty list
template<class T>int SeqList<T>::ListEmpty(void) const{ return size == 0;}
// clears list by setting size to 0
template<class T>void SeqList<T>::ClearList(void){ size = 0;}
// Take item as key and search the list. //return True if item is in the list
and // false otherwise. If found, assign the list // element to the reference parameter item.
template<class T>int SeqList<T>::Find(T& item) const{ int i = 0; if (ListEmpty())return 0; // return False when list empty
while(i<size &&!(item==listitem[i])) i++; if (i < size) { item = listitem[i]; // assign list element to item return 1; // return True } else
return 0; // return false}
// insert item at the rear of the list.
template<class T>void SeqList<T>::Insert(const T& item){ // 如果超长,扩大内存
if (size+1 > listitem.ListSize( )) listitem.Resize(size+1); // index of rear is current value of //size. insert at rear listitem[size] = item; size++; // increment list size }
template<class T> // 在第 i 位插入
void SeqList<T>::Insert(const T& item, int i){ if (i<0)
{cout<<“’i’can not be negative!"; return;}
if(i>=size){Insert(item);return;} if (size+1 > listitem.ListSize( )) listitem.Resize(size+1); int k=size-1;
//shift the tail of the list //to the right one position
while (k >= i) { listitem[k+1] = listitem[k]; k--; } listitem[i] = item; size++; // increament list size}
//search for item in the list //and delete it if found
template<class T>void SeqList<T>::Delete(const T& item){ int i = 0; // search for item while (i < size && !(item == listitem[i])) i++; if (i < size) // successful if i < size {
// shift the tail of the list //to the left one position
while (i < size-1) { listitem[i] = listitem[i+1]; i++; } size--; // decreament size }}
//delete element at front of list and return // its value. terminate the
program with // an error message if the list is empty. template<class T> T SeqList<T>::DeleteFront(void) { T frontItem; // list is empty if size == 0 if (size == 0) { cerr << "Attempt to delete the front / of an empty list!" << endl; exit(1); }
frontItem = listitem[0]; // get value from position 0. Delete(frontItem); // delete the first item and shift terms
return frontItem; // return the original value
}
// return value at position pos in list. // if pos is not valid list position,// teminate program with an error message.template<class T>T SeqList<T>::GetData(int pos) const{ // terminate program if pos out of range if (pos < 0 || pos >= size) {cerr << "pos is out of range!" << endl; exit(1); } return listitem[pos];}
测试 #include “ iostream.h” #include “aseqlist.h”void main(void){ SeqList<int> a,b; int x; for(int i=0;i<20;i++) {a.Insert(i);
cout<<"input "<<i’s<<“ integer:"; cin>>x; b.Insert(x+1);} for(i=0;i<20;i++) cout<<a.GetData(i)<<' '; cout<<endl;
for(i=0;i<20;i++) cout<<b.GetData(i)<<' '; cout<<endl; a.Insert(99,0); a.Insert(98,10); a.Insert(97,20); a.Insert(96,30); int k=a.ListSize( ); for(i=0;i<k;i++) cout<<a.GetData(i)<<' '; cout<<endl;}
顺序表应用的例:
1. 用顺序表做插入 , 选择排序 .
2. 合并两个已排序的线性表 3. 用顺序表做集合 : 只插入不重复的元素 4. 求两个集合的交合并 5. 表示一个多项式 6. 求多项式的和差积商 , 微分 , 积分 7. 存储一个矩阵 , 求矩阵的和 , 积 , 逆
顺序线性表复杂度分析 1. 从已建立的顺序表中“取表长” ,“取第
i 个元素”的复杂性是 O(1),2. 在表长 n 的顺序表第 i 位前插入一个元素,
要把表尾 n-i+1 个元素后移一格。 假设每一位都插入一个数,从第 1 位到末
尾第 n+1 位,总移动次数是: Σi=1
i=n+1(n-i+1)=1+2+…+n=n*(n+1)/2
平均复杂度为 O(n/2).3. 删除第 i 位元素,要把表尾 n-i 个元素前移
一格。假设每一位都删除一个数,从第 1位到末尾第 n 位,总移动次数是:
Σi=1i=n+1(n-i)=1+2+…+(n-1)=n*(n-1)/2
平均复杂度为 O((n-1)/2).
一个阶数很高的矩阵中如果有许多相等的元素,或零元素,成为特殊矩阵。
对特殊矩阵可以进行压缩存储
三、稀疏矩阵
特殊矩阵
对称矩阵 上(下)三角矩阵 对角矩阵 稀疏矩阵
对称矩阵
矩阵 A=(aij)n,n
aij= aji , 0≤i,j≤n
每一对元素分配一个存储空间,可以 将 n2 个元素存储到 n(n+1)/2 个空间中
下三角矩阵 a11
a21a22
a31a32 a33
……
an1an2 an3 ……ann
1+2+3+ ……+n=n(n+1)/2T s[n(n+1)/2];
0 1 2 3 4 5 6 k
s a11 a21 a22 a31 a32 a33
k=i(i-1)/2+j-1; i≥j; k=j(j-1)/2+i-1; i<j.
s[12]=aij=aji; i=4, j=3
s[0]=a11; s[1]=a21; s[k]=ai
j
对角矩阵 a11 a12
a21 a22 a23
· · · · · ·
· · an-1n
ann-1 ann
a11 a12 a21 a22 a23 s[k]
s[k]=aij; k=3(i-1)+j; j=k%3; i=(k-j)/3
稀疏矩阵 Sparse Matrix
m*n 阶矩阵 A=(aij)mn 中有 t 个非零元素 , 如果 δ=t/(m*n)≤5%,
称 A 为稀疏矩阵 0 12 9 0 0 0 0
0 0 0 0 0 0 0
-3 0 0 0 0 14 0
0 0 24 0 0 0 0
0 18 0 0 0 0 0
15 0 0 -7 0 0 0
//smatrix.dat
6 7 8 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7
稀疏矩阵的存储
row col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7
template<class T>
class Triple
{ public:
int row, col;
T elem;
SetVal(int r,int c,T d)
{elem=d;row=r;col=c;}
};
稀疏矩阵元素的类 TRiple
稀疏矩阵类的定义#define MAXSIZE 500template<class T>class SparseMatrix{ Triple<T> data[MAXSIZE+1]; int mu, nu, tu; // 行数、列数、元素个数 public: SparseMatrix( ){mu=nu=tu=0;} SparseMatrix(char*filename); SparseMatrix<T> Transpose( ); SparseMatrix<T> Add(SparseMatrix<T> b); SparseMatrix<T> Muliply(SparseMatrix<T> b); void print( )const; };
template<class T>
SparseMatrix<T>::SparseMatrix(char *filename)
{ ifstream fin; int i,r,c; T d;
fin.open(filename, ios::in | ios::nocreate);
if (!fin){ cerr << "The maze data file " << filename
<< " cannot be opened!" << endl; exit(1); }
fin >> mu>>nu>>tu;
for (i = 1; i <= tu; i++)
{ fin >> r >> c>>d; data[i].SetVal(r,c,d);}
fin.close( );
};
矩阵的转置 T=M’
for(col=1;col<=nu;col++)
for(row=1;row<=mu;row++)
T[col][row]=M[row][col]
时间复杂度 O(mu*nu)
M
row col elem
1 2 12
1 3 9
3 1 –3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
M’
row col elem
2 1 12
3 1 9
1 3 –3
6 3 14
3 4 24
2 5 18
1 6 15
4 6 -7
M
row col elem
1 2 12
1 3 9
3 1 –3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
M’
row col elem
1 3 -3
1 6 15
2 1 12
2 5 18
3 1 9
3 4 24
4 6 -7
6 3 14
稀疏矩阵的转置 T=M’ 算法 5.1
template <class T> SparseMatrix<T> SparseMatrix<T> :: Transpose( )
{SparseMatrix<T> temp; int i, j, k=1; temp.mu=nu; temp.nu=mu; temp.tu=tu; if(tu){for(i=1;i<=nu;++i) for(j=1;j<=tu;++j) if(data[j].col==i) {temp.data[k].row=data[j].col; temp.data[k].col=data[j].row; temp.data[k].elem=data[j].elem; k++;} return temp;}
稀疏矩阵的转置的时间复杂度
O(nu*tu)
若 tu~nu*mu
O(nu*tu)=O(mu*nu*nu)
不是一个好算法!应当改进!
快速转置 依次逐个对号入座
Mrow col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7
M’row col elem
2 1 12
3 1 9
先求出 M 中每一列(即 M’ 中每一行)元素的个数 num[col] ,确定 M’ 每行起始位置 cpot[col] 。
快速转置Mrow col elem 1 2 12 1 3 9 3 1 –3 3 6 14 4 3 24 5 2 18 6 1 15 6 4 -7
col 1 2
3 4 5 6 7
num[col]
cpot[col]
1
2
3
2
5
2 7 1
8 0
8 1
9
row col elem
cpot[1]
cpot[2]
cpot[3]
cpot[4]
cpot[6]
2
1 12
3
1 9
1
3 9
6
3 14
快速转置算法 5.2
template <class T> SparseMatrix<T> SparseMatrix<T> ::Transpose( )
{SparseMatrix<T> temp; int i, j, k ; int*num=new int[nu+1]; int* cpot=new int[nu+1];
cpot[1]=1; temp.mu=nu; temp.nu=mu;temp.tu=tu; if(tu){for(i=1;i<=nu;++i)num[i]=0; for(i=1;i<=tu;++i)++num[data[i].col]; for(i=1;i<nu;++i)cpot[i+1]=cpot[i]+num[i]; for(i=1;i<=tu;++i){j=data[i].col;k=cpot[j]; temp.data[k].row=j; temp.data[k].col=data[i].row; temp.data[k].elem=data[i].elem; ++cpot[j];} } return temp;}
时间复杂性 O(nu+tu)
稀疏矩阵的加法template <class T> SparseMatrix<T> SparseMatrix<T>:: Add(SparseMatrix<T> b ){SparseMatrix<T> temp; if(mu!=b.mu||nu!=b.nu) {cerr<<“error ”<<end;return temp;} temp.mu=mu; temp.nu=nu; int i=1, j=1, k=1; while(i<=tu||j<=b.tu) {if((data[i].row<b.data[j].row) || (data[i].row==b.data[j].row) && (data[i].col<b.data[j].col)) {temp.data[k]=data[i]; k++;i++;}
else if((data[i].row==b.data[j].row)&&
(data[i].col==b.data[j].col))
{temp.data[k].row=data[i]. row;
temp.data[k].col=data[i].col;
temp.data[k].elem=data[i]. elem+ b.data[j]. elem
k++;i++;j++;}
else
{ temp.data[k]=b.data[j];k++;j++;}
temp.tu=k-1;
return temp;
}
矩阵的乘法 Amp*Bpn
(aij)*(bij)=(Σ1≤k≤paik*bkj)
2 0 0 -1
0 1 0 3
0 0 1 0
1 0 1 0 0 -1 0 0 0 2 0 1 3 0 1 0
a11*b11 a11*b12 a11*b13 a11*b14
a12*b21 a12*b22 a12*b23 a12*b24
a13*b31 a13*b32 a13*b33 a13*b34
a14*b41 a14*b42 a14*b43 a14*b44
时间复杂度 mpn
稀疏矩阵的乘法A
row col elem
1 2 12
1 3 9
3 1 –3
3 6 14
4 3 24
5 2 18
6 1 15
6 4 -7
B
row col elem rpos[row]
1 1 8 rpos[1]= 1
2 3 4 rpos[2]= 2
3 2 1 rpos[3]=3
3 5 -1
4 1 2 rpos[4]=5
4 4 -3
5 1 5 rpos[5]=7
6 2 -2 rpos[6]=8
template <class T> SparseMatrix<T> SparseMatrix<T>:: Multiply(SparseMatrix<T> b ){SparseMatrix<T> temp; if(nu!=b.mu) {cer<<“error ”<<end;return temp;}
temp.mu=mu;temp.nu=b.nu; int *num=new int[b.mu+1]; int *rpos=new int[b.mu+1]; rpos[1]=1; T ctemp[b.nu+1]; for(int i=1;i<=b.mu;i++) num[i]=0; for(i=1;i<=b.tu;i++)++num[b.data[i].row]; for(i=1;i<=b.mu;i++)rpos[i+1]=rpos[i]+num[i];
int k=1,j, r,c,t=0;
while(k<=tu)
{ for( j=1;j<=b.nu;j++) ctemp[j]=0;
r=data[k].row;
while(k<=tu&&data[k]=r)
{c=data[k].col;
for(i=rpos[c];i<rpos[c+1];i++;)
{j=b.data[i].col; ctemp[j]=ctemp[j]+data[k].elem*b.data[i].elem;}
k++;}
for(j=1;j<=b.nu;j++)
if(ctemp[j]!=0)
{t++; temp.data[t].row=r;
temp.data[t].col=j;
temp.data[t].elem=ctemp[j];}
}
temp.tu=t;
return temp;
}
稀疏矩阵乘法的时间复杂度
O(tu.*b.nu)
稀疏矩阵的输出template <class T>void SparseMatrix<T> :: print( )const{int i, j,k=1; for(i=1;i<=mu;i++) {for(j=1;j<=nu;j++) if ((i=data[k].row)&&(j=data[k].col)) {cout<<setw(4)<<data[k].elem; k++;} else cout<<setw(4)<<0; cout<<endl; }}
串串 --- 由字符组成的线性表,也叫 字符串串是非数值计算算法处理的主要对象在模式匹配,程序编译,数据处理等领域有广泛的应用
串类型的定义 串类型的实现 串的模式匹配
C 语言中有关串的函数#include <string.h>
strlen(char *s);
strcpy(char *s, char *t);
strcmp(char*s, char *t);
strcat(char *s, char *t);
strchr(char*s, char c);
strrchr(char*s, char c);
没有插入,删除不好记,不好用
串类型的定义
1 。用数组定义串 #define MAXSTRLEN 255
typedef unsigned SString[MAXSTRLEN+1];
Sstring s1, s2;
// 用 s1[0], s2[0] 存储各自的长度
2 。堆分配存储表示
typedef struct{
char *ch;
int length;
}HString;
HString s;
s.length=15;
s.ch=new char[s.length];
3. 块链存储 #define CHUNKSIZE 80typedef struct Chunk{ char ch[CHUNKSIZE]; Chunk *next; } ;typedef struct{ Chunk *head,*tail; int curlen; }LString; // 定长字符串作元素的线性链表
堆分配存储串类的实现 //“strclass.h”
#define STRING_CLASS
#include <iostream.h>
#include <string.h>
#include <stdlib.h>
#ifndef NULL
const int NULL = 0;
#endif // NULL
const int outOfMemory = 0, indexError = 1;
#ifndef STRING_CLASS
class String
{ char *str;
int size;
void Error(int errorType, int badIndex = 0) const;
public:
String(char *s = “ ” );
String(const String& s);
~String(void);
String& operator= (const String& s);
String& operator= (char *s);
int operator== (const String& s) const;
int operator== (char *s) const;
friend int operator== (char *str, const String& s);
int operator!= (const String& s) const;
int operator!= (char *s) const;
friend int operator!= (char *str, const String& s);
int operator< (const String& s) const;
int operator< (char *s) const;
friend int operator< (char *str, const String& s);
int operator<= (const String& s) const;
int operator<= (char *s) const;
friend int operator<= (char *str, const String& s);
int operator> (const String& s) const;
int operator> (char *s) const;
friend int operator> (char *str, const String& s);
int operator>= (const String& s) const;
int operator>= (char *s) const;
friend int operator>= (char *str, const String& s);
String operator+ (const String& s) const;
String operator+ (char *s) const;
friend String operator+ (char *str,const String& s);
void operator+= (const String& s);
void operator+= (char *s);
// String functions
int Find(char c, int start) const;
int FindLast(char c) const;
String Substr(int index, int count) const;
void Insert(const String& s, int index);
void Insert(char *s, int index);
void Remove(int index, int count);
char& operator[] (int n);
operator char* (void) const;
// String I/O
friend ostream& operator<< (ostream& ostr,
const String& s);
friend istream& operator>> (istream& istr,
String& s);
int ReadString(istream& is=cin,
char delimiter='\n');
int Length(void) const;
int IsEmpty(void) const;
void Clear(void);
};
void String::Error(int errorType, int badIndex) const
{ if (errorType == outOfMemory) cerr << "Memory exhausted!" << endl; else cerr << "Index " << badIndex << " out of range" << endl; exit(1);}
// constructor. allocate memory and copy in a C++String
String::String(char *s){ size = strlen(s) + 1; str = new char [size]; // terminate program if memory is exhausted.
if (str == NULL) Error(outOfMemory); strcpy(str,s);}
// copy constructor
String::String(const String& s){ // current object as length of s
size = s.size; // allocate same amount of space as s uses. copy string
str = new char [size]; if (str == NULL) Error(outOfMemory); strcpy(str, s.str);}
// destructor
String::~String(void)
{
delete [] str;
}
// assignment operator. String to String
String& String::operator= (const String& s)
{ if (s.size != size)
{ delete [] str;
str = new char [s.size];
if(str == NULL) Error(outOfMemory); // assign size to be size of s
size = s.size; } // copy s.str and return reference to current object
strcpy(str, s.str);
return *this;
}
// assignment operator. C++String to String
String& String::operator= (char *s){ int slen = strlen(s) + 1; // if sizes differ, delete current string and reallocate
if (slen != size) { delete [] str; str = new char [slen]; if (str == NULL) Error(outOfMemory); size = slen; } strcpy(str, s); return *this;}
// all relational operators use C++ string function strcmp
// String == String
int String::operator== (const String& s) const
{
return strcmp(str,s.str) == 0;
}
// String == C++String
int String::operator== (char *s) const
{
return strcmp(str,s) == 0;
}
// C++String == String. this is a friend function, since
// the left operand is a C++String.
int operator== (char *str, const String& s)
{
return strcmp(str,s.str) == 0;
}
// String != String
int String::operator!= (const String& s) const
{
return strcmp(str,s.str) != 0;
}
// String != C++String
int String::operator!= (char *s) const
{
return strcmp(str,s) != 0;
}
// C++String != String
int operator!= (char *str, const String& s)
{
return strcmp(str,s.str) != 0;
}
// String < String
int String::operator< (const String& s) const
{
return strcmp(str,s.str) < 0;
}
// String < C++String
int String::operator< (char *s) const
{
return strcmp(str,s) < 0;
}
// C++String < String
int operator< (char *str, const String& s)
{
return strcmp(str,s.str) < 0;
}
// String <= String
int String::operator<= (const String& s) const
{
return strcmp(str,s.str) <= 0;
}
// String <= C++String
int String::operator<= (char *s) const
{
return strcmp(str,s) <= 0;
}
// C++String <= String
int operator<= (char *str, const String& s)
{
return strcmp(str,s.str) <= 0;
}
// String > String
int String::operator> (const String& s) const
{
return strcmp(str,s.str) > 0;
}
// String > C++String
int String::operator> (char *s) const
{
return strcmp(str,s) > 0;
}
// C++String > String
int operator> (char *str, const String& s)
{
return strcmp(str,s.str) > 0;
}
// String >= String
int String::operator>= (const String& s) const
{
return strcmp(str,s.str) >= 0;
}
// String >= C++String
int String::operator>= (char *s) const
{
return strcmp(str,s) >= 0;
}
// C++String >= String
int operator>= (char *str, const String& s)
{
return strcmp(str,s.str) >= 0;
}
// concatention: String + String
String String::operator+ (const String& s) const{ String temp; int len; delete [] temp.str; len = size + s.size - 1; temp.str = new char [len]; if (temp.str == NULL)Error(outOfMemory); temp.size = len; strcpy(temp.str,str); // copy str to temp strcat(temp.str, s.str); // concatenate s.str return temp; // return temp}
// concatention: String + C++String. same algorithm as// String + String, with a C++String as the right operand
String String::operator+ (char *s) const{String temp; int len; delete [] temp.str; len = size + strlen(s); temp.str = new char [len]; if (temp.str == NULL) Error(outOfMemory); temp.size = len; strcpy(temp.str,str); strcat(temp.str, s); return temp;}
// concatention: C++String + String. same algorithm as
// String + String, with a C++String as the left operand
String operator+ (char *cs, const String& s){ String temp; int len; delete [] temp.str; len = strlen(cs) + s.size; temp.str = new char [len]; if (temp.str == NULL) s.Error(outOfMemory); temp.size = len; strcpy(temp.str, cs); strcat(temp.str, s.str); return temp;}
// concatenate and assign: String += String
// the current object is modified
void String::operator+= (const String& s){ char *tempstr; int len; len = size + s.size - 1; tempstr = new char [len]; if (tempstr == NULL) Error(outOfMemory); strcpy(tempstr,str); strcat(tempstr, s.str); delete [] str; str = tempstr; size = len;}
void String::operator+= (char *s)
{ int len; char *tempstr; len = size + strlen(s); tempstr = new char [len]; if (tempstr == NULL) Error(outOfMemory); strcpy(tempstr,str); strcat(tempstr, s); delete [] str; str = tempstr; size = len;}
int String::Find(char c, int start) const
{ int ret; char *p; p = strchr(&str[start], c); if (p != NULL) ret = int(p-str); else ret = -1; return ret;}
// return index of last occurrence of c in string
int String::FindLast(char c) const{ int ret; char *p; // use C++ library function strrchr. returns pointer to
// the last occurrence of a character in the string
p = strrchr(str, c); if (p != NULL) ret = int(p-str); // compute index else ret = -1; // return -1 on failure return ret;}
{ int charsLeft = size-index-1, i; String temp; char *p, *q; if (index >= size-1) return temp; if (count > charsLeft) count = charsLeft; delete [] temp.str; temp.str = new char [count+1]; if (temp.str == NULL) Error(outOfMemory); for(i=0,p=temp.str,q=&str[index];i < count;i++) *p++ = *q++; *p = 0; temp.size = count+1; return temp;}
String String::Substr(int index, int count) const
void String::Insert(const String& s, int index){ int newsize, length_s = s.size-1, i; char *newstr, *p, *q; newsize = size + length_s; newstr = new char [newsize]; if (newstr == NULL)Error(outOfMemory);
for(i=0,p = newstr, q = str; i <= index-1;i++) *p++ = *q++; strcpy(p,s.str); p += length_s; strcpy(p,&str[index]); delete [] str; size = newsize; str = newstr;}
void String::Insert(char *s, int index)
{ int newsize, length_s = strlen(s), i; char *newstr, *p, *q; newsize = size + length_s; newstr = new char [newsize]; if (newstr == NULL) Error(outOfMemory); for(i=0,p = newstr, q = str;i <= index-1;i++) *p++ = *q++; strcpy(p,s); p += length_s; strcpy(p,&str[inde
x]); delete [] str; size = newsize; str = newstr; }
void String::Remove(int index, int count){ int charsLeft = size-index-1, newsize, i; char *newstr, *p, *q; if (index >= size-1) return; if (count > charsLeft) count = charsLeft; newsize = size - count; newstr = new char [newsize]; if (newstr == NULL)Error(outOfMemory);
for(i=0,p=newstr,q=str;i <= index-1;i++) *p++ = *q++; q += count; strcpy(p,q); delete [] str; size = newsize; str = newstr;}
// String index operator
char& String::operator[] (int n)
{
if (n <0 || n >= size-1)
Error(indexError,n);
return str[n];
}
// pointer conversion operator
String::operator char* (void) const
{
return str;
}
istream& operator>> (istream& istr, String& s)
{char tmp[256]; if (istr >> tmp) { delete [] s.str; // delete existing string s.size = strlen(tmp) + 1; s.str = new char [s.size]; if (s.str == NULL) s.Error(outOfMemory); strcpy(s.str,tmp); } return istr;}
ostream& operator<< (ostream& ostr, const String& s)
{
ostr << s.str;
return ostr;
}
// read characters from istr
int String::ReadString (istream& istr, char delimiter)
{ char tmp[256]; if (istr.getline(tmp, 256, delimiter)) { delete [] str; size = strlen(tmp) + 1; str = new char [size]; if (str == NULL)Error(outOfMemory);
strcpy(str,tmp); return size-1; } else return -1; // return -1 on end of file}
int String::Length(void) const
{
return size-1;
}
int String::IsEmpty(void) const
{
return size == 1;
}
void String::Clear(void)
{ delete [] str; size = 1; str = new char [size]; if (str == NULL) Error(outOfMemory); str[0] = 0;}
#endif // STRING_CLASS
测试
#include <iostream.h>
#pragma hdrstop
#include "strclass.h"
#define TF(b) ((b) ? "TRUE" : "FALSE")
void main(void)
{ String s1("STRING "), s2("CLASS"), s3;
int i; char c, cstr[30];
s3 = s1 + s2;
cout << s1 << "concatenated with " << s2
<< " = " << s3 << endl;
cout << "Length of " << s2 << " = “
<< s2.Length( ) << endl;
cout << "The first occurrence of 'S' in " << s2
<< " = " << s2.Find('S',0) << endl;
cout << "The last occurrence of 'S' in " << s2
<< " is " << s2.FindLast('S') << endl;
cout << “Insert 'OBJECT ' into s3 at position 7.” << endl; s3.Insert("OBJECT ", 7); cout << s3 << endl; s1 = "FILE1.S"; for(i=0;i < s1.Length( );i++) { c = s1[i]; if (c >= 'A' && c <= 'Z') { c += 32; // convert c to lower case s1[i] = c; } } cout << "The string 'FILE1.S' converted to lower \ case is "; cout << s1 << endl;
cout << "Test relational operators with strings "; cout << "s1 = 'ABCDE' s2 = 'BCF'" << endl; s1 = "ABCDE"; s2 = "BCF"; cout << "s1 < s2 is " << TF(s1 < s2) << endl; cout << "s1 == s2 is " << TF(s1 == s2) << endl; cout << "Use 'operator char* ( )' to get s1" << " as a C++ string: "; strcpy(cstr, s1); cout << cstr << endl;}
/*<Run of Program >STRING concatenated with CLASS = STRING
CLASSLength of CLASS = 5The first occurrence of 'S' in CLASS = 3The last occurrence of 'S' in CLASS is 4Insert 'OBJECT ' into s3 at position 7.STRING OBJECT CLASSThe string 'FILE1.S' converted to lower case is
file1.sTest relational operators with strings s1 = 'ABCDE' s2 = 'BCF's1 < s2 is TRUEs1 == s2 is FALSEUse 'operator char* ( )' to get s1 as a C++ string:
ABCDE*/