0%

时间字符串格式相互转换——C语言实现

简介

最近在写程序的时候,需要解析字符串中的时间数据,讲一讲之前我是怎么处理的,例如:CCLK:2021-05-11 12:24:30这串数据,首先我会截取冒号后边的时间数据,然后使用atoi函数再利用指针偏移逐个解析年月日时分秒,这样做也很简单,但是这样使用于格式固定的时间格式的数据,比如必须为xxxx-xx-xx xx:xx:xx,一旦少一个字符解析出的时间就会出错。当然有的人会根据分割符去截取数据,这样做也是可以的,今天我们使用一种类似于正则表达解析的方法,在单片机中使用正则表达式几乎是不可能实现的,那么我们应该怎么操作呢,这就要提到sscanf函数了。

sscanf()介绍

描述

sscanf隶属于stdio.h标准库

C 库函数 int sscanf(const char str, const char format, …) 从字符串读取格式化输入。

声明

下面是 sscanf() 函数的声明。

1
int sscanf(const char *str, const char *format, ...)

参数

  • str — 这是 C 字符串,是函数检索数据的源。
  • format — 这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。
    format 说明符形式为[=%[*][width][modifiers]type=],具体讲解如下:
参数 描述
* 这是一个可选的星号,表示数据是从流 stream 中读取的,但是可以被忽视,即它不存储在对应的参数中。
width 这指定了在当前读取操作中读取的最大字符数。
modifiers 为对应的附加参数所指向的数据指定一个不同于整型(针对 d、i 和 n)、无符号整型(针对 o、u 和 x)或浮点型(针对 e、f 和 g)的大小: h :短整型(针对 d、i 和 n),或无符号短整型(针对 o、u 和 x) l :长整型(针对 d、i 和 n),或无符号长整型(针对 o、u 和 x),或双精度型(针对 e、f 和 g) L :长双精度型(针对 e、f 和 g)
type 一个字符,指定了要被读取的数据类型以及数据读取方式。具体参见下一个表格。

sscanf 类型说明符:

类型 合格的输入 参数的类型
c 单个字符:读取下一个字符。如果指定了一个不为 1 的宽度 width,函数会读取 width 个字符,并通过参数传递,把它们存储在数组中连续位置。在末尾不会追加空字符。 char *
d 十进制整数:数字前面的 + 或 - 号是可选的。 int *
e,E,f,g,G 浮点数:包含了一个小数点、一个可选的前置符号 + 或 -、一个可选的后置字符 e 或 E,以及一个十进制数字。两个有效的实例 -732.103 和 7.12e4 float *
o 八进制整数。 int *
s 字符串。这将读取连续字符,直到遇到一个空格字符(空格字符可以是空白、换行和制表符)。 char *
u 无符号的十进制整数。 unsigned int *
x,X 十六进制整数。 int *
  • 附加参数 — 这个函数接受一系列的指针作为附加参数,每一个指针都指向一个对象,对象类型由 format 字符串中相应的 % 标签指定,参数与 % 标签的顺序相同。
    针对检索数据的 format 字符串中的每个 format 说明符,应指定一个附加参数。如果您想要把 sscanf 操作的结果存储在一个普通的变量中,您应该在标识符前放置引用运算符(&),例如:

    int n;
    sscanf (str,”%d”,&n);

    返回值

    如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。

time()介绍

描述

C 库函数 time_t time(time_t *seconds) 返回自纪元 Epoch(1970-01-01 00:00:00 UTC)起经过的时间,以秒为单位。如果 seconds 不为空,则返回值也存储在变量 seconds 中。

声明

下面是 time() 函数的声明。

1
time_t time(time_t *seconds)

参数

  • seconds — 这是指向类型为 time_t 的对象的指针,用来存储 seconds 的值。

返回值

以 time_t 对象返回当前日历时间。

localtime()介绍

描述

C 库函数 struct tm *localtime(const time_t *timer) 使用 timer 的值来填充 tm 结构。timer 的值被分解为 tm 结构,并用本地时区表示。

声明

下面是 localtime() 函数的声明。

1
struct tm *localtime(const time_t *timer)

参数

  • timer — 这是指向表示日历时间的 time_t 值的指针。

返回值

该函数返回指向 tm 结构的指针,该结构带有被填充的时间信息。下面是 tm 结构的细节:

1
2
3
4
5
6
7
8
9
10
11
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
int tm_min; /* 分,范围从 0 到 59 */
int tm_hour; /* 小时,范围从 0 到 23 */
int tm_mday; /* 一月中的第几天,范围从 1 到 31 */
int tm_mon; /* 月份,范围从 0 到 11 */
int tm_year; /* 自 1900 起的年数 */
int tm_wday; /* 一周中的第几天,范围从 0 到 6 */
int tm_yday; /* 一年中的第几天,范围从 0 到 365 */
int tm_isdst; /* 夏令时 */
};

strftime()函数

描述

C 库函数size_t strftime(char str, size_t maxsize, const char format, const struct tm *timeptr) 根据 format 中定义的格式化规则,格式化结构 timeptr 表示的时间,并把它存储在 str 中。

声明

下面是 strftime() 函数的声明。

1
size_t strftime(char *str, size_t maxsize, const char *format, const struct tm *timeptr)

参数

str — 这是指向目标数组的指针,用来复制产生的 C 字符串。
maxsize — 这是被复制到 str 的最大字符数。
format — 这是 C 字符串,包含了普通字符和特殊格式说明符的任何组合。这些格式说明符由函数替换为表示 tm 中所指定时间的相对应值。格式说明符是:

说明符 介绍 实例
%a 缩写的星期几名称 Sun
%A 完整的星期几名称 Sunday
%b 缩写的月份名称 Mar
%B 完整的月份名称 March
%c 日期和时间表示法 Sun Aug 19 02:56:02 2012
%d 一月中的第几天(01-31) 19
%H 24 小时格式的小时(00-23) 14
%I 12 小时格式的小时(01-12) 05
%j 一年中的第几天(001-366) 231
%m 十进制数表示的月份(01-12) 08
%M 分(00-59) 55
%p AM 或 PM 名称 PM
%S 秒(00-61) 02
%U 一年中的第几周,以第一个星期日作为第一周的第一天(00-53) 33
%w 十进制数表示的星期几,星期日表示为 0(0-6) 4
%W 一年中的第几周,以第一个星期一作为第一周的第一天(00-53) 34
%x 日期表示法 08/19/12
%X 时间表示法 02:50:06
%y 年份,最后两个数字(00-99) 01
%Y 年份 2012
%Z 时区的名称或缩写 CDT
%% 一个 % 符号 %
  • timeptr — 这是指向 tm 结构的指针,该结构包含了一个呗分解为以下各部分的日历时间:
1
2
3
4
5
6
7
8
9
10
11
struct tm {
int tm_sec; /* 秒,范围从 0 到 59 */
int tm_min; /* 分,范围从 0 到 59 */
int tm_hour; /* 小时,范围从 0 到 23 */
int tm_mday; /* 一月中的第几天,范围从 1 到 31 */
int tm_mon; /* 月份,范围从 0 到 11 */
int tm_year; /* 自 1900 起的年数 */
int tm_wday; /* 一周中的第几天,范围从 0 到 6 */
int tm_yday; /* 一年中的第几天,范围从 0 到 365 */
int tm_isdst; /* 夏令时 */
};

返回值

如果产生的 C 字符串小于 size 个字符(包括空结束字符),则会返回复制到 str 中的字符总数(不包括空结束字符),否则返回零。

综合示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
#include <stdio.h>
#include <time.h>
#include <string.h>

/* 字符串转换为时间*/
void test()
{
int year, month, day, hour, minute,second;
char time[] = {"2021-05-11 12:24:30"};

sscanf(time, "%d-%d-%d %d:%d:%d", &year, &month, &day, &hour, &minute, &second);
printf("year: %d\n",year);
printf("month: %d\n",month);
printf("day: %d\n",day);
printf("hour: %d\n",hour);
printf("minute: %d\n",minute);
printf("second: %d\n",second);
}
/*时间格式数据转换为字符串*/
void ToStrTime(void)
{
char buffer[80];
time_t nowTime;
time(&nowTime);//获取系统时间,得到一个长整型数据
printf("\r\n%d\n",nowTime);
strftime(buffer,sizeof(buffer),"%Y-%m-%d %H:%M:%S",localtime(&nowTime));//转换为年月日形式,并格式化输出

printf("%s\n",buffer);
}

int main ()
{
test();
ToStrTime();
return 0;
}

示例效果

1.png

结尾

如果有疑问或者需要了解更多,请在下边评论或者进交流群讨论