我正在尝试学习结构和函数并使其更有趣我有一个任务要求我创建一个扫描两个时间戳并计算它们之间差异的程序。
我已经担心在午夜计算时间戳时代码会是什么样子......
无论如何,我将使用函数 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;
}
答案 0 :(得分:0)
<强>解释强>
scanf从stdin读取数据并根据参数存储它们 格式化为附加参数
指向的位置
没有点放置任何分隔符(如':')。如果你想使用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向我们展示了你可以使用的结构。
<强>代码强>
#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;
}
答案 1 :(得分:0)
我采取不同的方法:
对于这两个时间戳,请使用fgets()
将它们分别读入“字符串”。
使用strptime()
将“字符串”转换为struct tm
s。
使用mktime()
从time_t
创建struct tm
。
然后最后使用difftime()
来计算以秒为单位的差异。
答案 2 :(得分: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对:
进行了重复请!我说我是结构和功能的新手,你知道我 [不要] 知道你的一半代码意味着什么吗?不要误会我的意思,我很乐意得到专业人士的帮助,但你必须明白,这根本不能帮助我。它只会让我更加困惑!
上面的代码是对现有代码的一个非常小的修改。 “输入验证代码”部分中的代码&#39;下面有点复杂;你可以暂时忽略它(但你应该能够在本周末理解它;它不复杂,尽管它在使用函数以避免重复时是无情的。)
解析上面的代码:
main()
之外,以便其他函数也可以使用该类型。err_exit
接受一个字符串参数(char const *msg
)并将其打印在标准错误(这是报告错误消息的正确文件流)上,然后退出程序。退出值0表示成功; 1是一个常见的问题&#39;退出状态。如果您愿意,可以使用EXIT_SUCCESS
和EXIT_FAILURE
;它们在<stdlib.h>
中定义,以便与exit()
函数一起使用。编写此函数意味着我可以使用单个函数调用报告代码中的错误,而不必每次都编写3行或4行代码(取决于您的格式化首选项)。使用功能是一种省力的技术。它也是首字母缩略词DRY:不要重复自己。关键字static
对您来说并不重要 - 它让我的编译器对我使用的选项感到满意,以防止我犯下愚蠢的错误。如果您愿意,我们可以稍后单独讨论该问题。calculateTimeDiff()
是您的函数逐字。给定两个整数值,它返回它们之间的差异。print_time(char const *pre, Time t, char const *post)
有三个参数。 const
用于告诉编译器该函数不会尝试修改字符串;你可以放弃const
这个词而不会产生任何重大的不良影响。中间参数是您的Time
结构之一,因此该函数获取堆栈结构的副本。然后代码调用printf()
在pre
中打印前缀字符串,Time
结构中的3个数字(%2d
表示打印2位数字或空格和1位数字 - 到足够好的近似值; %.2d
表示总是打印2位数,如果需要,使用前导0来填充,以及post
中的后缀字符串。这是格式化时间值的简单方法。main()
函数,t1
和t2
的声明与firstTime
和secondTime
的声明相同,但我拒绝写这么长的声明名。printf()
与您的相同。scanf()
的呼叫与您的呼叫相同,但名称t1
代替firstTime
。它包含在if
语句中,用于检查读取操作是否成功。如果用户输入格式错误的输入(可能是1::0::0
),则scanf()
将不会返回3;对于示例输入,它将返回1。如果用户输入midnight
,它将返回0.如果用户指示EOF(在Unix上键入 Control-D 或在Windows上键入 Control-Z ),则scanf()
会返回EOF。scanf()
不成功,则调用err_exit()
函数报告问题并退出程序。t2
(代替secondTime
)。s1
和s2
代替firstFullTime
和secondFullTime
。每行计算一个结构中的值的时间(以秒为单位)。一小时60分钟,一分钟60秒。 (t1.hours * 60 + t1.minutes)
给出 hh:mm 值表示的分钟数。当该值乘以60并添加秒数时,结果是自用户键入的 hh:mm:ss 值所代表的午夜以来的秒数。print_time()
来打印t1
和t2
中的值;打印你输入的输入是非常宝贵的,这样你才能知道计算机的功能。大多数情况下,它与您认为的计算机相同,但是如果出现问题,请务必检查您和计算机是否一致。在它们之间,两个调用生成输出,例如T1 = 1:00:01; T2 = 0:59:59;
(其中第二个分号后面有空格)。如果我希望输出分布在两行,我可以用"; "
替换"\n"
参数。calculateTimeDiff()
,然后使用printf()
打印结果。在&#39; 1小时,1秒和#39;之间有两秒钟。和&#39; 59分59秒&#39;所以calculateTimeDiff()
功能正常工作。该程序从return 0;
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
$
突然间,我们陷入了棘手的境地。处理签名的分段数字(例如此处的分段是小时,分钟,秒)时,您需要将符号与组件值分开。我不打算解决这个问题。