☆
去掉首尾空格的函數
char * trim(char * s)
{
if(s==NULL)
return NULL;
unsigned len=strlen(s);
register char *p1=s;
register char *p2=s+len-1;
while(*p1==' ')
p1++;
if(p1>=p2){
memcpy(s,p1,strlen(p1)+1);
return s;
}
while(*p2==' ')
p2--;
memcpy(s,p1,p2-p1+1);
*(s+(p2-p1)+1)=0;
return(s);
}
☆
比較內存內容memcmp
表頭文件:#include <string.h>
定義函數:int memcmp(const void *s1, const void *s2, size_t n)
函數說明:memcmp()用來比較s1和s2所指的內存區間前n個字符。字符串大小的比較是以ASCII碼表上的順序來決定,此順序亦為字符的值。memcmp()首先將s1第一個字符值減去s2第一個字符值,若差值為0則再繼續比較下個字符,若差值不為0則將差值返回。
返回值:若參數s1和s2所指定的內存內容都完全相同則返回0值。s1若大于s2則返回大于0的值。s1若小于s2則返回小于0的值
范例:
#include <string.h>
main()
{
char *a="aBcDeF";
char *b="AbCdEf";
printf("%d", memcmp((void *) a, (void *) b, 6));
}
☆
sprintf()函數
sprintf跟printf在用法上差不多,只是打印的目的地不同,前者打印到字符串中,后者直接在命令行上輸出。
定義函數:int sprintf( char *buffer, const char *format [,argument]
);
經典用途:格式化數字字符串;連接字符串(可以連接多個,比strcat強)。
注意:小心第一個參數的長度不夠。為了安全,可以使用%.ns來控制輸出參數的最多個數。而且好像buffer不是申明為字符數組會報錯。
范例:
#include <stdio.h>
int main(void){
char * a="abcdefg";
char b[15];
sprintf(b,"%.7s",a);
printf("result=%s\n",b);
}
☆
比較字符串函數
1)strncmp
表頭文件:<string.h>
定義函數:int strncmp(char *str1, char *str2, int maxlen);
和memcmp類似
2)strncasecmp(不區分大小寫)
定義函數:int strncasecmp(char *str1, char *str2, int maxlen);
3) memcmp()函數與strncmp()函數基本相似,只是它在遇到NUL字符時不會結束。
☆
atexit
注冊一個給定的函數,該函數在程序exit時候被調用。(不管是通過exit(3)或者還是通過從程序的main函數中返回)。 注冊的函數是反序被調用的;沒有參數。至少32個函數總是可以被注冊的,只要有充分的分配的內存,更多的函數也是允許的。
定義函數:int atexit(void (*function)(void))
表頭文件:stdlib.h
例子:
#include <stdlib.h>
int atexit(void (*function)(void));
#include <stdio.h>
void fn(void );
int main( void )
{
atexit( fn);
printf( "main\n" );
}
void fn()
{
printf( "fn\n" );
}
☆
segmentation fault
如果在運行的時候,非法訪問內存就會出現"segmentation fault"的結果。
例如:
int i=100;
printf("%s",i);
這樣會直接取訪問100地址的空間。
☆
malloc動態分配內存
例如分配100個字符空間:char * p=(char *)malloc(100*sizeof(char));
釋放空間:free(p);
注意:
1)申請了內存空間后,必須檢查是否分配成功。如果分配失敗得到的p是NULL;
2)當不需要再使用時,記得釋放(和java就是不一樣),如果不釋放會造成內存泄漏;釋放后應該把指向這塊內存的指針指向NULL,防止程序后面不小心使用了它。
3)如果釋放兩次及兩次以上會出現錯誤(釋放空指針例外,釋放空指針其實也等于啥也沒做,所以釋放空指針釋放多少次都沒有問題)。
4)malloc()函數的類型是(void *),任何類型的指針都可以轉換成(void *),但是最好還是在前面進行強制類型轉換,因為這樣可以躲過一些編譯器的檢查。
malloc從哪里得到空間:
從堆里面獲得空間。也就是說函數返回的指針是指向堆里面的一塊內存。操作系統中有一個記錄空閑內存地址的鏈表。當操作系統收到程序的申請時,就會遍歷該鏈表,然后就尋找第一個空間大于所申請空間的堆結點,然后就將該結點從空閑結點鏈表中刪除,并將該結點的空間分配給程序。
☆
堆/棧
堆是大家共有的空間,分全局堆和局部堆。全局堆就是所有沒有分配的空間,局部堆就是用戶分配的空間。堆在操作系統對進程初始化的時候分配,運行過程中也可以向系統要額外的堆。
棧是線程獨有的,保存其運行狀態和局部自動變量的。棧在線程開始的時候初始化,每個線程的棧互相獨立。每個函數都有自己的棧,棧被用來在函數之間傳遞參數。操作系統在切換線程的時候會自動的切換棧,就是切換SS/ESP寄存器。棧空間不需要在高級語言里面顯式的分配和釋放。
☆
字符數據賦值
char str[5]="1234";
str="abcd";//這樣會出錯(將常量字符串的地址付給一個字符指針)
☆
分解字符串(類似JAVA中的split)
定義函數:extern char *strtok(char *s, char *delim);
表頭文件:<string.h>
功能:分解字符串為一組標記串。s為要分解的字符串,delim為分隔符字符串。
說明:首次調用時,s必須指向要分解的字符串,隨后調用要把s設成NULL。strtok在s中查找包含在delim中的字符并用NULL('\0')來替換,直到找遍整個字符串。返回指向下一個標記串。當沒有標記串時則返回空字符NULL。
舉例(怪怪的):
#include <string.h>
#include <stdio.h>
int main(void)
{
char s[]="a,b,c,d";
char *p;
p=strtok(s,",");
while(p!=NULL)
{
printf("%s\n",p);
p=strtok(NULL,",");
}
return 0;
}
☆
求字符串長度的函數strlen
定義函數:size_t strlen(const char * s);
表頭文件:<string.h>
函數功能:計算字符串s的長度,不包括'\0';
舉例:
int main(void){
char a[5]="abc";
printf("%d",strlen(a));
}
☆
正則表達式
標準的C不支持正則表達式,但有一些函數庫可以輔助完成這一功能,其中最著名的當數Philip Hazel的Perl-Compatible Regular Expression庫,許多Linux發行版本都帶有這個函數庫。
使用正則表達式用三個過程:編譯正則表達式->匹配正則表達式->釋放正則表達式
1)編譯正則表達式
為了提高效率,在將一個字符串與正則表達式進行比較之前,首先要用regcomp()函數對它進行編譯,將其轉化為regex_t結構:
int regcomp(regex_t *preg, const char *regex,int cflags);
參數regex是一個字符串,它代表將要被編譯的正則表達式;參數preg指向一個聲明為regex_t的數據結構,用來保存編譯結果;參數cflags決定了正則表達式該如何被處理的細節。如果函數regcomp()執行成功,并且編譯結果被正確填充到preg中后,函數將返回0,任何其它的返回結果都代表有某種錯誤產生。
2)匹配正則表達式
一旦用regcomp()函數成功地編譯了正則表達式,接下來就可以調用regexec()函數完成模式匹配:
int regexec(const regex_t *preg, const char *string, size_t nmatch,regmatch_t pmatch[], int eflags);
typedef struct {regoff_t rm_so; regoff_t rm_eo; } regmatch_t;
參數preg指向編譯后的正則表達式,參數string是將要進行匹配的字符串,而參數nmatch和pmatch則用于把匹配結果返回給調用程序,最后一個參數eflags決定了匹配的細節。
在調用函數regexec()進行模式匹配的過程中,可能在字符串string中會有多處與給定的正則表達式相匹配,參數pmatch就是用來保存這些匹配位置的,而參數nmatch則告訴函數regexec()最多可以把多少個匹配結果填充到pmatch數組中。當regexec()函數成功返回時,從string+pmatch[0].rm_so到string+pmatch[0].rm_eo是第一個匹配的字符串,而從string+pmatch[1].rm_so到string+pmatch[1].rm_eo,則是第二個匹配的字符串,依此類推。
3)釋放正則表達式
無論什么時候,當不再需要已經編譯過的正則表達式時,都應該調用函數regfree()將其釋放,以免產生內存泄漏。
void regfree(regex_t *preg);
函數regfree()不會返回任何結果,它僅接收一個指向regex_t數據類型的指針,這是之前調用regcomp()函數所得到的編譯結果。
如果在程序中針對同一個regex_t結構調用了多次regcomp()函數,POSIX標準并沒有規定是否每次都必須調用regfree()函數進行釋放,但建議每次調用regcomp()函數對正則表達式進行編譯后都調用一次regfree()函數,以盡早釋放占用的存儲空間。
4)報告錯誤信息
如果調用函數regcomp()或regexec()得到的是一個非0的返回值,則表明在對正則表達式的處理過程中出現了某種錯誤,此時可以通過調用函數regerror()得到詳細的錯誤信息。
size_t regerror(int errcode, const regex_t *preg, char *errbuf,size_t errbuf_size);
參數errcode是來自函數regcomp()或regexec()的錯誤代碼,而參數preg則是由函數regcomp()得到的編譯結果,其目的是把格式化消息所必須的上下文提供給regerror()函數。在執行函數regerror()時,將按照參數errbuf_size指明的最大字節數,在errbuf緩沖區中填入格式化后的錯誤信息,同時返回錯誤信息的長度。
5)應用正則表達式
例如匹配電話號碼和Email的例子
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
/*******************************************
*pattern:正則表達式,str:待檢測的字符串
*如果匹配返回0,否則返回-1
********************************************/
int regMatch(char * pattern,char * str){
int ret=-1;
regex_t reg;
regmatch_t match={0,0};
if(regcomp(®,pattern,REG_EXTENDED)==0)
ret=regexec(®,str,1,&match,0);
regfree(®);
return ret;
}
int main(int argc, char *argv[])
{
printf("ret=%d\n",regMatch("^[0-9]\{3,4}-[0-9]\{7,8}$","0592-1234567"));
printf("ret=%d\n",regMatch("^[a-z0-9A-Z_-]+@([a-z0-9A-Z_-]+\\.)+[a-z0-9A-Z_-]+$","zeng_chao_1984@163.com"));
return 0;
}
例如返回匹配結果的例子
#include <sys/types.h>
#include <regex.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
regex_t prog;
regmatch_t match={0,0};
char *pattern="[0-9]+";
char *string="12 3456 3456y 7890",*s;
regcomp(&prog, pattern, REG_EXTENDED);
s= string;
while(regexec(&prog,s, 1,&match,0)==0)
{
printf("match at offset %d,length %d\n",s-string+match.rm_so,match.rm_eo-match.rm_so);
s+=match.rm_eo;
}
regfree(&prog);
}
☆
make命令
使用make命令的幾個優點:
1)只編譯修改過的程序。例如一個大的項目包含上百個程序,如果只修改其中一小部分需要測試,這時使用make會只重新編譯修改過的程序,而不會全部編譯。
2)make命令能確定不同文件之間的依賴關系,可以定義宏和附加的目標文件,可以執行多項操作,提高開發效率
一個簡單的make例子(文件命名為makefile)
CC = cc
ESQL = $(INFORMIXDIR)/bin/esql
LIBDIR = /usr/lib
test:test.o
$(ESQL) -o test test.o
執行make命令,輸入make test,如果修改過顯示如下:
cc -c -o test.o test.c
/home/informix/bin/esql -o test test.o
如果已經是最新的話,不需要重新編譯,顯示如下:
make: `test' is up to date.
☆
memcpy
函數原型:extern void *memcpy(void *dest, void *src, unsigned int count);
用法:#include <string.h>
功能:由src所指內存區域復制count個字節到dest所指內存區域。
說明:src和dest所指內存區域不能重疊,函數返回指向dest的指針。
運用1:實現Java中的淺度克隆
typedef struct
{
int id;
} structA;
int main(){
structA a==(structA *)malloc(sizeof(structA));
a.id=1;
structA b==(structA *)malloc(sizeof(structA));
memcpy(b,a,sizeof(b));
return 0;
}
運用2:實現Java中的深度克隆
typedef struct
{
int charLen;
char* charA;
} structB;
typedef struct
{
structB* b;
} structA;
typedef struct
{
structA* a;
} testStruct;
structB b;
structA a;
testStruct *des,src;
int main()
{
char *p="test";
b.charA=p;
b.charLen=strlen(p);
a.b=&b;
src.a=&a;
printf("%s\n",src.a->b->charA);
/* 一級一級分配空間*/
des=(testStruct*)malloc(sizeof(testStruct));
des->a=(structA*)malloc(sizeof(structA));
des->a->b=(structB*)malloc(sizeof(structB));
des->a->b->charA=(char*)malloc(sizeof(p));
/*深度復制*/
memcpy(des,&src,sizeof(testStruct));
printf("%s\n",des->a->b->charA);
/*一級一級釋放空間*/
/*先釋放最里面指針的空間,然后外層,否則會引起內存泄露*/
free(des->a->b->charA);
free(des->a->b);
free(des->a);
free(des);
return 0;
}
☆
查找最先出現的任意指定字符strtpbrk()
表頭文件:#include<string.h>
函數定義:char * strpbrk(const char *s,const char * accept);
函數說明:strpbrk()用來查找在字符串s中最先出現的accept中的任意一個字符的位置;
返回值:如果找到指定的字符則返回該字符所在地址,否則返回0;
例如:
int main(){
char a[10]="abcdefgh";
char * p=NULL;
p=strpbrk(a,"123d45");
printf("%s\n",p);
return 0;
}
輸出結果:defgh
☆
查找指定的字符串strstr()
表頭文件:#include<string.h>
函數定義:char * strstr(const char *str,const char * s);
函數說明:strstr()用來查找在字符串str中最先出現字符串s的位置;
返回值:如果找到指定的字符串則返回該字符串所在地址,否則返回0;
例如:
int main(){
char a[10]="abcdefgh";
char * p=NULL;
p=strpbrk(a,"def");
printf("%s\n",p);
return 0;
}
輸出結果:defgh
posted on 2007-09-25 10:45
破繭而出 閱讀(1003)
評論(0) 編輯 收藏 所屬分類:
C/C++