尝试从命令行获取时间并将其存储在 struct timespec 变量中

问题描述

我试图从命令行以纪元格式输入时间,我想将其存储在 struct timespec 变量中。

我能够存储它并以某种方式打印它,但是当我向 timespec 变量添加一些东西时,它给出了奇怪的东西

这是代码

#include <time.h>
#include <stdio.h>
#include <stdlib.h>



int main (int argc,char *argv[]){

    struct timespec InputTime;

    InputTime.tv_sec = (time_t)argv[1]; //(__time_t)
    InputTime.tv_nsec = (long)argv[2]; //(__syscall_slong_t)

    printf("The time before %s,%s\n",InputTime.tv_sec,InputTime.tv_nsec);

    InputTime.tv_sec += 3;
    InputTime.tv_nsec += 3;

    printf("The time after %s,InputTime.tv_nsec);

    return 0;

}

这是输入和输出

INPUT

./InputTime 1615578864 438734073

OUTPUT


The time before 140733952311809,140733952311820
The time after 140733952311812,140733952311823

我尝试将其他变量类型用于 *argv[] 并尝试使用 %s 进行打印输出但是之前的时间给了我正确的输入但之后的时间给了我一些奇怪的例子当我将 %ld 更改为 %s 时的输出。此外,当我这样做时,编译器会给出一些警告,因为我没有使用正确的格式

./InputTime 1615578864 438734073
The time before 1615578864,438734073
The time after 5578864,734073

我正在使用这个 gcc 版本

gcc --version
gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
copyright (C) 2019 Free Software Foundation,Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or fitness FOR A PARTIculaR PURPOSE.

解决方法

继续我上面的评论。任何时候您读取 C 中的文本输入(与文件中的二进制输入相反),您读取的是字符而不是数值。当用户输入一个数字时,它是一串数字,而不是一个数值。程序员可以使用提供完整错误检测的 strtol() 系列函数执行从数字字符串到数值的转换,或者至少使用 sscanf()从成功/失败的角度验证转换。

在您的情况下,您可以简单地使用 strtoul() 为输入值提供最大范围。您只需使用 argv[1]argv[2]strtoul() 转换为数值。最低验证将是,例如

    errno = 0;  /* set errno zero before conversion */
    InputTime.tv_sec = strtoul (argv[1],&endptr,0);   /* convert w/strtoul */
    if (endptr == argv[1] && InputTime.tv_sec == 0) {   /* validate digits converted */
        fputs ("error: no digits converted.\n",stderr);
        return 1;
    }
    else if (errno) {   /* validate no overflow in conversion */
        fputs ("error: overflow in conversion.\n",stderr);
        return 1;
    }

在通过两次验证(数字已转换且转换期间未发生错误)后,您可以确信您的 struct timespec 包含有效输入(您还可以进一步检查转换后的数字是否在可接受的范围内)使用前范围)

如果你把它放在一起,你可以做如下的事情:

#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

int main (int argc,char *argv[]) {

    struct timespec InputTime;
    char *endptr;
    
    if (argc < 3) {
        fputs ("error: insufficient arguments\n"
            "usage: ./progrm seconds nanoseconds\n",stderr);
        return 1;
    }
    
    errno = 0;  /* set errno zero before conversion */
    InputTime.tv_sec = strtoul (argv[1],stderr);
        return 1;
    }
    
    errno = 0;  /* set errno zero before conversion */
    InputTime.tv_nsec = strtoul (argv[2],0);   /* convert w/strtoul */
    if (endptr == argv[2] && InputTime.tv_nsec == 0) {   /* validate digits converted */
        fputs ("error: no digits converted.\n",stderr);
        return 1;
    }

    printf ("The time before %lu,%09lu\n",InputTime.tv_sec,InputTime.tv_nsec);

    InputTime.tv_sec += 3;
    InputTime.tv_nsec += 3;

    printf ("The time after  %lu,InputTime.tv_nsec);
}

注意:包含 errno.h 标头)

示例使用/输出

$ ./bin/inputtime_strtol 1615578864 438734073
The time before 1615578864,438734073
The time after  1615578867,438734076

检查一下,如果您还有其他问题,请告诉我。