struct strbuf {int len; //當(dāng)前緩沖區(qū)(字符串)長度
int alloc; //當(dāng)前緩沖區(qū)(字符串)容量
char *buf; //緩沖區(qū)(字符串)
};
HINT:
//初始化 sb 結(jié)構(gòu)體,容量為 alloc。
void strbuf_init(struct strbuf *sb, size_t alloc)//數(shù)據(jù)類型解釋見下
{sb->len=0;
sb->alloc=alloc;
sb->buf=(char *)malloc(sizeof(char)*alloc);//強(qiáng)制類型轉(zhuǎn)換(void*--char*)
strcpy(sb->buf,"");
}
//將字符串填充到 sb 中,長度為 len, 容量為 alloc。
void strbuf_attach(struct strbuf *sb, void *str, size_t len, size_t alloc)
{sb->buf=(char*)str;//強(qiáng)制類型轉(zhuǎn)換(void*--char*)
sb->len=len;
sb->alloc=alloc;
}
//釋放 sb 結(jié)構(gòu)體的內(nèi)存。
void strbuf_release(struct strbuf *sb)
{free(sb->buf);//參數(shù)是malloc()返回的地址,當(dāng)時(shí)用buf存該地址
sb->buf=NULL;//把指針設(shè)為NULL
sb->len=0;
sb->alloc=0;
}
//交換兩個(gè) strbuf。
void strbuf_swap(struct strbuf *a, struct strbuf *b)
{struct strbuf t;
法一:
t=*a;
*a=*b;
*b=t;
法二:
t.len=a->len;
t.alloc=a->alloc;
t.buf=a->buf;
a->len=b->len;
a->alloc=b->alloc;
a->buf=b->buf;
b->len=t.len;
b->alloc=t.alloc;
b->buf=t.buf;
}
//將 sb 中的原始內(nèi)存取出,并將 sz 設(shè)置為其 alloc 大小 。
char *strbuf_detach(struct strbuf *sb, size_t *sz)
{*sz=sb->alloc;//sz=&(sb->alloc)編譯錯(cuò)誤
//因?yàn)閏annot convert ‘int*’ to ‘size_t*’ {aka ‘long unsigned int*’} in assignment
return sb->buf;//注意函數(shù)的返回類型
}
//比較兩個(gè) strbuf 的內(nèi)存是否相同。
int strbuf_cmp(const struct strbuf *first, const struct strbuf *second)
{// int tag=1;錯(cuò)
// if(first->len!=second->len)tag=0;
// if(first->alloc!=second->alloc)tag=0;
// if(strcmp(first->buf,second->buf)!=0)tag=0;
// return tag;//相同‘1’,不同‘0’
if(first->len>second->len)
return 1;
if(first->lenlen)
return -1;
else
return 0;
}
//清空 sb 。
void strbuf_reset(struct strbuf *sb)//清空指的是讓內(nèi)存沒有東西,而非釋放(128G內(nèi)存恢復(fù)出場設(shè)置)
{// sb->len=0;錯(cuò)
// sb->alloc=0;
// free(sb->buf);
// sb->buf=NULL;
法一:
int i;
for(i=0;ilen;i++){sb->buf[i]='\0';
}
sb->len=0;
// sb->alloc=0 因?yàn)閍lloc是申請到的內(nèi)存大小,所以不能令為零(否則恢復(fù)出場設(shè)置后128G空間都沒了)
法二:
memset(sb->buf,0,sb->len);//函數(shù)解釋見下
sb->len=0;
}
size_t
無符號整數(shù),32位下為unsigned int,64位下為unsigned long
在數(shù)組下標(biāo)和內(nèi)存管理函數(shù)之類的地方廣泛使用
memset
void *memset(void *s, int c, size_t n);
- s指向要填充的內(nèi)存塊。
c是要被設(shè)置的值。
n是要被設(shè)置該值的字符數(shù)。
返回類型是一個(gè)指向存儲區(qū)s的指針。
//確保在 len 之后 strbuf 中至少有 extra 個(gè)字節(jié)的空閑空間可用。
//(128G總內(nèi)存空間在已用100G后,確保至少有30G空閑空間可以用)->如果不夠,再申請一塊內(nèi)存(再買內(nèi)存卡)
void strbuf_grow(struct strbuf *sb, size_t extra)
{if(sb->alloc-sb->len< extra){sb->buf=(char*)realloc(sb->buf,sb->alloc+extra);//默認(rèn)buf之前申請過一塊內(nèi)存,返回值為剛申請到的內(nèi)存首地址
sb->alloc += extra; //函數(shù)解釋見下
}
}
//向 sb 追加長度為 len 的數(shù)據(jù) data 。
void strbuf_add(struct strbuf *sb, const void *data, size_t len)
{// if(sb->len+len<= sb->alloc){ //錯(cuò)
// sb->buf=strcat(sb->buf,(const char*)data);//(要不要強(qiáng)制類型轉(zhuǎn)換為char*?)要!
// }
// else {// strbuf_grow(sb,sb->alloc);//再來一倍
// sb->buf=strcat(sb->buf,(const char*)data);
// }
// sb->len+=len;
法一:
if(sb->len+len >= sb->alloc)
{sb->buf=(char*)realloc(sb->buf,sb->len+len+1);//包括\0
sb->alloc=sb->len+len+1;//更新擴(kuò)容后的內(nèi)存大小256G
}
法二:
strbuf_grow(sb->buf,len+1);
memcpy(sb->buf+sb->len,data,len);//函數(shù)解釋見下
sb->len+=len;
// sb->buf+sb->len='\0'; //錯(cuò)
//*(sb->buf+sb->len)='\0'; //ok!
sb->buf[sb->len]='\0';
}
//向 sb 追加一個(gè)字符 c。
void strbuf_addch(struct strbuf *sb, int c)
{// char a[1];
// a[0]=c;
// if(sb->len+1<= sb->alloc)
// sb->buf=strcat(sb->buf,a);
// else {// strbuf_grow(sb,sb->alloc);
// sb->buf=strcat(sb->buf,a);
// }
// sb->len+=1;
法一:
if(sb->len+1 >= sb->alloc){sb->buf=(char*)realloc(sb->buf,(sb->alloc)*2);//內(nèi)存翻兩倍
sb->alloc=sb->alloc*2;
}
memcpy(sb->buf+sb->len,&c,1);
sb->len+=1;
sb->buf[sb->len]='\0';
法二:
strbuf_add(sb,&c,1);
}
//向 sb 追加一個(gè)字符串 s。
void strbuf_addstr(struct strbuf *sb, const char *s)
{法一:
int n=strlen(s);
if(sb->len+n >= sb->alloc){sb->buf=(char*)realloc(sb->buf,sb->len+n+1);
sb->alloc=sb->len+n+1;
}
memcpy(sb->buf+sb->len,s,n);
// sb->buf=strcat(sb->buf,s); 錯(cuò)->解釋見下
sb->len+=n;
sb->buf[sb->len]='\0';
法二:
strbuf_add(sb,s,strlen(s));
}
//向一個(gè) sb 追加另一個(gè) strbuf 的數(shù)據(jù)。
void strbuf_addbuf(struct strbuf *sb, const struct strbuf *sb2)//追加一個(gè)結(jié)構(gòu)體
{法一:
if(sb->len+sb2->len >= sb->alloc){sb->buf=(char*)realloc(sb->buf,sb->len+sb2->len+1);
sb->alloc=sb->len+sb2->len+1;
}
sb->buf=strcat(sb->buf,sb2->buf);
sb->len+=sb2->len;
法二:
strbuf_addstr(sb,sb2->buf);
}
//設(shè)置 sb 的長度 len。
void strbuf_setlen(struct strbuf *sb, size_t len)
{if(len >= sb->alloc)//(要安裝應(yīng)用,先判斷是否裝的下)
{sb->buf=(char*)realloc(sb->buf,len+1);
sb->alloc=len+1;
}
sb->len=len;
sb->buf[sb->len]='\0';
}
//計(jì)算 sb 目前仍可以向后追加的字符串長度。
size_t strbuf_avail(const struct strbuf *sb)
{return (sb->alloc-(sb->len+1));//末尾的\0
}
//向 sb 內(nèi)存坐標(biāo)為 pos 位置插入長度為 len 的數(shù)據(jù) data 。
void strbuf_insert(struct strbuf *sb, size_t pos, const void *data, size_t len)
{if(sb->len+len >sb->alloc){strbuf_grow(sb,len+1);
}
// int i;錯(cuò)
// char a[len];
// strcpy(a,(const char*)data);
// for(i=0;i// sb->buf[pos+i]=a[i]; //默認(rèn)原來位置沒有數(shù)據(jù)->不行
// }
memmove(sb->buf+pos+len,sb->buf+pos,sb->len-pos);//把pos位置后面的數(shù)據(jù)移到pos+len的地方,空出來的len長度來存放data,函數(shù)解釋見下
memcpy(sb->buf+pos,data,len);//sb->buf[pos]錯(cuò)
sb->len+=len;
sb->buf[sb->len]='\0';
}
realloc
void* realloc(void* memblock, size_t size)
- memblock: 先前開辟的內(nèi)存塊的指針(也就是malloc或calloc之前申請的那塊內(nèi)存空間,即需要調(diào)整大小的內(nèi)存空間)
- size: New size in bytes,新的字節(jié)數(shù),注意不是增加的字節(jié)數(shù),而是新開辟的那塊內(nèi)存空間的
字節(jié)數(shù)
(sizeof(…))- 返回值: 新內(nèi)存的起始地址(一般要xx=realloc)
memcpy
void *memcpy(void *dest, void *source, size_t n)
- dest:指向用于存儲復(fù)制內(nèi)容的目標(biāo)數(shù)組
- source:指向要復(fù)制的數(shù)據(jù)源
- n :要被復(fù)制的
字節(jié)數(shù)
(sizeof(…))- 返回值:指向dest的指針(一般不用xx=,而是直接調(diào)用即可)
1.正常在復(fù)制字符串時(shí)用strcpy,而需要復(fù)制其他類型數(shù)據(jù)時(shí)則一般用memcpy
2.strcpy不需要指定長度,它遇到被復(fù)制字符的串結(jié)束符"\0"才結(jié)束,所以容易溢出。memcpy則可控制需要復(fù)制長短n
3.source和destin所指的內(nèi)存區(qū)域可能重疊,但是如果source和dest所指的內(nèi)存區(qū)域重疊,那么這個(gè)函數(shù)并不能夠確保source所在重疊區(qū)域在拷貝之前不被覆蓋。而使用memmove
可以用來處理重疊區(qū)域。
memmove
void *memmove(void *dest, const void *source, size_t n)
- dest:指向用于存儲復(fù)制內(nèi)容的目標(biāo)數(shù)組
- source:指向要復(fù)制的數(shù)據(jù)源
- n:要被復(fù)制的
字節(jié)數(shù)
- 返回值:指向dest的指針(一般不用xx=,而是直接調(diào)用即可)
能夠?qū)Ρ旧磉M(jìn)行覆蓋拷貝的函數(shù),其又同時(shí)兼?zhèn)淞?memcpy函數(shù) 可做的事
//去除 sb 緩沖區(qū)左端的所有 空格,tab,'\t'。
void strbuf_ltrim(struct strbuf *sb)
{while((*(sb->buf)==' '||sb->buf[0]=='\t')&&sb->buf[0]!='\0')//這兩種都可以,就是不行sb->buf==' ',因?yàn)? { //C++ forbids comparison between pointer and integer
sb->buf=(char*)memmove(sb->buf,sb->buf+1,sb->len-1);//全部向左平移一位
sb->len--;
}
}
//去除 sb 緩沖區(qū)右端的所有 空格,tab, '\t'。
void strbuf_rtrim(struct strbuf *sb)
{while((sb->buf[(sb->len)-1]==' '||sb->buf[(sb->len)-1]=='\t')&&sb->buf[(sb->len)-1]!='\0')
{// sb->buf+(sb->len)-1='\0';錯(cuò)
// sb->buf=(char*)memmove(sb->buf+(sb->len)-1,sb->buf+(sb->len),1);
sb->buf[(sb->len)-1]='\0';
sb->len--;
}
}
//刪除 sb 緩沖區(qū)從 pos 坐標(biāo)長度為 len 的內(nèi)容。
void strbuf_remove(struct strbuf *sb, size_t pos, size_t len)
{// int i;多此一舉
// for(i=0;i// sb->buf[pos+i]=0;
// }
memmove(sb->buf+pos,sb->buf+pos+len,sb->len-pos-len);//strlen(sb->buf+pos+len)+1 OK!
sb->len=sb->len-len;
sb->buf[sb->len]='\0';
}
//sb 增長 hint ? hint : 8192 大小, 然后將文件描述符為 fd 的所有文件內(nèi)容追加到 sb 中。
ssize_t strbuf_read(struct strbuf *sb, int fd, size_t hint)//數(shù)據(jù)類型解釋見下
{ssize_t result; //根據(jù)函數(shù)返回值定數(shù)據(jù)類型
sb->buf=(char*)realloc(sb->buf,sb->alloc+(hint ? hint : 8192));//不是sb->len+(...)
sb->alloc+=(hint ? hint : 8192);
result=read(fd,sb->buf+sb->len,sb->alloc-sb->len-1);//函數(shù)解釋見下
if(result){sb->len+=result;
sb->buf[sb->len]='\0';
}
return result;
}
//將 將文件句柄為 fp 的一行內(nèi)容(拋棄換行符)讀取到 sb 。
int strbuf_getline(struct strbuf *sb, FILE *fp)
{char ch;
// ch=fgetc(fp); //返回值為int,然后再ch!=EOF ->ok因?yàn)镋OF=-1
法一:
while((ch = fgetc(fp))!='\n' && ch!=EOF)
{ strbuf_addch(sb, ch);
}
法二:
while((ch = fgetc(fp))!='\n' && feof(fp)==0)//順序不能錯(cuò),函數(shù)解釋見下
{ strbuf_addch(sb, ch);
}
return 1;
}
read
ssize_t read(int fd ,void *buf, size_t count);
作用:從文件描述符對應(yīng)的文件讀取數(shù)據(jù),調(diào)用成功返回讀出的字節(jié)數(shù)
頭文件:include
- fd:文件描述符
- buf:讀出數(shù)據(jù)的緩沖區(qū)(將文件中讀出目標(biāo)數(shù)據(jù),放入buf緩沖區(qū)中)
- count:每次讀取的
字節(jié)數(shù)
(是請求讀取的字節(jié)數(shù),讀上來的數(shù)據(jù)保存在緩沖區(qū)buf中,同時(shí)文件的當(dāng)前讀寫位置向后移)- 返回值:成功返回讀出的字節(jié)數(shù);失敗返回-1;EOF返回0
ssize_t
有符號整型,在32位機(jī)器上等同與int,在64位機(jī)器上等同與long int
文件描述符
- 操作系統(tǒng)利用文件描述符來訪問文件。
- 文件描述符是非負(fù)整數(shù)。
- 打開現(xiàn)存文件或新建文件時(shí),內(nèi)核會返回一個(gè)文件描述符。
- 讀寫文件也需要使用文件描述符來指定待讀寫的文件。
- 只要獲取到文件描述符,就可以找到對應(yīng)的文件
文件句柄pf/fp
出錯(cuò)返回NULL
fgetc
int fgetc(FILE *filename)
- 在文件處理中,通過fgetc()函數(shù),我們從輸入流中獲取下一個(gè)字符,并將文件指針加1 (調(diào)用一次,filename向后移動一位)
- 返回一個(gè)整數(shù)值,該值是無符號char的轉(zhuǎn)換。 它還返回EOF ,而EOF也是一個(gè)整數(shù)值-1 。
feof
int feof(FILE *fp)
- 當(dāng)文件被打開,光標(biāo)處于默認(rèn)的開頭時(shí),光標(biāo)后都有信息,這時(shí)候調(diào)用feof()來查看光標(biāo)后是否還有內(nèi)容,就沒意義
- 先使用getc(),從文件中讀取一個(gè)字符,讓光標(biāo)向后移動一個(gè)字符。這時(shí)空文件的光標(biāo)就已經(jīng)移動到EOF的后面,這時(shí)使用feof()就會返回1了
- 原理:站在光標(biāo)所在位置,向后看看還有沒有字符。
如果有,返回0
;如果沒有,返回非0
。它并不會讀取相關(guān)信息,只是查看光標(biāo)后是否還有內(nèi)容。
//實(shí)現(xiàn)字符串切割
//將長度為 len 的字符串 str 根據(jù)切割字符 terminator 切成多個(gè) strbuf,并從結(jié)果返回,
//max 可以用來限定大切割數(shù)量。返回 struct strbuf 的指針數(shù)組,數(shù)組的最后元素為 NULL
struct strbuf **strbuf_split_buf(const char *str, size_t len, int terminator, int max)
{//分配內(nèi)存
struct strbuf **p=(struct strbuf**)malloc(sizeof(struct strbuf*)*(max+1));//切3次,有3+1塊
//由于要返回struct strbuf的指針數(shù)組,因此定義**p,相當(dāng)于*p[],
//即數(shù)組p里面每個(gè)單元都是一個(gè)struct strbuf*指針,單獨(dú)指向一個(gè)結(jié)構(gòu)體(而每個(gè)結(jié)構(gòu)體的buf指向一塊內(nèi)存空間,所以下面需要兩次申請malloc)
//指針保存被切割字符串的首末地址
const char *begin=str;
const char *end=str+len; // 字符串str \0的位置
const char *next;
int i=0;
int len2;
//首元素是被切割字符的話,就直接跳過(p[]里放空內(nèi)容沒有意義)
while(*begin==terminator)
begin++;
//從第一個(gè)非切割字符開始,往后遍歷整個(gè)str,找切割字符terminator
for (next=begin;next<=end;next++)
{if (*next==terminator||next==end)//注意是否要*
{len2=next-begin;//地址之差,長度即為小塊的字符串
p[i]=(struct strbuf*)malloc(sizeof(struct strbuf));//為指針p[i]所指向的結(jié)構(gòu)體申請一塊內(nèi)存,用于存放結(jié)構(gòu)體(然后p[i]指向了這塊空間,也就指向了那個(gè)結(jié)構(gòu)體)
p[i]->len=len2;
p[i]->alloc=len2+1;
p[i]->buf=(char*)malloc(sizeof(char)*(len2+1));// 因?yàn)榻Y(jié)構(gòu)體里的buf為指針,又指向了一塊內(nèi)存,所以向上面各個(gè)函數(shù)一樣,malloc?。ㄗ⒁鈂0)
memcpy(p[i]->buf,begin,len2);//len2長度的限制,從而實(shí)現(xiàn)將一小塊字符串拷貝到buf中
*(p[i]->buf+len2)='\0';
i++;
//連續(xù)的切割字符沒有意義,跳過
while(*next==terminator&&next<=end)
next++;
//新的頭(每切一塊,頭就向后移動對應(yīng)的長度)
begin=next;
}
if(i==max)
break;
}
p[i]=NULL;
return p;
}
//實(shí)現(xiàn)判斷一個(gè) strbuf 是否以指定字符串開頭的功能
//target_str:目標(biāo)字符串,str:前綴字符串,strnlen:target_str 長度,前綴相同返回 true 失敗返回 false
bool strbuf_begin_judge(char* target_str, const char* str, int strnlen)//返回值解釋見下
{法一:
if(strnlen==0 || memcmp(target_str,str,strlen(str))==0)//相同返回0,函數(shù)解釋見下
return true;
else
return false;
法二:
int i;
for(i=0;iif(str[i]=='\0')
break;
if(target_str[i]!=str[i])
return false;
}
return true;
}
//獲取字符串從坐標(biāo) [begin, end) 的所有內(nèi)容(可以分成引用和拷貝兩個(gè)模式)
//target_str:目標(biāo)字符串,begin:開始下標(biāo),end:結(jié)束下標(biāo),len:target_buf的長度
//下標(biāo)從0開始,[begin, end)區(qū)間,參數(shù)不合法返回 NULL
char* strbuf_get_mid_buf(char* target_buf, int begin, int end, int len)
{if(end
memcmp
int memcmp(const void *str1, const void *str2, size_t n)
- str1 : 指向內(nèi)存塊的指針
- str2 : 指向內(nèi)存塊的指針
- n : 要被比較的
字節(jié)數(shù)
- 返回值 :當(dāng)str1
????當(dāng)str1=str2時(shí),返回值=0
????當(dāng)str1>str2時(shí),返回值>0如果兩個(gè)字符串相同而且n大于字符串長度的話,memcmp不會在\0處停下來,會繼續(xù)比較\0后面的內(nèi)存單元,直到_res不為零或者達(dá)到n的次數(shù)。
- 但strncmp必定會在最短的字符串的末尾停下來,即使count還未為零
boll
頭文件:include
只能用來存放兩個(gè)值:true (1) 和 false (0)
你是否還在尋找穩(wěn)定的海外服務(wù)器提供商?創(chuàng)新互聯(lián)www.cdcxhl.cn海外機(jī)房具備T級流量清洗系統(tǒng)配攻擊溯源,準(zhǔn)確流量調(diào)度確保服務(wù)器高可用性,企業(yè)級服務(wù)器適合批量采購,新人活動首月15元起,快前往官網(wǎng)查看詳情吧
網(wǎng)頁名稱:設(shè)計(jì)一個(gè)C語言的動態(tài)擴(kuò)容緩沖區(qū)-創(chuàng)新互聯(lián)
文章源于:http://jinyejixie.com/article38/hgdsp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)、定制網(wǎng)站、域名注冊、品牌網(wǎng)站建設(shè)、網(wǎng)站排名、標(biāo)簽優(yōu)化
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容