#include
#include
#include
#include
#define SUCCESS 1 // 定义操作成功的标志为SUCCESS
#define FAILURE 0 // 定义操作失败的标志为FAILURE
typedef struct _String // 定义链串结构
{
char character ; // 组成串的字符( 数据域 )
struct _String* next ; // 指向下一串结构的指针( 链域 )
} String ; // 串类型
typedef struct _StringInformation // 定义串信息结构
{
String* str ; // 链串首结点
int letters_count ; // 字母个数
int figures_count ; // 数字个数
int space_count ; // 空格个数
int endline_count ; // 换行符个数
int others_count ; // 其他字符个数
int characters_count ; // 总字符个数
} StringInformation ; // 串信息类型
typedef struct _Index // 定义串索引结构
{
int sub_index ; // 子串在其父串的位置( 或索引 )
struct _Index* next_index ; // 指向子串的下一个串索引结构的指针
} Index ; // 串索引类型
// 字符串操作基本函数及其他相关辅助函数 :
int StringToUnsignedInt( char* s , int max ) ; // 字符串转换成无符号整数
void InitalizeStringInformation( StringInformation* SI , int initalizeAll ) ;// 串信息初始化
void CreatStringFromArray( String** S , char* cString ) ; // 从字符数组建立字符串
int CreatStringFromFile( String** S , char* filePath ) ; // 从文件建立字符串
int StringLength( String* S ) ; // 求串长
int StringCompare( String* S1 , String* S2 ) ; // 串比较
void StringCopy( String** targetString , String* sourceString ) ; // 串拷贝
void SubString( String* S , int index , int subLength , String** subS ) ; // 子串提取
int SubStringIndex( String* S , String* subS ) ; // 求子串在父串首次出现的位置
int StringInsert( String** S , int index , String* insertedString ) ; // 串插入
int SubStringDelete( String** S , int index , int subLength ) ; // 子串删除
void PrintString( String* S ) ; // 串输出
void PrintIndex( Index* subIndex ) ; // 子串的所有索引输出
void PrintStringInformation( StringInformation* SI ) ; // 串组成信息输出
void SaveToFile( String* S , char* filePath ) ; // 保存字符串到文件
void DestroyString( String** S ) ;
// 串销毁
void DestroyIndex( Index** subIndex ) ; // 子串索引销毁
// 字符串处理扩展函数 :
int SubStringIndexAll( String* S , String* subS , Index** subIndex ) ;// 查找子串所有索引
// 广义字符串替换:第一个函数替换特定子串 , 第二个函数替换所有子串 , 替换串为NULL时 , 视为删除
int SubStringReplaceSingle( String** S , int index , String* subS , String* replaceSubS ) ;
int SubStringReplaceAll( String** S , String* subS , String* replaceSubS ) ;
int main( )
{
StringInformation S , Source ;
String* newString = NULL , * replaceString = NULL , * subString , * tempString ;
Index* subIndex ;
char input[ 200 ] , cString[ 200 ] , filePath[ 200 ] = "" , anotherPath[ 200 ] = "" ;
int position , choice , succeed , subLength , count ;
InitalizeStringInformation( &S , 1 ) ;
InitalizeStringInformation( &Source , 1 ) ;
system( "color 1E" ) ;
do
{
system( "cls" ) ;
printf( "Designed by Wind Fantasy\n" ) ;
printf( "\n\t*-*-*-*-*-*-*-*-*-*-*-*-< 菜单 >-*-*-*-*-*-*-*-*-*-*-*-*\n" ) ;
printf( "\t*%55c\n" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "01.读取(文本)文件建立新字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "02.查看源(文本)文件内容和组成信息 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "03.查看当前字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "04.查看当前字符串的组成信息 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "05.查找指定位置开始的指定长度字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "06.查找指定的字符串的位置 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "07.在当前字符串指定的位置插入字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "08.从当前字符串中删除指定的子字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "09.替换当前字符串指定的子字符串 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "10.保存对(文本)文件的修改 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "11.另存为(文本)文件 ;" , '*' ) ;
printf( "\t%-9c%-38s%9c\n" , '*' , "00.退出程序 ." , '*' ) ;
printf( "\t*%55c\n" , '*' ) ;
printf( "\t*-*-*-*-*-*-*-*-*-*-*-*-*-*--*-*-*-*-*-*-*-*-*-*-*-*-*-*\n" ) ;
printf( "\n请输入一个自然数并按 \"Enter\" 键以执行相应操作 : " ) ;
gets( input ) ;
choice = StringToUnsignedInt( input , 11 ) ;
switch( choice )
{
case 1:
if( S.str != NULL )
{
printf( "已从文件中建立过字符串,是否要重新建立以替
换原有字符串?\n" ) ;
printf( "\"是\"请输入y , \"否\"请输入其它字符串或不输入 : " ) ;
gets( input ) ;
if( ( input[ 0 ] != 'y' && input[ 0 ] != 'Y' ) || input[ 1 ] != '\0' )
{
printf( "已取消重新建立字符串!\n" ) ;
break ;
}
}
tempString = S.str ;
printf( "请输入源(文本)文件的绝对路径( 如D:\\Test\\test.txt ) :\n" ) ;
gets( filePath ) ;
succeed = CreatStringFromFile( &S.str , filePath ) ;
if( succeed == SUCCESS )
{
DestroyString( &tempString ) ;
printf( "已成功读取(文本)文件并建立字符串!\n" ) ;
}
break ;
case 2:
succeed = CreatStringFromFile( &Source.str , filePath ) ;
if( succeed == SUCCESS )
{
system( "cls" ) ;
printf( "源(文本)文件\"%s\"的内容( 不含最后9行 )如下:\n" , filePath ) ;
PrintString( Source.str ) ;
PrintStringInformation( &Source ) ;
DestroyString( &Source.str ) ;
}
break ;
case 3:
system( "cls" ) ;
printf( "当前字符串( 不含最后一行 )如下 :\n" ) ;
PrintString( S.str ) ;
break ;
case 4:
PrintStringInformation( &S ) ;
break ;
case 5:
printf( "请输入子字符串的起始位置 : " ) ;
gets( input ) ;
position = StringToUnsignedInt( input , -1 ) ;
if( position == -1 )
{
printf( "对不起 , 请你输入合法的位置 !\n" ) ;
break ;
}
printf( "请输入子字符串的长度 : " ) ;
gets( input ) ;
subLength = StringToUnsignedInt( input , -1 ) ;
if( subLength == -1 )
{
printf( "对不起 , 请你输入合法的字符串长度 !\n" ) ;
break ;
}
SubString( S.str , position , subLength , &subString ) ;
if( subString == NULL )
printf( "对不起 , 无法输出子字符串 , 请你输入合适的数据 !\n" ) ;
else
{
printf( "你查找的子字符串如下( 不包含最后一行 ) :\n" ) ;
PrintString( subString ) ;
DestroyString( &subString ) ;
}
break ;
case 6:
printf( "请输入将查找的子字符串 :\n" ) ;
gets( cString
) ;
CreatStringFromArray( &subString , cString ) ;
count = SubStringIndexAll( S.str , subString , &subIndex ) ;
if( count == FAILURE )
printf( "对不起 , 没有找到该字符串 !\n" ) ;
else
if( count == 1 )
printf( "该字符串在当前字符串中的位置是: %d .\n" , subIndex ->sub_index ) ;
else
{
printf( "系统查找到该字符串在父串中的所有出现位置如下 :\n" ) ;
PrintIndex( subIndex ) ;
}
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
case 7:
printf( "请输入将插入字符串的位置 : " ) ;
gets( input ) ;
position = StringToUnsignedInt( input , -1 ) ;
if( position == -1 )
{
printf( "对不起 , 请输入合法的位置 !\n" ) ;
break ;
}
printf( "请输入将插入的字符串 : " ) ;
gets( cString ) ;
CreatStringFromArray( &newString , cString ) ;
succeed = StringInsert( &S.str , position , newString ) ;
if( succeed == SUCCESS )
printf( "已成功插入字符串 \"%s\" !\n" , cString ) ;
else
{
printf( "对不起 , 未能成功插入字符串 \"%s\" , 请你输入合适的数据 !\n"
, cString ) ;
DestroyString( &newString ) ;
}
break ;
case 8:
printf( "请输入将删除的子字符串 :\n" ) ;
gets( cString ) ;
CreatStringFromArray( &subString , cString ) ;
count = SubStringIndexAll( S.str , subString , &subIndex ) ;
if( count == FAILURE )
{
printf( "对不起 , 没有找到该字符串 , 无法执行删除!\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
if( count == 1 )
{
SubStringReplaceSingle( &S.str , subIndex ->sub_index , subString , NULL ) ;
printf( "已成功删除子字符串 \"%s\" !\n" , cString ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
printf( "系统查找到该字符串在当前字符串中的所有出现位置如下 :\n" ) ;
PrintIndex( subIndex ) ;
printf( "\n请你输入将删除的子字符串的位置(输入0删除所有的子字符串) : " ) ;
gets( input ) ;
position = StringToUnsignedInt( input , -1 ) ;
if( position == -1 )
{
printf( "对不起 , 请输入合法的删除位置 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
if( position == 0 )
{
SubStringReplaceAll( &S.str , subString , NULL ) ;
printf( "已成功删除所有的子字符串 \"%s\" !\n" , cString ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
succeed = SubStringReplaceSingle( &S.str , position , subString , NULL ) ;
if( succeed == SUCCESS )
printf( "已成功删除子字符串 \"%s\" !\n" , cString ) ;
else
printf( "对不起 , 未能成功删除子字符串 , 请输入合适的删除位置 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
case 9:
printf( "请输入将被替换的子字符串 :\n" ) ;
gets( cString ) ;
CreatStringFromArray( &subString , cString ) ;
count = SubStringIndexAll( S.str , subString , &subIndex ) ;
if( count == FAILURE )
{
printf( "对不起 , 没有找到该字符串 , 无法执行替换!\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
if( count == 1 )
{
position = subIndex ->sub_index ;
printf( "请输入一个字符串以替换上面的字符串 :\n" ) ;
gets( cString ) ;
CreatStringFromArray( &replaceString , cString ) ;
SubStringReplaceSingle( &S.str , position , subString , replaceString ) ;
printf( "已成功替换子字符串 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
printf( "系统查找到该字符串在父串中的所有出现位置如下 :\n" ) ;
PrintIndex( subIndex ) ;
printf( "\n请你输入将替换的子字符串的位置(输入0替换所有的子字符串) : " ) ;
gets( input ) ;
position = StringToUnsignedInt( input , -1 ) ;
if( position == -1 )
{
printf( "对不起 , 请输入合法的删除位置 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
printf( "请输
入一个字符串以替换上面的字符串(不输入则取消本次替换操作) :\n" ) ;
gets( cString ) ;
if( *cString == '\0' )
{
printf( "已取消本次替换操作 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
CreatStringFromArray( &replaceString , cString ) ;
if( position == 0 )
{
SubStringReplaceAll( &S.str , subString , replaceString ) ;
printf( "已成功替换所有的子字符串 !\n" ) ;
DestroyString( &replaceString ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
}
succeed = SubStringReplaceSingle( &S.str , position , subString , replaceString ) ;
if( succeed == SUCCESS ) // ****
printf( "已成功替换子字符串 !\n" ) ;
else
printf( "对不起 , 你输入的位置不合法 , 未能成功替换子字符串 !\n" ) ;
DestroyIndex( &subIndex ) ;
DestroyString( &subString ) ;
break ;
case 10:
SaveToFile( S.str , filePath ) ;
break ;
case 11:
printf( "请输入将另存为的文件的绝对路径 :\n" ) ;
gets( anotherPath ) ;
SaveToFile( S.str , anotherPath ) ;
break ;
case 0:
DestroyString( &S.str ) ;
printf( "谢谢你的使用 , 欢迎再次使用 , 再见 !\n" ) ;
printf( "请按任意键退出程序. . ." ) ;
getch( ) ;
return 0 ;
default:
printf( "对不起 , 输入错误 , 请重新输入 !\n" ) ;
}
printf( "\n请按任意键返回 \"菜单\" . " ) ;
getch( ) ;
} while( choice != 0 ) ;
return 0 ;
}
int StringLength( String* S ) // 求串长
{
int length = 0 ;
while( S != NULL ) // ( S == NULL ) 即表示为 S 为空串
{
length ++ ;
S = S ->next ;
}
return length ;
}
void StringCopy( String** targetString , String* sourceString ) // 串拷贝
{
String* newNode , * tailNode ;
if( sourceString == NULL )
*targetString = NULL ; // 空串则直接赋值为NULL
else // 非空串则需另开辟内存空间
{
*targetString = ( String* )malloc( sizeof( String ) ) ; // 建立串首结点
( *targetString ) ->character = sourceString ->character ;
tailNode = *targetStrin
g ;
sourceString = sourceString ->next ; // 源串移至其第二个字符
while( sourceString != NULL )
{
newNode = ( String* )malloc( sizeof( String ) ) ; // 新建结点
newNode ->character = sourceString ->character ; // 子字符复制
tailNode ->next = newNode ; // 新建结点插入到尾结点后
tailNode = newNode ; // 新建结点成为尾结点
sourceString = sourceString ->next ; // 继续复制源串的下一个字符
}
tailNode ->next = NULL ; // 尾结点的链域为空( NULL )
}
}
int StringCompare( String* S1 , String* S2 ) // 字符串比较 , 相等返回0
{
while( S1 != NULL && S2 != NULL )
if( S1 ->character > S2 ->character )
return 1 ;
else
if( S1 ->character < S2 ->character )
return -1 ;
else
if( S1 ->character == S2 ->character ) // 若相等则继续比较下一字符
{
S1 = S1 ->next ;
S2 = S2 ->next ;
}
if( S1 != NULL && S2 == NULL ) // 父串比子串大 , 返回1
return 1 ;
else
if( S1 == NULL && S2 != NULL )
return -1 ;
return 0 ;
}
void CreatStringFromArray( String** S , char* cString ) // 通过字符数组建立串
{
String* newNode , * tailNode ;
if( *cString == '\0' )
*S = NULL ; // 字符数组为空串时,则*S = NULL
else
{
*S = ( String* )malloc( sizeof( String ) ) ;
( *S ) ->character = *cString ;
tailNode = *S ;
cString ++ ;
while( *cString )
{
newNode = ( String* )malloc( sizeof( String ) ) ;
newNode ->character = *cString ;
tailNode ->next = newNode ;
tailNode = newNode ;
cString ++ ;
}
tailNode ->next = NULL ; // 尾结点的链域为空
}
}
void DestroyString( String** S ) // 串销毁
{
String* traverseNode = *S , * preNode ;
while( traverseNode != NULL )
{
preNode = traverseNode ; // 记录当前结点
traverseNode = traverseNode ->next ; // 记录下一个要删除的结点
free( preNode ) ; // 删除当前结点并释放( 回收 )其所占的内存空间
}
*S = NULL ; // 销毁串*S且成为空串
}
void DestroyIndex( Index
** subIndex ) // 子串索引销毁
{
Index* traverseNode = *subIndex , * preNode ;
while( traverseNode != NULL )
{
preNode = traverseNode ;
traverseNode = traverseNode ->next_index ;
free( preNode ) ;
}
*subIndex = NULL ;
}
void InitalizeStringInformation( StringInformation* SI , int initalizeAll ) // 串信息初始化
{
if( initalizeAll != 0 )
SI ->str = NULL ; // 如果初始化全部信息,则初始化为空串
SI ->letters_count = 0 ; // 字母个数为0
SI ->figures_count = 0 ; // 数字个数为0
SI ->space_count = 0 ; // 空格个数为0
SI ->endline_count = 0 ; // 换行符个数为0
SI ->others_count = 0 ; // 其他字符个数为0
SI ->characters_count = 0 ; // 总字符个数为0
}
int CreatStringFromFile( String** S , char* filePath ) // 通过读取文本文件建立串
{
FILE* fp ; // 文件指针
String* newNode , * tailNode ;
int ch ;
if( *filePath == '\0' || ( fp = fopen( filePath , "r" ) ) == NULL )
{
printf( "对不起 , 无法打开(文本)文件 \"%s\" !\n" , filePath ) ;
return FAILURE ; // 打开指定文件失败返回0
}
else // 打开指定文件成功
{
ch = fgetc( fp ) ; // 获取文件的第一个字符
if( ch == EOF ) // EOF 文件结束标志
*S = NULL ; // 如果是空文件则为空串
else
{
*S = ( String* )malloc( sizeof( String ) ) ;
( *S ) ->character = ch ;
tailNode = *S ;
ch = fgetc( fp ) ;
while( ch != EOF ) // 读取字符直至文件指针移至文件尾
{
newNode = ( String* )malloc( sizeof( String ) ) ;
newNode ->character = ch ;
tailNode ->next = newNode ;
tailNode = newNode ;
ch = fgetc( fp ) ; // 读取下一个字符
}
tailNode ->next = NULL ;
}
fclose( fp ) ; // 关闭文件
return SUCCESS ;
}
}
int StringInsert( String** S , int index , String* insertedString ) // 串插入
{ // 在串*S的第index位置上插入串insertedString
int S_length = StringLength( *S ) , i ;
String* S_targetNode = *S
, * insertedString_tailNode = insertedString ;
if( index <= S_length + 1 && index >= 1 && insertedString != NULL )
// 合法的串插入位置
if( index != 1 ) // 不在串的第一位置插入
{
for( i = 1 ; i < index - 1 ; i ++ )
S_targetNode = S_targetNode ->next ; // 查找插入串实际位置的前一结点
while( insertedString_tailNode ->next != NULL ) // 查找串insertedString的尾结点
insertedString_tailNode = insertedString_tailNode ->next ;
insertedString_tailNode ->next = S_targetNode ->next ;
// insertedString的尾结点的下一结点为目标结点S_targetNode的下一结点
S_targetNode ->next = insertedString ;
// 将串insertedString插入到目标结点S_targetNode之后
}
else //在串的第一位置插入
{
while( insertedString_tailNode ->next != NULL ) // 查找串insertedString的尾结点
insertedString_tailNode = insertedString_tailNode ->next ;
insertedString_tailNode ->next = *S ; // 将insertedString插入到*S之前
*S = insertedString ; // insertedString成为串首结点
}
else
return FAILURE ;
return SUCCESS ;
}
int SubStringDelete( String** S , int index , int subLength )// 子串删除
{ // 删除串*S自index位置开始的subLength个子字符
int i , Length = StringLength( *S ) ;
String* targetNode = *S , * traverseNode , * preNode ;
if( index - 1 + subLength - 1 < Length && index > 0 && subLength > 0 )
// 合法的子串删除位置
if( index != 1 ) // 不是从第一位置删除子串
{
for( i = 1 ; i < index - 1 ; i ++ ) // 查找删除子串实际位置( index )的前一结点
targetNode = targetNode ->next ;
traverseNode = targetNode ->next ; // traverse记录第index个结点
for( i = 1 ; i <= subLength ; i ++ )// 删除串*S自index开始的subLength个字符
{
preNode = traverseNode ;
traverseNode = traverseNode ->next ;
free( preNode ) ; // 释放( 回收 )删除的结点所占的内存空间
}
targetNode ->next = traverseNode ; // 目标结点targetNode下一结点为traverseNode
}
else // 从第一位置删除子串
{
traverseNode = targetNode ;
for( i = 1 ; i <= subLength ; i ++ )// 删除串*S的前subLength个字符
{
preNode = traverseNode ;
traverseNode = traverseNode ->next ;
free( preNode ) ;
}
*S = traverseNode ;
// traverseNode为删除的最后一个结点的下一结点 , 且成为删除子串后的串首结点
}
else
return FAILURE ;
return SUCCESS ;
}
void SubString( String* S , int index , int subLength , String** subS) // 子串提取
{ // 提取串*S自index位置开始的subLength个子字符组成的子串subS
int Length = StringLength( S ) , i ;
String* newNode , * tailNode ;
if( index - 1 + subLength - 1 < Length && index > 0 && subLength > 0 )
{ // 合法的子串位置
for( i = 1 ; i < index ; i ++ ) // 查找子串位置的结点
S = S ->next ;
*subS = ( String* )malloc( sizeof( String ) ) ; // 建立子串首结点
( *subS ) ->character = S ->character ; // 复制首字符
tailNode = *subS ;
S = S ->next ;
for( i = 1 ; i < subLength ; i ++ ) // 复制余下的( subLength - 1 )个字符
{
newNode = ( String* )malloc( sizeof( String ) ) ;
newNode ->character = S ->character ;
tailNode ->next = newNode ;
tailNode = newNode ;
S = S ->next ;
}
tailNode ->next = NULL ;
}
else
*subS = NULL ;
}
int SubStringIndex( String* S , String* subS ) // 求子串subS在父串S首次出现的位置
{
int S_length = StringLength( S ) , subS_length = StringLength( subS ) , index = 1 ;
String* S_traverse , * subS_traverse ;
if( subS != NULL && S != NULL && subS_length <= S_length ) // 合法的子串
while( S != NULL )
{
S_traverse = S ; // 确定串匹配的起点
subS_traverse = subS ; // 初始化subS_traverse
while( S_traverse != NULL && subS_traverse != NULL )
if( S_traverse ->character == subS_traverse ->character )
{
S_traverse = S_traverse ->next ;
subS_traverse = subS_traverse ->next ; // 若字符相等则继续比较
}
else // 否则进入下一趟匹配
break ;
if( subS_traverse == NULL ) // subS是S的子串
return index ; // 返回子串subS的位置
S = S ->next ; // 进入下一趟匹配
index ++ ;
// 子串位置自增1
}
return FAILURE ; // 未找到或有非法数据则返回0
}
void PrintString( String* S ) // 串输出
{
while( S != NULL )
{
printf( "%c" , S ->character ) ; // 输出串的各个字符
S = S ->next ;
}
}
void PrintIndex( Index* subIndex ) // 子串所有索引输出
{
while( subIndex != NULL )
{
printf( "%4d " , subIndex ->sub_index ) ;
subIndex = subIndex ->next_index ;
}
}
int SubStringReplaceSingle( String** S , int index , String* subS , String* replaceSubS )
{ // 替换特定位置的子串
int subLength ;
String* realSubS ;
if( subS == NULL ) // 非法的子串
return FAILURE ; // 替换失败
subLength = StringLength( subS ) ;
SubString( *S , index , subLength , &realSubS ) ; // 提取实际参考串realSubS
if( StringCompare( subS , realSubS ) == 0 ) // 判断subS是否是*S的index位置的子串
{
SubStringDelete( S , index , subLength ) ;
StringInsert( S , index , replaceSubS ) ; // 若是则替换
DestroyString( &realSubS ) ; // 销毁实际参考串realSubS
return SUCCESS ; // 替换成功
}
else
{
DestroyString( &realSubS ) ;
return FAILURE ; // 替换失败
}
}
int SubStringReplaceAll( String** S , String* subS , String* replaceSubS )
{
int index , subLength , replaceLength , position ;
String* replaceSubS_Copy , * tailNode ;
position = index = SubStringIndex( *S , subS ) ; // 查找subS在串*S首次出现的位置
subLength = StringLength( subS ) ; // 计算子串subS的长度
if( index == 0 ) // 未找到子字符串则返回0
return FAILURE ;
if( replaceSubS == NULL ) // 若替换成空串则认为删除所有子串
{
while( index != 0 )
{
tailNode = *S ;
for( index = 1 ; index <= position + subLength - 1 ; index ++ )
tailNode = tailNode ->next ; // tailNode移至下一遍历首结点
SubStringDelete( S , position , subLength ) ; // 删除子字符串
index = SubStringIndex( tailNode , subS ) ; // 查找相对位置index
position += index - 1 ; // 计算下次删除的子串的实际位置
}
return SUCC
ESS ; // 替换成功则返回1
}
replaceLength = StringLength( replaceSubS ) ; // 计算替换串的长度
while( index != 0 ) // 当还查找的到子串时
{
StringCopy( &replaceSubS_Copy , replaceSubS ) ; // 串拷贝
tailNode = replaceSubS_Copy ;
while( tailNode ->next != NULL ) // 查找新建串的尾结点
tailNode = tailNode ->next ;
SubStringDelete( S , position , subLength ) ; // 删除*S的子串subS
StringInsert( S , position , replaceSubS_Copy ) ; // 插入替换串replaceSubS_Copy
index = SubStringIndex( tailNode ->next , subS ) ; // 自tailNode ->next开始查找子串
// subS相对tailNode ->next位置
position += replaceLength - 1 + index ; // 计算下次删除的子串的实际位置
}
return SUCCESS ;
}
void SaveToFile( String* S , char* filePath ) // 文件保存
{
FILE* fp ;
int ch ;
if( ( fp = fopen( filePath , "w" ) ) == NULL ) // 非法的文件路径或无空间存储
printf( "对不起 , 无法建立文件 !\n" ) ;
else // 文件重写或创建成功
{
while( S != NULL )
{
ch = S ->character ;
fputc( ch , fp ) ; // 写入当前字符
S = S ->next ; // 下一个字符将被写入
}
fclose( fp ) ; // 关闭文件
printf( "成功保存到文件 \"%s\" !\n" , filePath ) ;
}
}
void PrintStringInformation( StringInformation* SI ) // 字符串信息统计与输出
{
String* traverseNode = SI ->str ;
char ch ;
InitalizeStringInformation( SI , 0 ) ;
while( traverseNode != NULL )
{
ch = traverseNode ->character ;
if( ch <= '9' && ch >= '0' )
SI ->figures_count ++ ;
else
if( ( ch <= 'z' && ch >= 'a' ) || ( ch <= 'Z' && ch >= 'A' ) )
SI ->letters_count ++ ;
else
if( ch == ' ' )
SI ->space_count ++ ;
else
if( ch == '\n' )
SI ->endline_count ++ ;
else
SI ->others_count ++ ;
SI ->characters_count ++ ;
traverseNode = traverseNode ->next ;
}
printf( "\n字符串组成信息如下 :\n" ) ;
printf( "字母字符总数是 : %-5d ;\n" , SI ->letters_count ) ;
printf( "数字字
符总数是 : %-5d ;\n" , SI ->figures_count ) ;
printf( "空格字符总数是 : %-5d ;\n" , SI ->space_count ) ;
printf( "换行字符总数是 : %-5d ;\n" , SI ->endline_count ) ;
printf( "其他字符总数是 : %-5d ;\n" , SI ->others_count ) ;
printf( "所有字符总数是 : %-5d .\n" , SI ->characters_count ) ;
}
int StringToUnsignedInt( char* s , int max ) // 字符串转换成自然数
// s指定要转换的字符串 , max指定转换成的自然数的上限 , 特别地当max < 0时取消上限
{
int resault = 0 ;
if( *s == '\0' ) // 空串直接返回-1
return -1 ;
while( *s <= '9' && *s >= '0' ) // 将有效的数字字符转换成自然数
{
resault = resault * 10 + ( *s - '0' ) ;
s ++ ;
}
return ( *s == '\0' && ( max < 0 || resault <= max ) ) ? resault : -1 ;
// ******** Notice: here is " *s == '\0' " , not " *s = '\0'
// 当字符串是由纯数字组成( *s == '\0' )时,不约定上限( max < 0 )时或结果不大于上限
// ( resault <= max )时则直接返回结果( resault ) , 否则返回-1表示非法输入
}
int SubStringIndexAll( String* S , String* subS , Index** subIndex )// 查找子串的所有索引
{ // 返回子串出现的次数
int index , position = 0 , count = 0 ;
Index* newNode , * tailNode ;
index = SubStringIndex( S , subS ) ;
if( index == 0 ) // 未查找到串subS
{
*subIndex = NULL ;
return FAILURE ; // 返回FAILURE , 子串出现次数为0
}
*subIndex = ( Index* )malloc( sizeof( Index ) ) ; // 分配内存空间以存储子串所有索引
( *subIndex ) ->sub_index = index ; // 记录第一个索引
tailNode = *subIndex ;
position ++ ; // position指定下次遍历的位置
count ++ ; // 出现次数自增1
S = S ->next ; // S移至下次串遍历的起点
while( S != NULL ) // 子串出现次数不止一次
{
index = SubStringIndex( S , subS ) ; // 继续以下一个字符为起点进行查找
if( index != 0 && tailNode ->sub_index != index + position )
{ // 找到子串并且索引与上一个不相等时
newNode = ( Index* )malloc( sizeof( Index ) ) ;
newNode ->sub_index = index + position ; // 计算索引在串S中的实际位置
tailNode ->next_index = newNode ;
// 添加新的索引
tailNode = newNode ; // 新的索引成为尾结点
count ++ ; // 出现次数自增1
}
position ++ ; // 准备从下一个字符进行查找
S = S ->next ; // S移至下次串遍历的起点
}
tailNode ->next_index = NULL ;
return count ; // 返回子串出现次数
}