0
\$\begingroup\$

I have written a program in C, which given a time in 12-hour AM/PM format, converts it to military time (24 hours).

Function Description

The timeConversion function should return a new string representing the input time in 24-hour format.

timeConversion has the following parameter(s):

string s: a time in 12 hour format 

Returns

string: the time in 24 hour format

Input Format

A single string s that represents a time in 12-hour clock format (i.e.:hh:mm:ssAM or hh:mm:ssPM)

1) Sample Input

07:05:45PM

Sample Output

19:05:45

2) Sample Input

12:01:00PM

Sample Output

12:01:00

3) Sample Input

12:01:00AM

Sample Output

00:01:00

Code:

#include <asm-generic/errno-base.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <sys/types.h>
#include <errno.h>
#include <err.h>
#include <stdbool.h>

static char *timeConversion(char *restrict);

int
main(void)
{
    char *s = NULL;
    size_t n = 0;
    getline(&s, &n, stdin);

    char *res = timeConversion(s);

    (void)fprintf(stdout, "%s\n", res);
    exit(EXIT_SUCCESS);
}

static char *
timeConversion(char *restrict s)
{
    int h1 = (int)s[0] - '0';
    int h2 = (int)s[1] - '0';

    int HH = h1 * 10 + h2 % 10;
    char t[] = { s[8], s[9] }, *fmt = s;

    char *out = malloc(BUFSIZ * sizeof(char));
    if (out == NULL)
        errx(EXIT_FAILURE, "%s", strerror(ENOMEM));
    
    memmove(fmt, fmt+2, strlen(fmt));

    fmt[strcspn(fmt, "\r\t\n")] = 0;
    fmt[strlen(fmt) - 2] = '\0';

    _Bool status = strcmp(t, "AM");
    if (!status) {
        if (HH == 12)
            HH = 0;
    } else {
        HH += 12;
        if (HH == 24)
            HH -= 12;
    }
    sprintf(out, "%02d%s", HH, fmt);
    return (char *)(out);
}

I know this may not be the best solution, but it was more or less what came my mind. And well, I wrote it on a Linux Machine (Gentoo), and I see that it works as expected, with the inputs above. But when I tried to test it on another machine (Mac OS), the results were:

Sample Input

07:05:45AM

Sample Output

19:05:45

I'd like to know if there is any way to improve it or a solution to "fix" the behavior of this program?

\$\endgroup\$
2
  • 1
    \$\begingroup\$ Great question, well formatted and well specified. \$\endgroup\$
    – Reinderien
    Commented Jul 26, 2022 at 12:52
  • 1
    \$\begingroup\$ strcmp(t, "AM") invokes undefined behaviour: The code as presented is not ready for Code Review@SE. \$\endgroup\$
    – greybeard
    Commented Jul 27, 2022 at 6:48

1 Answer 1

1
\$\begingroup\$

There is a problem comparing a literal string "AM" and a char array not ended with '\0' ==> t[]

char t[] = { s[8], s[9] }

//int strcmp(const char *str1, const char *str2)
_Bool status = strcmp(t, "AM");

If you want to compare char t[] with "AM", you need to add an extra char at the end to sepecify that the string is ended.

char t[] = { s[8], s[9], '\0'};

Note: you can see your current t[] values just printing them, and you will see the extra characters that strcmp is using when comparing with "AM".

sprintf(out, "output: %s", t);
output: AM╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠└ñÌ☺
\$\endgroup\$

Not the answer you're looking for? Browse other questions tagged or ask your own question.