I need to convert this date : 2019-08-22 16:16:08 to this specific form: aammjjhhmmss
(aa
for 'année' or year; jj
for 'jour' or day).
I'm working with C language. This is my code. I don't find it good because I need to call the function three times to get what I want:
#include <stdio.h>
#include <string.h>
void removeChar(char *s, int c){
int j;
int n = strlen(s);
for (int i=j=0; i<n; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
}
int main()
{
char s[] = "2019-08-22 16:16:08";
removeChar(s, '-');
printf("test 1 without '-' %s \n",s);
removeChar(s, ':');
printf("test 2 without ':' %s \n",s);
removeChar(s, ' ');
printf("test 3 without ' ' %s \n",s);
return 0;
}
Results :
test 1 without '-' 20190822 16:16:08
test 2 without ':' 20190822 161608
test 3 without ' ' 20190822161608
And the format is: YYMMDDHHMMSS
.
You can treat this as an exercise in date/time manipulation (hard), or as an exercise in string manipulation (easier).
If you want to do date/time manipulation, then in a POSIX environment, strptime()
and strftime()
are your friends. (NB: strftime()
is standard C; strptime()
is part of POSIX.)
Your code treats it as an exercise in string manipulation. Your result shows YYYYMMDD (4 digits for the year); your request shows AA or YY (2 digits) for the year. I wonder which is correct? If you have 4 input and 4 output digits life is simpler than if you have 4 input and 2 output. Assuming that it should be 4 digits in, 4 digits out, then all you need to do is copy the digits.
There's a subtle bug in your code:
int j;
int n = strlen(s);
for (int i=j=0; i<n; i++)
if (s[i] != c)
s[j++] = s[i];
s[j] = '\0';
You have two different variables j
, and the j
used in the last assignment is uninitialized. If you use GCC, you could use -Wshadow
as a compilation option to get warnings about such variable shadowing. You should use:
int j = 0;
int n = strlen(s);
for (int i = 0; i < n; i++)
{
if (s[i] != c)
s[j++] = s[i];
}
s[j] = '\0';
However, you legitimately worry about calling your function three times. You could write a variant that only needs to be called once, because it keeps only the digits in the input:
#include <ctype.h>
void keepDigits(char *s)
{
int j = 0;
int n = strlen(s);
for (int i = 0; i < n; i++)
{
if (isdigit((unsigned char)s[i]))
s[j++] = s[i];
}
s[j] = '\0';
}
Indeed, you could also avoid pre-scanning the string with strlen()
by using:
void keepDigits(char *s)
{
int j = 0;
for (int i = 0; s[i] != '\0'; i++)
{
if (isdigit((unsigned char)s[i]))
s[j++] = s[i];
}
s[j] = '\0';
}
Now you scan the string once instead of 6 times (3 calls to your 'remove' function which scans the entire string, and each of which calls strlen()
which also scans the entire string).
Test code:
int main(void)
{
char s[] = "2019-08-22 16:16:08";
printf("Before: [%s]\n", s);
keepDigits(s);
printf("After: [%s]\n", s);
return 0;
}
Output:
Before: [2019-08-22 16:16:08]
After: [20190822161608]
If you only want 2 digits for the year, then you could use:
int main(void)
{
char s[] = "2019-08-22 16:16:08";
char *p = &s[2];
printf("Before: [%s]\n", p);
keepDigits(p);
printf("After: [%s]\n", p);
return 0;
}
Output:
Before: [19-08-22 16:16:08]
After: [190822161608]
Note, however, that the leading two digits are still in s
here.