5

Please bear with me since I'm still really new to C programming. When I run this code:

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

int main(void)
{
    while (1) {
        time_t mytime;
        mytime = time(NULL);
        printf("%s Hello world\n", ctime(&mytime));
        sleep(1);
    }
    return 0;
}

The output always looks like this:

Wed Jan 18 02:32:32 2017
 Hello world
Wed Jan 18 02:32:33 2017
 Hello world
Wed Jan 18 02:32:34 2017
 Hello world

What I want is like this:

Wed Jan 18 02:32:32 2017 Hello world
Wed Jan 18 02:32:33 2017 Hello world
Wed Jan 18 02:32:34 2017 Hello world

How can I do that ?

Note: If I remove \n from printf("%s Hello world\n", ctime(&mytime)); it'll result like this:

Wed Jan 18 02:38:29 2017
 Hello worldWed Jan 18 02:38:30 2017
 Hello worldWed Jan 18 02:38:31 2017
 Hello worldWed Jan 18 02:38:32 2017
 Hello worldWed Jan 18 02:38:33 2017
hillz
  • 537
  • 6
  • 10
  • 18

5 Answers5

10

The ctime function will return a pointer to a string which ends in a newline.

From the man page:

The call ctime(t) is equivalent to asctime(localtime(t)). It converts the calendar time t into a null-terminated string of the form "Wed Jun 30 21:49:08 1993\n"

If you don't want the newline, you need to save the pointer and remove the newline before printing.

char *t = ctime(&mytime);
if (t[strlen(t)-1] == '\n') t[strlen(t)-1] = '\0';
printf("%s Hello world\n", t);
dbush
  • 205,898
  • 23
  • 218
  • 273
  • But is it guaranteed to be a `\n` and never a `\r\n` across different systems? – Havenard Jan 17 '17 at 19:42
  • 1
    @Havenard Yes, the C standard also states the above equivalence between `ctime` and `asctime` and output format for `asctime`. – dbush Jan 17 '17 at 19:46
  • Reasonable. Yet why the test for `t[strlen(t)-1] == '\n'`? If code is not confident that the `'\n` ends the buffer, then it should not be confident that `'\n'` even exist and the bad string could begin with `'\0'` which leads to UB with `t[strlen(t)-1]`. – chux - Reinstate Monica Jan 17 '17 at 20:08
  • Simpler solution, works in all cases: `t[strcspn(t, "\r\n")] = '\0';` – chqrlie Mar 15 '20 at 14:22
4

I faced the same problem so the workaround I figured was using strtok() in the string.h library. This will omit '\n' and store the whole token before it:

char *p = strtok(ctime(&mytime), '\n');
Muhid
  • 91
  • 5
3

Use strftime to format your own string:

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

int main(void)
{
    char buf[100];
    strftime(buf, 100, "%a %b %d %T %Y", localtime(&(time_t){time(NULL)}));
    printf("%s Hello world\n", buf);
}

For simple formatting tasks like the one in the question, you can spare yourself the printf and let strftime do all the work:

    strftime(buf, 100, "%a %b %d %T %Y Hello world\n",
             localtime(&(time_t){time(NULL)}));
    fputs(buf, stdout);

You should also check the return value of strftime, zero may indicate failure.

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
2

Here are 2 simple solutions:

  • store the pointer returned by ctime() and overwrite the trailing newline with:
#include <time.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    while (1) {
        time_t mytime;
        mytime = time(NULL);
        char *p = ctime(&mytime);
        p[strcspn(p, "\n")] = '\0';
        printf("%s Hello world\n", p);
        sleep(1);
    }
    return 0;
}
  • even simpler: just print the first 24 characters of the string returned by ctime():
#include <time.h>
#include <stdio.h>
#include <unistd.h>

int main(void) {
    while (1) {
        time_t mytime;
        mytime = time(NULL);
        printf("%.24s Hello world\n", ctime(&mytime));
        sleep(1);
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • 1
    The date format produced by ctime is "Www Mmm dd hh:mm:ss yyyy" so you'll want to use `%.24s` to strip the new-line and null-character at the end. – Matt K Mar 02 '21 at 18:30
1

Lop off the '\n' in the popular fashion as suggested here after fgets(). It does not even have a problem if '\n' is missing.

char * ct = ctime(&mytime));
ct[strcspn(ct, "\n")] = '\0';
printf("%s Hello world\n", ct);

ctime() nominally returns a pointer to static char some_name[26]; in the following example form

Sun Sep 16 01:03:52 1973\n\0

The C spec has a qualifier about struct tm fields values being in their normal ranges, else the results are UB. Going on the idea that the year could be outside the range 1000-9999, this renders the fixed placement of '\n' problematic.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256