在C语言中使用指针时,必须考虑访问内存的长度,否则内存空间易出现各种错误,因此在实际操作时,要么设置结束标记(如读取文件的EOF,c字符串的'\0'等等),要么与长度信息配套使用(没想到其他方法555)。而且,两种操作方法是可以互相转化的。所以,这次作业要求实现一个简单(粗陋)的PString库,取消字符串的结束标记‘\0',并将字符串与长度信息捆绑为结构体,
现在要为PString定义各类字符串操作函数,PString结构体包含int length和char *content两个成员。
基本思路(偷工减料的思路doge):尽量使用string.h库中已有的可靠函数,所要做的只是两种字符串格式的转换,即记录长度、增减'\0'。虽然这样效果稳定,但效率低下,为了进一步学习字符串的操作和指针的使用,应该尝试自己重写字符串操作。
全部代码如下(较长):(由于c先声明后调用,需要引入.h头文件,头文件在此不表)
#include "pstring.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
//char[] 到PString
PString* psCreate(const char* s){
int len = strlen(s);
//still depends on free from user;
PString *ps = (PString *)malloc(sizeof(int)+len);
ps->length = len;
strncpy(ps->content,s,len);
return ps;
}
char * toString(PString *ps){
//still depends on free from user;
char *str = malloc(ps->length+1);
strncpy(str,ps->content,ps->length);
str[ps->length]='\0';
return str;
}
//PSting 到char[],只需要使用strncpy复制length个字符,再加'\0'即可
void psFree(PString *ps){
if(!ps) return;
free(ps);
return;
}
void psPrint(const PString* ps){
int q=0;
for(q=0;q<ps->length;q++){
printf("%c",(ps->content)[q]);
}
}
PString* psReadWord(){
//此处可以实现一个动态数组功能,即随着读入长度,分步增长内存长度
//char inp[9999];
scanf("%s",inp);
return psCreate(inp);
}
PString* psReadLine(){
//此处可以实现一个动态数组功能,即随着读入长度,分步增长内存长度
//char inp[9999],temp='\0';
while((temp=getchar()) == '\n' || temp == ' ');
if(temp) inp[0]=temp;
gets(inp+1);
return psCreate(inp);
}
int psLength(const PString* ps){
return ps->length;
}
PString* psClone(const PString *ps){
char *str=toString(ps);
//可以直接新建,不建议复用psCreate函数
PString*ret= psCreate(str);
free(str);
return ret;
}
PString* psConcat(const PString* ps1, const PString* ps2){
//对应strcat()
char *p=(char *) malloc(ps1->length+ps2->length+1),*start=p;
strncpy(p,ps1->content,ps1->length);
p+=ps1->length;
strncpy(p,ps2->content,ps2->length);
p+=ps2->length;
*p='\0';
PString* ret= psCreate(start);
free(start);
return ret;
}
int psCompare(const PString* ps1, const PString* ps2){
//对应strcmp
/*char *a=toString(ps1);
char *b=toString(ps2);
int ret = strcmp(a,b);
free(a);
free(b);
return ret;
*/
int len1=ps1->length;
int len2=ps2->length;
int q=strncmp((ps1->content),(ps2->content),(len1<len2?len1:len2));
if(q == 0){
if(len1 < len2) return -1;
if(len1 > len2) return 1;
return 0;
}else return q;
}
int psFindChar(const PString* ps, char ch){
//对应strchr函数
char *str = toString(ps);
char *find = strchr(str,ch);
int ret=-1;
if(find) ret=find-str;
free(str);
return ret;
/*
int q;
for(q=0;q<ps->length;q++){
if((ps->content)[q] == ch) return q;
}
return -1;
*/
}
int psFindString(const PString* ps1, const PString* ps2){
//对应string.h中的strstr函数
int q,w;
int startPoint=-1;
if(ps2->length == 0) return 0;
//使用strstr,增加空间开销,实际上不可取
char s1[ps1->length+1],s2[ps2->length];
strncmp(s1,ps1->content,ps1->length);
s1[ps1->length] = '\0';
strncmp(s2,ps2->content,ps2->length);
s2[ps2->length] = '\0';
char *find =strstr(s1,s2);
if(find == NULL) return -1;
return find-s1;
//不使用strstr
/*
for(q=0;q<ps1->length;q++){
if((ps1->content)[q] == (ps2->content)[0]){
startPoint=q;
for(w=0;w<ps2->length && w< ps1->length-q;w++){
if((ps1->content)[q+w] != (ps2->content)[w]){
startPoint=-1;
break;
}
}
}
if(startPoint!=-1) break;
}
*/
return startPoint;
}
PString* psTrim(const PString* ps){
//记录修剪的首尾位置,注意两端都要保留
int start=0,end=ps->length-1,q;
while(start<ps->length-1 &&((ps->content)[start] == ' '||(ps->content)[start] == '\n'\
||(ps->content)[start] == '\t')) start++;
while(end>=0 && ((ps->content)[end] == ' '|| (ps->content)[end] == '\n'\
||(ps->content)[end] == '\t')) end--;
PString * p=psSubstring(ps,start,end+1);
return p;
}
PString* psLower(const PString* ps){
//对应strlwr()
int q;
//函数复用
PString* ret = psClone(ps);
for(q=0;q<ret->length;q++){
if((ret->content)[q] >= 'A' && (ret->content)[q] <= 'Z'){
ret->content[q] +='a'-'A';
}
}
return ret;
}
PString* psUpper(const PString* ps){
//对应strupr
int q;
PString* ret = psClone(ps);
for(q=0;q<ret->length;q++){
if((ret->content)[q] >= 'a' && (ret->content)[q] <= 'z'){
ret->content[q] -='a'-'A';
}
}
return ret;
}
PString* psSubstring(const PString* ps, int begin, int end){
//可利用strncpy简单实现
if(end>=ps->length) end=ps->length;
if(begin>end) begin=end;
PString *p = (PString *) malloc(sizeof(int)+end-begin);
p->length = end-begin;
if(p->length <=0) return p;
strncpy(p->content,(ps->content)+begin,p->length);
return p;
}
PString* psReplace(const PString* ps, char ch1, char ch2){
PString *ret=psClone(ps);
int q;
for(q=0;q<ret->length;q++){
if((ret->content)[q] == ch1) (ret->content)[q] = ch2;
}
return ret;
}
char psChar(const PString* ps, int index){
//查找
if(index<0 || index>=ps->length) return '\0';
return (ps->content)[index];
}
int psBeginWith(const PString* ps1, const PString* ps2){
//函数复用,当然也可以自己再写
if(psFindString(ps1,ps2) == 0) return 1;
return 0;
}
部分函数提供两种方法,当然还有更多的方法,可以多写多练。
如有不足(肯定有大量不足)请指出。