C实现 每隔1s向time.txt文件输出系统时间(C I/O函数)

平台:x86/Debian Linux/gcc

1 题目

编程读写一个文件test.txt,每隔1s向文件中写入一行记录,类似于这样:

1 2009-7-30 15:16:42

2 2009-7-30 15:16:43

该程序应该是无限循环,直到按Ctrl + C终止。下次再启动程序时再test.txt文件末尾追加记录,并且序号能够持续上次的序号,比如:

1 2009-7-30 15:16:42

2 2009-7-30 15:16:43

3 2009-7-30 15:19:02

4 2009-7-30 15:19:03

5 2009-7-30 15:19:04

2 编程实现

(1) C代码

  1. /* Filename:    out_date_and_time.c 
  2.  * Brife:   Output date and time to time.txt one by one second 
  3.  * Date:    2014.8.7 Thursday 
  4.  * Author:  One fish 
  5.  */  
  6. #include <time.h>  
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9. #include <string.h>  
  10.   
  11.   
  12.   
  13. //------------Maro------------------  
  14. #define EPOCH_YEAR  1900  
  15. #define EPOCH_MONTH 1  
  16. #define EPOCH_DAY   1  
  17. #define OUT_FILE    "time.txt"  
  18.   
  19.   
  20.   
  21. //------------Function decalre-------  
  22. void get_localtime(unsigned long int file_num);  
  23. unsigned long int find_file_end(const char *file);  
  24.   
  25.   
  26.   
  27. //----------Golbal varibles----------  
  28. FILE *fp = NULL;  
  29.   
  30.   
  31.   
  32.   
  33. int main(void)  
  34. {  
  35.     unsigned long int file_num = 0;  
  36.   
  37.     file_num    = find_file_end(OUT_FILE);        
  38.     printf("line number: %d\n", file_num);  
  39.       
  40.     while( 1 ){  
  41.         get_localtime( file_num + 1 );  
  42.         sleep(1);  
  43.     }  
  44.     return 0;  
  45. }  
  46.   
  47.   
  48.   
  49.   
  50. /*@Brife:   Open file and find file end line number 
  51.  *@Arg:     file is the opened file 
  52.  *@Rel:     Return the file number 
  53.  */  
  54. unsigned long int find_file_end(const char *file)  
  55. {  
  56.     char buf[30];  
  57.     int file_num = 0;  
  58.   
  59.     fp  = fopen(file, "a+");  
  60.     if(NULL != fp){  
  61.           
  62.         //File is empty  
  63.         if( NULL == fgets(buf, 30, fp) )  
  64.             return 0;  
  65.           
  66.         //Move fp to the start of the last line of the file  
  67.         fseek(fp, -strlen(buf), SEEK_END);  
  68.         fgets(buf, 30, fp);  
  69.       
  70.         //Or line number bigger than long long int scope  
  71.         if(1 != sscanf(buf, "%d", &file_num) ){  
  72.             printf("*.txt format is not correct\n");  
  73.             return 0;  
  74.         }  
  75.   
  76.         return file_num;  
  77.     }else{  
  78.         printf("Open %s failed\n", OUT_FILE);  
  79.     }  
  80. }  
  81.   
  82.   
  83.   
  84. /*@Brife:   Get current date and output to time.txt 
  85.  *      Should be called after find_file_end() 
  86.  *@Arg:     File_num, the line number should be printed 
  87.  */  
  88. void get_localtime(unsigned long int file_num)  
  89. {  
  90.   
  91.     time_t *t = NULL;  
  92.     static unsigned long int num = 0;  
  93.     if(num <= file_num){  
  94.         num = file_num;  
  95.     }  
  96.   
  97.     t   = (time_t *)malloc(sizeof(time_t));  
  98.   
  99.     if(NULL != t){  
  100.         struct tm *ptm = NULL;  
  101.           
  102.         //Get the time as the number of seconds since the Epoch, 1970-01-01 00:00 + 0000(UTC)  
  103.         //Translate calendar time to broken-down time  
  104.         time(t);  
  105.         ptm = localtime(t);  
  106.           
  107.         if(NULL != fp){  
  108.             fprintf(fp, "%d %d-%d-%d\t", num, EPOCH_YEAR + ptm->tm_year, EPOCH_MONTH + ptm->tm_mon, EPOCH_MONTH + ptm->tm_mday);  
  109.             fprintf(fp, "%d:%d:%d\n", ptm->tm_hour, ptm->tm_min, ptm->tm_sec);  
  110.             fflush(fp);  
  111.             ++num;  
  112.         }else{  
  113.             printf("%s Not found\n", OUT_FILE);  
  114.         }  
  115.     }  
  116.     free(t);  
  117. }  

(2) 运行结果

编译程序:gcc  -o  out_date_and_time  out_date_and_time.c

第一次运行程序一小会后按Ctrl + C终止程序,隔一小会再运行程序。time.txt文件内容如下:

1 2014-8-9    14:40:41

2 2014-8-9    14:40:42

3 2014-8-9    14:40:43

4 2014-8-9    14:40:44

5 2014-8-9    14:40:48

6 2014-8-9    14:40:49

7 2014-8-9    14:40:50

3 man page + 验证

(1) fgets()

原型:char *fgets(char *s, int size, FILE *stream) 

用户定义的缓冲区s的sizeof(s)要大于等于size,如果小于size则在fgets读到size-1字符给s后会继续添加一个’\0’字符。使缓冲区s的使用越界。

fgets读一个新建的文件返回NULL。fgets读一个用”backspace”退隔调所有内容的文件,输出fgets的返回值是一个换行。 

(2) fseek()

原型:int fseek(FILE  *stream, long  offset, int  whence)

对以下两个不同文件内容:

 

Figure1.文件1

 

Figure2.文件2

文件1只有1行数据(1 2014-8-9 15:15:55)并手动输入回车跳到文件1的第二行。文件2的每行内容是由fprintf输出的,行尾带回车。文件1和文件2每行数据长度相同为len,使fp指向文件1时,fseek(fp, -len, SEEK_END)时fp指向1后面的空格。fp指向文件2时,用fseek(fp, -len,SEEK_END)时fp指向第七行(黄色数字为行号)的数字7。

(3) time()和localtime()

用以上代码中time()和localtime()联用,由后者返回struct tm后,加上起始时间后tm_mday比实际时间多一天。

(4) fflush()

原型:fflush(FILE *stream)

因为fprintf属C标准库I/O库函数,stream指向的文件属常规文件(标准输入输出可能为行缓冲),其缓冲类型为全缓冲类型。故而在缓冲区满或程序正常结束前fprintf输出的内容全在缓冲区,在缓冲区未满时按Ctrl + C 后exit()函数没有得到运行,没有得到flush操作,故而stream指向的文件中无内容输出。所以要在每个fprintf函数后面添加ffush()函数,强制进入内核将内容输出到文件中。

永不止步步 发表于04-18 15:48 浏览65535次
分享到:

已有0条评论

暂时还没有回复哟,快来抢沙发吧

添加一条新评论

只有登录用户才能评论,请先登录注册哦!

话题作者

永不止步步
金币:67410个|学分:308317个
立即注册
畅学电子网,带你进入电子开发学习世界
专业电子工程技术学习交流社区,加入畅学一起充电加油吧!

x

畅学电子网订阅号