0

我正在尝试学习结构和函数并使其更有趣,我有一个任务要求我创建一个程序来扫描两个时间戳并计算它们之间的差异。

我已经担心在午夜计算时间戳时代码会是什么样子......

无论如何,我将使用函数calculateTimeToDiff()来计算时间戳之间的差异。该函数将有两个参数,第一个时间戳和第二个时间戳。它将返回两个 tiemstamp 之间的差异。

问题 1

我真的很好奇为什么我不能用两个冒号作为分隔符来扫描值:

scanf("%d::%d::%d", &time.hours, &time.minutes, &time.seconds);

我必须这样输入(这是正确的输入方式):

scanf("%d:%d:%d", &time.hours, &time.minutes, &time.seconds);

这就是我计划制作程序的方式,但我相信你会生气并说我不应该这样做,因为blabla。由于我几乎不了解结构和函数,请解释一下我应该怎么做,就像我五岁一样:

#include <stdio.h>

int calculateTimeDiff(int time1, int time2)
{
    int difference = time1 - time2;

    return difference;
}

int main(void)
{
    typedef struct
    {
        int hours;
        int minutes;
        int seconds; 
    } Time;

    Time firstTime;
    Time secondTime;

    printf("Time #1: ");
    scanf("%d:%d:%d", &firstTime.hours, &firstTime.minutes, &firstTime.seconds);

    printf("Time #2: ");
    scanf("%d:%d:%d", &secondTime.hours, &secondTime.minutes, &secondTime.seconds);

    // I understand that it will not work to separate the variables with a comma, but I am kind of stuck here
    int firstFullTime   =   firstTime.hours, firstTime.minutes, firstTime.seconds;
    int secondFullTime  =   secondTime.hours, secondTime.minutes, secondTime.seconds;

    calculateTimeDiff(firstFullTime, secondFullTime);

    return 0;
}
4

3 回答 3

1

我会采取不同的方法:

  1. 对于两个时间戳,都使用fgets()将它们分别读入一个“字符串”。

  2. 用于strptime()将“字符串”转换为struct tms。

  3. 用于从smktime()创建s。time_tstruct tm

  4. 然后最后用difftime()秒来计算差异。

于 2013-11-10T15:29:13.650 回答
0

对您的代码进行初步破解可能会产生:

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

typedef struct
{
    int hours;
    int minutes;
    int seconds; 
} Time;

static void err_exit(char const *msg)
{
    fprintf(stderr, "%s\n", msg);
    exit(1);
}

static int calculateTimeDiff(int time1, int time2)
{
    int difference = time1 - time2;
    return difference;
}

static void print_time(char const *pre, Time t, char const *post)
{
    printf("%s%2d:%.2d:%.2d%s", pre, t.hours, t.minutes, t.seconds, post);
}

int main(void)
{
    Time t1;
    Time t2;

    printf("Time #1: ");
    if (scanf("%d:%d:%d", &t1.hours, &t1.minutes, &t1.seconds) != 3)
        err_exit("Failed to read time value");

    printf("Time #2: ");
    if (scanf("%d:%d:%d", &t2.hours, &t2.minutes, &t2.seconds) != 3)
        err_exit("Failed to read time value");

    int s1 = (t1.hours * 60 + t1.minutes) * 60 + t1.seconds;
    int s2 = (t2.hours * 60 + t2.minutes) * 60 + t2.seconds;

    print_time("T1 = ", t1, "; ");
    print_time("T2 = ", t2, "; ");
    printf("Difference in seconds (T1-T2): %d\n", calculateTimeDiff(s1, s2));

    return 0;
}

运行示例:

Time #1: 1:0:1  
Time #2: 0:59:59
T1 =  1:00:01; T2 =  0:59:59; Difference in seconds (T1-T2): 2

OP 反击:

请!我说我是结构和函数的新手,你知道我[不]知道你的一半代码是什么意思吗?不要误会我的意思,我很高兴得到专业人士的帮助,但你要明白,这对我一点帮助都没有。只会让我更加困惑!

上面的代码是对现有代码的一个非常小的修改。下面“带有输入验证的代码”部分中的代码稍微复杂一些;你可以暂时忽略它(但到周末你应该可以理解它;它并不复杂,虽然它在使用函数以避免重复方面是无情的)。

剖析上面的代码:

  1. 结构类型的定义被移到外面,main()以便其他函数也可以使用该类型。
  2. 该函数err_exit接受一个字符串参数 ( char const *msg) 并在标准错误(这是报告错误消息的正确文件流)上打印它,然后退出程序。退出值 0 表示成功;1 是常见的“出现问题”退出状态。你可以使用EXIT_SUCCESSEXIT_FAILURE如果你愿意的话;它们被定义<stdlib.h>为与exit()函数一起使用。编写此函数意味着我可以使用单个函数调用报告代码中的错误,而不必每次都编写 3 或 4 行代码(取决于您的格式偏好)。使用函数是一种节省劳动力的技术。它也有首字母缩写词 DRY:不要重复自己。关键字static对你来说并不重要——它让我的编译器对我用来防止我犯愚蠢错误的选项感到满意。如果您愿意,我们可以稍后单独讨论这个问题。
  3. 该功能calculateTimeDiff()是您的功能逐字。给定两个整数值,它返回它们之间的差。
  4. 该函数print_time(char const *pre, Time t, char const *post)接受三个参数。用于告诉编译器该const函数不会尝试修改字符串;你可以放弃这个词const而不会产生任何重大的不良影响。中间参数是您的Time结构之一,因此该函数在堆栈上获取结构的副本。然后代码调用printf()以打印前缀字符串pre,结构中的 3 个数字Time(%2d意味着打印 2 位数字或空格和 1 位数字 — 到足够好的近似值;%.2d意味着始终打印 2 位数字,必要时使用前导 0 填充),以及 . 中的后缀字符串post。这是一种格式化时间值的简单方法。
  5. 说到main()函数, and 的声明t1t2你的firstTimeand一样secondTime,但是我拒绝写这么长的名字。
  6. 和你的printf()一样。
  7. 呼叫scanf()与您的呼叫相同,只是名称t1代替了firstTime。它包含在一条if语句中以检查读取操作是否成功。如果用户输入了格式错误的输入(可能是1::0::0),则scanf()不会返回 3;它将为示例输入返回 1。如果用户键入midnight,则返回 0。如果用户指定 EOF(Control-D在 Unix 或Control-ZWindows 上键入),则scanf()返回 EOF。
  8. 如果scanf()不成功,则err_exit()调用该函数报告问题并退出程序。
  9. 下一段代码本质上等同于第 6-8 点中讨论的代码,使用t2(而不是secondTime)。
  10. 接下来的两行使用名称s1ands2代替您的firstFullTimeand secondFullTime。每行根据您的一个结构中的值计算以秒为单位的时间。一小时有60分钟,一分钟有60秒。 (t1.hours * 60 + t1.minutes)给出由hh:mm值表示的分钟数. 当它乘以 60 并添加秒时,结果是自午夜以来的秒数,由用户键入的hh:mm:ss值表示。
  11. 下一段代码使用print_time()上面创建的函数来打印t1and中的值t2;打印你得到的输入是非常宝贵的,这样你就知道计算机得到了什么。大多数情况下,它与您认为计算机得到的相同,但是当出现问题时,检查您和计算机的想法是否相同很重要。在它们之间,这两个调用会生成输出,例如T1 = 1:00:01; T2 = 0:59:59;(第二个分号后有一个空格)。如果我希望输出分布在两行上,我可以将"; "参数替换为"\n".
  12. 最后一行calculateTimeDiff()使用从两个结构计算的两个整数值调用您的函数,然后使用printf(). '1 小时 1 秒' 和 '59 分 59 秒' 之间有 2 秒,因此该calculateTimeDiff()功能正常工作。程序退出return 0;from main(),表示成功。

这段代码真的没有什么复杂的。最难的部分是scanf(),你写的——我只是添加了错误检查以确保它有效。解释远比代码难。我故意忽略了对可行但不必要的代码可能变化的描述。


带有输入验证的代码

OP 应该暂时忽略这个答案的其余部分。

然后你可能会验证一些输入:

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

typedef struct
{
    int hours;
    int minutes;
    int seconds; 
} Time;

static int calculateTimeDiff(int time1, int time2)
{
    int difference = time1 - time2;
    return difference;
}

static inline int time_to_seconds(Time t)
{
    return (t.hours * 60 + t.minutes) * 60 + t.seconds;
}

static inline Time seconds_to_time(int s)
{
    Time t;
    t.hours = s / 3600;
    t.minutes = (s / 60) % 60;
    t.seconds = s % 60;
    return t;
}

static void print_time(char const *pre, Time t, char const *post)
{
    printf("%s%2d:%.2d:%.2d%s", pre, t.hours, t.minutes, t.seconds, post);
}

static int get_time(char const *prompt, Time *t)
{
    int rc = -1;    // Assume failure
    printf(prompt);
    if (scanf("%d:%d:%d", &t->hours, &t->minutes, &t->seconds) != 3)
        fprintf(stderr, "Failed to read time value in format hh:mm:ss\n");
    else if (t->seconds < 0 || t->seconds > 59)
        fprintf(stderr, "Seconds value %d is not in range 0..59\n", t->seconds);
    else if (t->minutes < 0 || t->minutes > 59)
        fprintf(stderr, "Minutes value %d is not in range 0..59\n", t->minutes);
    else if (t->hours < 0 || t->hours > 24)
        fprintf(stderr, "Hours value %d is not in range 0..24\n", t->hours);
    else if (t->hours == 24 && (t->seconds != 0 || t->minutes != 0))
        fprintf(stderr, "Maximum time value is 24:00:00 (you gave %2d:%.2d:%.2d)\n",
                 t->hours, t->minutes, t->seconds);
    else
        rc = 0; // All OK

    return rc;
}

int main(void)
{
    Time t1;
    Time t2;

    if (get_time("Time #1: ", &t1) != 0 ||
        get_time("Time #2: ", &t2) != 0)
        exit(1);

    int s1 = time_to_seconds(t1);
    int s2 = time_to_seconds(t2);

    print_time("T1 = ", t1, "\n");
    print_time("T2 = ", t2, "\n");
    printf("Delta (T1-T2) = %d seconds\n", calculateTimeDiff(s1, s2));
    print_time("Delta = ", seconds_to_time(calculateTimeDiff(s1, s2)), "\n");

    return 0;
}

示例运行(程序名称dt):

$ dt
Time #1: 24:00:01
Maximum time value is 24:00:00 (you gave 24:00:01)
$ dt
Time #1: -1:0:0
Hours value -1 is not in range 0..24
$ dt
Time #1: 0:-1:0
Minutes value -1 is not in range 0..59
$ dt
Time #1: 0:-1:-1
Seconds value -1 is not in range 0..59
$ dt
Time #1: 25:00:00
Hours value 25 is not in range 0..24
$ dt
Time #1: 23:60:00
Minutes value 60 is not in range 0..59
$ dt
Time #1: 23:59:60
Seconds value 60 is not in range 0..59
$ dt
Time #1: 24:01:00
Maximum time value is 24:00:00 (you gave 24:01:00)
$ dt
Time #1: 24:00:01
Maximum time value is 24:00:00 (you gave 24:00:01)
$ dt
Time #1: 24:00:00
Time #2: 0:0:0
T1 = 24:00:00
T2 =  0:00:00
Delta (T1-T2) = 86400 seconds
Delta = 24:00:00
$

到目前为止,一切都很好:

$ dt
Time #1: 0:0:0
Time #2: 23:59:59
T1 =  0:00:00
T2 = 23:59:59
Delta (T1-T2) = -86399 seconds
Delta = -23:-59:-59
$

突然间,我们进入了棘手的领域。在处理带符号的分段数字时(例如这里的分段是小时、分钟、秒),您需要将符号与组件值分开。我不打算解决这个问题。

于 2013-11-10T16:24:10.173 回答
0

解释

scanf 从标准输入读取数据并根据参数格式将它们存储到附加参数指向的位置

没有必要放置任何分隔符(如“:”)。如果您想使用 printf 函数打印它,那将是合适的。

我修复了 calculateTimeDiff 函数。您需要在此处传递 Time 对象,如果您想检查时间戳之间的确切差异,它必须返回 Time 对象。

下面的代码已被删除,在函数 calculateTimeDiff 修改后根本不需要(显然,该代码是错误的)。

int firstFullTime   =   firstTime.hours, firstTime.minutes, firstTime.seconds;
int secondFullTime  =   secondTime.hours, secondTime.minutes, secondTime.seconds;

为什么 calculateTimeDiff 返回时间?您需要知道这两个时间戳之间的确切时间差,对吗?使用 Time 对象,您可以检查精确的差异(小时、分钟、秒)。我不知道如何使用单个整数来完成它。

尽管如此,代码将无法正常工作,例如 10 秒 ( time2) 减去 30 秒 ( time1) 结果将是 -20 秒。如果你想制作自己的结构,你必须考虑到这种情况。alk 向我们展示了 tm 结构,您可以根据需要使用它们。

代码

#include <stdio.h>

typedef struct
{
  int hours;
  int minutes;
  int seconds; 
} Time;

Time calculateTimeDiff(Time time1, Time time2)
{
    Time result;
    result.hours = time2.hours - time1.hours;
    result.minutes = time2.minutes - time1.minutes;
    result.seconds = time2.seconds - time1.seconds;

    return result;
}

int main(void)
{

    Time firstTime;
    Time secondTime;

    printf("Time #1: ");
    scanf_s("%d\:\:%d\:\:%d", &firstTime.hours, &firstTime.minutes, &firstTime.seconds);

    printf("Time #2: ");
    scanf_s("%d\:\:%d\:\:%d", &secondTime.hours, &secondTime.minutes, &secondTime.seconds);

    Time result = calculateTimeDiff(firstTime, secondTime);

    return 0;
}
于 2013-11-10T15:23:16.517 回答