1. 程式人生 > >linux下的c語言系統函式呼叫

linux下的c語言系統函式呼叫

目錄

4.linux下的系統函式的使用 c語言

4.1數學函式的使用

1pow函式

2.exp函式

3.log函式

4.rand()隨機數函式

4.2字元函式的使用

4.3系統時間與日期函式的使用

系統時間

時間間隔

4.4環境控制函式


 

4.linux下的系統函式的使用 c語言

4.1數學函式的使用

pow(x,y)  //x的y次方 
exp(x)      //e的x次方
log(x)      //lnx
log10(x)  //lg(x)   
以上返回值引數全double

1pow函式

#include<stdio.h>
#include<math.h>
int main(){
	double answer,x,y;
	scanf("%lf %lf",&x,&y);
	answer=pow(x,y);
	printf("%lf的%lf次方等於%lf\n",x,y,answer);
	return 0;
}

 

2.exp函式

#include<stdio.h>
#include<math.h>
int main(){
	double answer,x;
	scanf("%lf",&x);
	answer=exp(x);
	printf("e的%lf次方等於%lf\n",x,answer);
	return 0;
}

 

3.log函式

#include<stdio.h>
#include<math.h>
int main(){
	double answer1,answer2,x,y;
	scanf("%lf %lf",&x,&y);
	answer1=log(x);//2.718281828
	answer2=log10(y);//10
	printf("log(%lf)=%lf\n",x,answer1);
	printf("log10(%lf)=%lf\n",y,answer2);
	return 0;
}

 

sqrt(x)  求平方根   

函式都在math.h 裡編譯時加上-lm    c++編譯則不用

 

4.rand()隨機數函式

先設定隨機數種子 否則每次產生的隨機數一樣
srand(time(0));

標頭檔案 #include<stdlib.h>

int rand(void); //0~2147483674(0~RAND_MAX) 之間的隨機數

模板1:
rand()/(RAND_MAX+1.0)                 產生:[0,1)
int(10.0×rand()/(RAND_MAX+1.0))     產生[0,10)
1+int(10.0×rand()/(RAND_MAX+1.0))     產生[1,10]

模板2:
rand()%(N+1)    產生[0,N]
M+rand()%(N+1)  產生[M,M+N]

 

4.1.產生10個1到10的隨機數

#include<stdio.h>
#include "stdlib.h"
int main(){
	int i,j;
	srand((int)time(0));
	for(i=0;i<10;i++){
		j=1+(int)(10.0*rand()/(RAND_MAX+1.0));
		printf(" %d ",j);
	}
	printf("\n");
	return 0;
}

 

4.2產生20個[100,1000]的隨機數

#include <stdlib.h>
#include "stdio.h" 
int main(){
	int i,j; 
	srand((int)time(0)); 
	for(i=0;i<20;i++){
		j=100+rand()%901;
		printf(" %d ",j);
		if(i==9) printf("\n");
	}
	printf("\n");
}

 

4.2字元函式的使用

c語言字元函式
函式名 功能
isalnum 是否為英文字母或數字
isalpha 是否為英文字母
isascii 是否為ascii碼字元
isdigit 是否為阿拉伯數字
islower 是否為小寫英文字母
isprint 是否為可列印字元
isspace 是否為空格
ispunct 是否為標點符號或特殊符號
isupper 是否為大寫英文字母
isxdigit 是否為16進位制數字
標頭檔案 #include<ctype.h>
#include<stdio.h>
#include <ctype.h>
int main(){
	char c;
	while(scanf("%c",&c)==1){
		if(isalnum(c)) printf("%c是英文字母或數字\n",c);
		if(isalpha(c)) printf("%c是英文字母\n",c);
		if(isascii(c)) printf("%c是ascii碼字元\n",c);
		if(iscntrl(c)) printf("%c是ascii碼控制字元\n",c);
		if(isdigit(c)) printf("%c是數字\n",c);
		if(islower(c)) printf("%c是小寫字母\n",c);
		if(isupper(c)) printf("%c是大寫字母\n",c);
		if(isprint(c)) printf("%c是可列印字元\n",c);
		if(isspace(c)) printf("%c是空格\n",c);
		if(isxdigit(c)) printf("%c是16進位制數字\n",c);
		getchar();
	}
	return 0;
}

 

 

4.3系統時間與日期函式的使用

系統時間

系統時間與日期函式
函式名 功能
asctime 將時間和日期以字串格式表示
ctime 將時間和日期以字串格式表示
gettimeofday 取得當前時間
gmtime 把時間和日期轉換為格林尼治(GMT)時間(世界時)
localtime 取得目前當地的時間和日期,並轉換為現在的時間日期表示方法
mktime 將時間結構資料轉換成經過的秒數
settimeofday 設定當前時間
time 取得系統當前的時間
//系統結構體
struct tm{
	int tm_sec;  //秒
	int tm_min;  //分
	int tm_hour; //時
	int tm_mday;  //當前月日數
	int tm_mon;  //月 0~11
	int tm_year;  //1900至今的年數  1900+p->tm_year得到今年年份
	int tm_wday;  //一星期的日數 0~6
	int tm_yday;  //一年內的天數 0~365
	int tm_isdst;  //夏時制時間	
};

標頭檔案#include<time.h>
time_t time(time_t *t);  
取得當前時間 其實是返回1970年1月1日0:0:0至今的秒數 
返回值會直接存到t指向的記憶體   

標頭檔案#include<time.h>
struct tm* gmtime(const time_t* timep);
將time_t裡的秒數轉換成現在的時間格式(格林尼治)  返回結構體struct_t

標頭檔案#include<time.h>
char* asctime(const struct tm * timeptr);
將結構體struct_tm裡的時間轉換成現在使用的時間日期表示法,格式為”Wed Jun 30 16:13:00 2018\n”

標頭檔案#include<time.h>
struct tm *localtime(const time_t *timep);
將time_t裡的時間資訊轉換成現在使用的時間日期表示法,返回強悍的struct tm結構體

eg1:time取得當前時間,gmtime轉換成格林尼治時間,字串形式輸出(直接asctime函式轉)。
         自己轉換,成“xxxx年 x月 xx日 Tue 15:52:00"形式顯示系統時間
 

#include<time.h>
int main(){
	time_t timep;//時間結構體變數
	char *wday[]={"Sun","Mon","Tue","Wed","Thu","Fri","Sat"}; 
	struct tm *p;
	time(&timep);//獲取當前時間
	printf("%s",asctime(gmtime(&timep)));
	p=localtime(&timep);//獲取當地時間 並按現在的時間日期來表示
	printf("%d年 %d月 %d日\n",(1900+p->tm_year),(1+p->tm_mon),p->tm_mday);
	printf("%s %d:%d:%d\n",wday[p->tm_wday],p->tm_hour,p->tm_min,p->tm_sec);
	return 0;
}

eg2:c語言寫鐘錶

#include<stdio.h>
#include<time.h>
#include <unistd.h>
main(){
	time_t timep;//時間結構體變數
	struct tm *p;
	while(1){
		time(&timep);//獲取當前時間
		p=localtime(&timep);//獲取當地時間 並按現在的時間日期來表示
		printf("%d年%d月%d日 %d:%d:%02d\n",1900+p->tm_year,p->tm_mon+1,p->tm_mday,p->tm_hour,p->tm_min,p->tm_sec);
		sleep(1);
	}
 	printf("\n時間到!\n\a"); // \a是讓系統發出聲音的一種表達方式
 }

 

時間間隔

struct timeval{
       long tv_sec; //秒
       long tv_usec;//微秒
};

struct timezone{
       int tz_minuteswest; //和格林尼治時間差了多少分鐘
       int tz_dsttime; //日光節約時間的狀態
};

gettimeofday函式說明
標頭檔案:#include<sys/time.h>     #include<unistd.h>
int gettimeofday(struct timeval * tv,struct timezone * tz)
把當前時間分s與us放到tv中返回  當地時區資訊放到tz中返回

做某事的時間模板
gettimeofday(&tv1,&tz);
/*do something*/
gettimeofday(&tv2,&tz);
t=tv2.tv_sec-tv1.tv_sec+(tv2.tv_usec-tv1.tv_usec)*pow(10,-6);//s+us*10^-6

eg1.

#include <stdio.h>
#include <unistd.h>
#include <sys/time.h>
int main(){
	struct timeval tv1,tv2;
	struct timezone tz;
	gettimeofday(&tv1,&tz);
	printf("1970距離今天tv_sec= %d 秒\n",tv1.tv_sec);
	printf("零頭有tv_usec= %d 微秒\n",tv1.tv_usec);
	gettimeofday(&tv2,&tz);
	printf("第7行到第10行程式耗時tv2_usec-tv1_usec= %d 微秒\n",tv2.tv_usec-tv1.tv_usec);//程式一定在ms內完成
	//printf("%d\n",tv2.tv_sec-tv1.tv_sec);//絕對在ms級別 所以輸出0
	return 0;
}

 

exp2:大例

#include<stdio.h>
#include<stdlib.h>
#include<sys/time.h>
#include<unistd.h>
int main()
{
	long int begin,sec,stop;
	struct timeval tv1, tv2;
	struct timezone tz;
	char tmp;
	begin=0;
	stop=0;
	sec=0;
	system("clear");
	printf("計時器程式(單位s)\n");
	printf("輸入b(begin)計時器開始計時\n");
	printf("輸入w(watch)檢視已經累計時間\n");
	printf("輸入r(rest)重新開始計時\n");
	printf("輸入s(stop)暫停計時器\n");
	printf("輸入e(end)結束計時器\n");
	while(1)
	{
		scanf("%c",&tmp);
		if(tmp=='b')
		{
			if(begin==1&&stop==0)
				printf("計時器已經啟動!\n");
			if(begin==0&&stop==0)
			{
				printf("計時器啟動\n");
				gettimeofday(&tv1,&tz);
				sec=0;
				begin=1;
			}
			if(stop==1)
			{
				gettimeofday(&tv1,&tz);
				stop=0;
				printf("暫停結束!\n");
			}
		}
		if(tmp=='w'){
			if(stop==0){
				gettimeofday(&tv2,&tz);
				printf("已經計時%ld 秒\n",sec+tv2.tv_sec-tv1.tv_sec);
			}
			if(stop==1)
				printf("已經計時%ld 秒\n",sec);
		}
		if(tmp=='s'){
			if(stop==1){
				printf("計時已經暫停!\n");
			}
			if(stop==0){
				gettimeofday(&tv2,&tz);
				sec=sec+tv2.tv_sec-tv1.tv_sec;
				printf("計時暫停,已經計時%ld 秒\n",sec);
				stop=1;
			}
		}
		if(tmp=='r'){
			gettimeofday(&tv2,&tz); 
			printf("已經計時%ld 秒\n",sec+tv2.tv_sec-tv1.tv_sec);
			printf("計時器在5 秒後被重置!\n");
			sleep(5);
			begin=0;
			sec=0;
			stop=0;
			system("clear");
			printf("計時器程式(單位s)\n");
			printf("輸入b(begin)計時器開始計時\n");
			printf("輸入w(watch)檢視已經累計時間\n");
			printf("輸入r(rest)重新開始計時\n");
			printf("輸入s(stop)暫停計時器\n");
			printf("輸入e(end)結束計時器\n");
		}
		if(tmp=='e') break;
	}
	return 0;
}

 

 

4.4環境控制函式

常用環境控制函式
函式名 功能
getenv 取得環境變數的內容
putenv/setenv 改變/增加環境變數
unsetenv 取消已經改變的環境變數

getenv函式:
標頭檔案:#include<stdlib.h>
char* getenv(const char *name);  //失敗返回null
根據環境變數名name,取得該系統環境變數的值      環境變數格式key=value    

eg1.獲取當前登入使用者

當前登入使用者環境變數key為USER  (只能大寫,不能小寫)

#include<stdio.h>
#include<stdlib.h>
int main(){
	char *p;
	if((p=getenv("USER")))
		printf("USER=%s\n", p);
	return 0;
}

 

setenv函式:
標頭檔案:#include<stdlib.h>
int setenv(const char *key,const char *value,int overwrite);
改變或者增加環境變數     overwrite:1:改為value新值       0:該環境變數已有內容時,引數value被忽略(也即本次不改值)    

 

eg2:修改USER的值

#include<stdio.h>
#include<stdlib.h>
int main(){
	char *p;
	if(p=(getenv("USER"))){
		printf("USER =%s\n",p);
	}
	setenv("USER","test",1);
	printf("USER=%s\n",getenv("USER"));
	unsetenv("USER");
	printf("USER=%s\n",getenv("USER"));
	setenv("USER","test",0);//USER無value時也會改
	printf("USER=%s\n",getenv("USER"));
	setenv("USER","test2",0);//USER有value時不會改 忽略test2 下面仍然輸出test
	printf("USER=%s\n",getenv("USER"));
	return 1;	
}

 

 

exp3:輸出系統所有的環境變數

linuxC有一個全域性變數 environ 在unistd.h裡

#include<stdio.h>
int main(){
	extern char **environ;//environ不能取別的名字 是系統全域性變數
	int i;
	for(i=0;environ[i]!=NULL;i++){
		printf("%s\n",environ[i]);
	}
	return 0;
}

或者不用extern宣告 直接#include<unistd.h>

#include<stdio.h>
#include<unistd.h>
int main(){
	int i;
	for(i=0;environ[i]!=NULL;i++){
		printf("%s\n",environ[i]);
	}
	return 0;
}

 

4.5記憶體分配函式

常用記憶體分配函式
函式名 功能
calloc/malloc 配置記憶體空間
getpagesize 取得作業系統中記憶體分頁大小
mmap 建立記憶體對映
munmap 解除記憶體對映
free 釋放原先配置的記憶體

calloc函式
標頭檔案#include<stdlib.h>
void *calloc(size_t nmemb,size_t size); //成功返回指標,失敗返回NULL
用來分配nmemb*size的記憶體塊。
nmemb為記憶體塊的大小
size為記憶體塊的數量
calloc()配置記憶體時會將記憶體內容初始化為0

getpagesize函式
標頭檔案:#include<unistd.h>
size_t getpagesize(void);
取得記憶體分頁大小
取得的為系統分頁大小,不一定和硬體分頁大小相同

malloc函式
標頭檔案:#include<stdlib.h>
void *malloc(size_t size);//成功返回指標 失敗返回NULL
配置記憶體空間,大小由指定的size決定

exp1.錄入結構體

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<ctype.h>
struct co
{
	int index;
	char name[8];
	char MTel[12];
	char Tel[12];
};
int x;
int main(){
	freopen("input.txt","r",stdin);
	struct co *p;
	char ch;
	printf("do you want to add a user?Y/N\n");
	ch=getchar();
	if(ch=='y'||ch=='Y'){
		p=(struct co *)malloc(sizeof(struct co));
		p->index=++x;
		printf("User name:");
		scanf("%s", p->name);
		printf("MoveTel:");
		scanf("%s",p->MTel);
		printf("Tel:");
		scanf("%s",p->Tel);
		printf("intex:%d\nname:%s\nMoveTel:%s\nHomeTel:%s\n",p->index,p->name,p->MTel,p->Tel);
	}
	printf("page size=%d\n", getpagesize());/*取得記憶體分頁大小*/
	return 0;
}

input.txt:

Y
tomcat
17812345678
110

 

mmap函式
標頭檔案:#include<unistd.h>   #inlucde<sys/mman.h>
void *mmap(void *start,size_t length,int prot, int flags,int fd,off_t offsize);
引數start指向對應的記憶體起始地址,通常設定為NULL

引數length代表將檔案中多大的部分對應到記憶體

引數prot:對映區域的保護方式。可以為以下幾種方式的組合:
PROT_EXEC 對映區域可被執行
PROT_READ 對映區域可被讀取
PROT_WRITE 對映區域可被寫入
PROT_NONE 對映區域不能存取

引數flags:影響對映區域的各種特性。在呼叫mmap()時必須要指定MAP_SHARED 或MAP_PRIVATE。
MAP_FIXED 如果引數start所指的地址無法成功建立對映時,則放棄對映,不對地址做修正。通常不鼓勵用此旗標。
MAP_SHARED對對映區域的寫入資料會複製迴文件內,而且允許其他對映該檔案的程序共享。
MAP_PRIVATE 對對映區域的寫入操作會產生一個對映檔案的複製,即私人的“寫入時複製”(copy on write)對此區域作的任何修改都不會寫回原來的檔案內容。
MAP_ANONYMOUS建立匿名對映。此時會忽略引數fd,不涉及檔案,而且對映區域無法和其他程序共享。
MAP_DENYWRITE只允許對對映區域的寫入操作,其他對檔案直接寫入的操作將會被拒絕。
MAP_LOCKED 將對映區域鎖定住,這表示該區域不會被置換(swap)。

引數fd:要對映到記憶體中的檔案描述符。如果使用匿名記憶體對映時,即flags中設定了MAP_ANONYMOUS,fd設為-1。有些系統不支援匿名記憶體對映,則可以使用fopen開啟/dev/zero檔案,然後對該檔案進行對映,可以同樣達到匿名記憶體對映的效果。

引數offset:檔案對映的偏移量,通常設定為0,代表從檔案最前方開始對應,offset必須是分頁大小的整數倍。

返回值:
若對映成功則返回對映區的記憶體起始地址,否則返回MAP_FAILED(-1),錯誤原因存於errno 中。

 

exp2:mmap讀取檔案內容

#include<stdio.h>
#include<sys/types.h>
#include<sys/stat.h>
#include<fcntl.h>
#include<unistd.h>
#include<sys/mman.h>
int main(){
	int fd;
	void *start;
	struct stat sb;
	fd=open("/etc/passwd",O_RDONLY);//許多函式具體見第5章IO
	fstat(fd,&sb);/*取得檔案大小*/
	start=mmap(NULL,sb.st_size,PROT_READ,MAP_PRIVATE,fd,0);/*檔案對映到記憶體,始址為0,偏移量為0(從檔案頭開始)*/
	if(start==MAP_FAILED) return 0;/*對映失敗 直接返回*/
	printf(" %s ", start);
	munmap(start,sb.st_size);/*解除對映*/
	close(fd);
	return 0;
}

 

exp3:獲取檔案屬性

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main()
{
    const char fname[] = "main.c";
    struct stat stat_info;
    if(0 != stat(fname, &stat_info))
    {  
        perror("取得檔案資訊失敗了!");
        exit(1);
    }
    printf("檔案所在裝置編號:%ld\r\n", stat_info.st_dev);
    printf("檔案所在檔案系統索引:%ld\r\n", stat_info.st_ino);
    printf("檔案的型別和存取的許可權:%d\r\n", stat_info.st_mode);
    printf("連到該檔案的硬連線數目:%d\r\n", stat_info.st_nlink);
    printf("檔案所有者的使用者識別碼:%d\r\n", stat_info.st_uid);
    printf("檔案所有者的組識別碼:%d\r\n", stat_info.st_gid);
    printf("裝置裝置檔案:%ld\r\n", stat_info.st_rdev);
    printf("檔案大小:%ld\r\n", stat_info.st_size);
    printf("檔案系統的I/O緩衝區大小:%ld\r\n", stat_info.st_blksize);
    printf("佔用檔案區塊的個數(每一區塊大小為512個位元組):%ld\r\n", stat_info.st_blocks);
    printf("檔案最近一次被存取或被執行的時間:%ld\r\n", stat_info.st_atime);
    printf("檔案最後一次被修改的時間:%ld\r\n", stat_info.st_mtime);
    printf("最近一次被更改的時間:%ld\r\n", stat_info.st_ctime);
    return 0;
}

mian.c在當前目錄下

 

4.6資料結構中常用函式

函式名 功能
bsearch 二分法搜尋
lfind/lsearch 線性搜尋,lsearch()找不到關鍵資料時會主動把改項資料加入數組裡
qsort 利用快速排序法排序陣列

qsort()函式:
標頭檔案:#include<stdlib.h>
void qsort(void* base,size_t n,size_t size,
            int(*compar)(const void*,const void*));
eg:qsort(base,n,sizeof(int),compar); //對陣列base[n]排序
利用快速排序法排列陣列
base指向要被搜尋的陣列的開頭地址
n代表陣列中元素數量
size為每一元素大小
compar為函式指標,資料相同時則返回0;不同時返回非0值。返回1時兩個資料交換,返回-1時兩個資料不交換.不可預設

 

exp1:輸入n,再輸入n個整數,qsort()對n個整數進行排序

#include<stdio.h>
#include<stdlib.h>
#define m 70
int compar (const void *a,const void *b){
	int *pa=(int *)a,*pb=(int*)b;
	if(*pa>*pb) return 1;
	if(*pa == *pb) return 0;
	if(*pa < *pb) return -1;
}
int main(){
	freopen("input.txt","r",stdin);
	int base[m],n;
	int i;
	printf("input n(n<50):");
	scanf("%d",&n);
	for (int i = 0; i < n; ++i)	{
		scanf("%d",&base[i]);
	}
	printf("\n排序前:\n");
	for (int i = 0; i < n; ++i)	{
		printf("%d ",base[i]);
		if(i!=0&&i%10==0) printf("\n");
	}
	qsort(base,n,sizeof(int),compar);//必須有compar 沒有會報錯 無預設比較函式
	printf("\n排序後:\n");
	for (int i = 0; i < n; ++i)	{
		printf("%d ",base[i]);
		if(i!=0&&i%10==0) printf("\n");
	}
	printf("\n");
	return 0;
}

input.txt

10
6 7 -9 89 72 -89 0 10 7890 -909887

 

字串查詢

lfind函式:
標頭檔案:#include<stdlib.h>
void *lfind(const void *key,const void *base,size_t *n,size_t size,int(* compar)(const void*,const void*));
函式功能:線性搜尋,在陣列中從頭至尾,一項項查詢資料
eg:lsearch(key,base,&n,size,compar);//char[] key;char[] base;int n;int size;
key:指向欲查詢的關鍵資料的指標
base:指向要被搜尋的陣列開頭的地址
n:陣列中元素的數量
size:每一個元素的大小
compar:函式指標,相同返回0,不同返回非0
lfind和lsearch的不同點在於,當找不到關鍵資料時lfind()僅僅會返回NULL,而不會主動把該資料加入陣列尾端。如果lsearch()找不到關鍵資料,會主動把該資料加入數組裡。

bsearch函式說明:
void *bsearch(const void* key,const void *base,size_t n,size_t size,int(*compar)(const void*,const void*));
利用二分搜尋法從排序好的陣列中查詢資料
key:指向欲查詢的關鍵資料的指標
base:指向要被搜尋的陣列開頭地址
n:陣列中元素數量
size:每一元素的大小
compar:函式指標,資料相同時返回0,不同時返回