程序實現很簡單,涉及到的只有兩個知識點。
1、文件最最基本的打開關閉;
2、系統時間的獲取。
代碼是在VS2019環境下編寫的,部分函數在其他編譯器中會無法識別。這個就只能需要自己去查找對應的函數簡單修改即可。
如果遇到問題,歡迎大家提出來一起討論。
文件操作:
先來介紹一下 文件操作 的基本方法。
操作文件必須遵從的過程是:打開,讀寫,關閉。
一個文件首先要知道的是 文件名,當然你也可以新建一個文件。
如果是不同路徑下的文件,還需要知道文件的路徑。為了方便,本文采用同一目錄下操作來說明。
只知道文件名並沒什么用處,重要的是要通過文件名得到 文件結構體 FILE 的變量,里面會保存文件的一些基本但重要的信息。然后通過它來進行下一步的讀寫。
先來看一下文件操作的簡單代碼示例,后面再介紹函數的功能。
1 #include <stdio.h> 2 3 int main(void) { 4 FILE* stream;// 文件指針 5 errno_t err;// 錯誤碼 6 char* filename = "file.txt";// 文件名 7 // 打開,以在文件末尾追加(append)數據的形式打開文件filename 8 err = fopen_s(&stream, filename, "a"); 9 if (err == 0) { 10 printf("文件 %s 打開成功\n", filename); 11 } else { 12 printf("文件 %s 打開失敗\n", filename); 13 } 14 // 讀寫 15 if (stream != NULL) { 16 // 向文件末尾追加一段文字。 17 fprintf(stream, "%s", "文件操作成功!\n"); 18 } 19 // 關閉 20 if (stream != NULL) { 21 // 關閉文件指針,先要判斷是否為空 22 err = fclose(stream); 23 if (err == 0) { 24 printf("文件 %s 關閉成功\n", filename); 25 } else { 26 printf("文件 %s 關閉失敗\n", filename); 27 } 28 } 29 }
打開文件用到的是 fopen_s 函數,函數語法如下:
errno_t fopen_s(
FILE** pFile, // 一個指向文件指針的指針,它將接收指向打開的文件的指針。
const char *filename, // 文件名
const char *mode // 文件打開的方式,方式有很多種,可參考上面的鏈接。
);
如果打開成功返回 0,否則返回相應的錯誤碼。
寫數據用到的函數是 fprintf,語法如下:
int fprintf(
FILE *stream, // 文件指針
const char *format [, // 格式控制字符串
argument ]... // 可選參數
);
類似 printf 函數,只不過多了個文件指針而已。很好理解。
返回值是寫入的字節數,通常用不到,可忽略。
當然,不止這一個函數可以寫操作,還有 fwrite 函數,fputs 函數等等。
關閉文件用的是 fclose 函數,語法如下:
int fclose(
FILE *stream // 文件指針
);
關閉成功,返回 0,錯誤返回 EOF。
有了上面這些知識,你就可以向文件寫入一個 Hello World 了。其實還有很多內容,但是如標題所示,現在要寫的是時間。是個字符串,只需要用到這些內容。其他的可參考 UCRT alphabetical function reference。
獲取時間:
現在來看看怎么獲取當前時間。直接上代碼,再說明函數語法(其實看注釋就夠了)。
#include <stdio.h>
#include <time.h>
int main(void) {
char timebuf[21];// 字符串形式保存時間
time_t ltime;// 時間戳
struct tm today;// 本地時間結構體
errno_t err;// 錯誤碼
time(<ime);// 獲取系統時間
err = _localtime64_s(&today, <ime);// 轉換為本地時間
if (err != 0) {
printf("無法轉換為本地時間\n");
exit(1);
}
// 將時間轉換為字符串,自定義格式
strftime(timebuf, 21, "%Y/%m/%d %T%n", &today);
printf(timebuf);
}
用到的函數有:time,_localtime64_s,strftime
time 語法如下:
time_t time( time_t *destTime ); // 獲取系統時間,參數是指向時間的存儲位置的指針
返回值是從 1970/01/01 00:00:00 以來經過的秒數。有錯誤返回 -1。
_localtime64_s 語法如下:
errno_t _localtime64_s(
struct tm* tmDest, // 指向要填充的時間結構體
__time64_t const* sourceTime // 指向時間的存儲位置的指針
); // 將時間轉換為本地時間結構體
轉換成功返回 0,否則返回對應的錯誤碼。
strftime 語法如下:
size_t strftime(
char *strDest, // 保存時間的字符串
size_t maxsize, // strDest指向的大小
const char *format, // 格式控制串,參照使用手冊。
const struct tm *timeptr // 時間結構體
);
返回填充的字符數,如果超過了 maxsize,返回 0。
到這里差不多就已經掌握了簡單的寫入時間操作。可以試試自己寫一寫。
不會也沒關系,下面的代碼是封裝好的。可以直接調用。
函數原型:
// 功能:向txt文件filename末尾追加格式為YYYY/MM/DD HH:MM:SS的時間
// filename是文件名,文件名本身不帶雙引號
void log_time_filename(char const* filename);
// 功能:向stream指向的文件末尾追加格式為YYYY/MM/DD HH:MM:SS的時間
// stream必須打開
void log_time_stream(FILE* stream); // 參數是文件指針
// 功能:向txt文件filename末尾追加格式為YYYY/MM/DD HH:MM:SS的時間並換行
// filename是文件名,文件名本身不帶雙引號
void log_time_line_filename(char const* filename);
// 功能:向stream指向的文件末尾追加格式為YYYY/MM/DD HH:MM:SS的時間並換行
// stream必須打開
void log_time_line_stream(FILE* stream);
log.h文件:
將代碼保存到與 調用文件 在同一級目錄下的 log.h 文件中。有四個外部函數可供調用。
/********************************************************************* 文件: log.h 環境: Windows 10 IDE: Visual Studio 2019 版本: 1.5.0.1910 功能: 1、向 <文件名.txt> 文件末尾追加當前系統時間 2、向 <FILE* stream> 指向的文件末尾追加當前系統時間 備注: 1、目前只有默認日期格式,即YYYY/MM/DD hh:mm:ss 2、支持換行和不換行兩種形式 日期: 2019年10月16日15:42:15 作者: wowpH *********************************************************************/
#pragma once
#pragma message("log.h - wowpH - 1.5.0.1910")
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// 時間格式的最大長度
#define MAX_TIME_MODE_SIZE 21
//
// 可調用的函數
//
// 通過文件名追加時間
void log_time_filename(char const* filename);
// 通過文件指針追加時間
void log_time_stream(FILE* stream);
// 通過文件名追加時間,換行
void log_time_line_filename(char const* filename);
// 通過文件指針追加時間,換行
void log_time_line_stream(FILE* stream);
//
// 供內部使用的函數,外部調用可能出錯
//
// 向strDest寫入當前時間
void get_local_time(char* strDest);
// 打開文件
void open_file(FILE** stream, char const* filename);
// 關閉文件
void close_file(FILE* stream);
log.c文件:
將代碼保存到與 調用文件 同一級目錄下的 log.c 文件中。
#include "log.h"
const char* null_stream = "文件指針為空,請先打開一個文件!";
const char* error_open = "文件打開失敗!";
const char* error_close = "文件關閉失敗!";
const char* error_to_localtime = "無法轉換為本地時間!";
void log_time_filename(char const* filename) {
FILE* stream = NULL;
open_file(&stream, filename);
log_time_stream(stream);
close_file(stream);
}
void log_time_stream(FILE* const stream) {
if (stream != NULL) {
char time[MAX_TIME_MODE_SIZE];
get_local_time(time);
fprintf(stream, "%s", time);
} else {
printf("%s\n", null_stream);
exit(-1);
}
}
void log_time_line_filename(char const* filename) {
FILE* stream = NULL;
open_file(&stream, filename);
log_time_line_stream(stream);
close_file(stream);
}
void log_time_line_stream(FILE* stream) {
log_time_stream(stream);
fprintf(stream, "\n");
}
static void get_local_time(char* strDest) {
time_t ltime;
time(<ime);
struct tm today;
errno_t err;
err = _localtime64_s(&today, <ime);
if (err != 0) {
printf("%s\n", error_to_localtime);
exit(-1);
}
// 將時間轉換為字符串,自定義格式
strftime(strDest, MAX_TIME_MODE_SIZE, "%Y/%m/%d %T", &today);
}
static void open_file(FILE** stream, char const* filename) {
errno_t err = 0;
err = fopen_s(stream, filename, "a");
if (err != 0) {
printf("%s\n", error_open);
exit(-1);
}
}
static void close_file(FILE* stream) {
if (stream != NULL) {
errno_t err = 0;
err = fclose(stream);
if (err != 0) {
printf("%s\n", error_close);
exit(-1);
}
}
}