project dealing with char arrays

YYYYMMDDHHMM (e.g. 200708201425)
This should be converted to:
08/20/2007 1425



i need to convert the above char array (200708201425) to an actual time stamp without using string objects and im quite stuck.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstring> // assuming these are dumped to the global namespace

int main() {
    char a[] = "200708201425";
    char b[16] {};  // important to zero it out since
                    // strncpy doesn't add terminating '\0'
                    // and strcat needs the '\0'.

    strncpy(b, a + 4, 2);
    strcat(b, "/");
    strncpy(b + 3, a + 6, 2);
    strcat(b, "/");
    strncpy(b + 6, a, 4);
    strcat(b, " ");
    strcpy(b + 11, a + 8);

    std::cout << b << '\n';    // 08/20/2007 1425
}


Alternatively, and assuming you want a ':' in the time value, too:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <cstring>

int main() {
    char a[] = "200708201425";
    char b[20];

    strncpy(b, a + 4, 2);
    b[2] = '/';
    strncpy(b + 3, a + 6, 2);
    b[5] = '/';
    strncpy(b + 6, a, 4);
    b[10] = ' ';
    strncpy(b + 11, a + 8, 2);
    b[13] = ':';
    strcpy(b + 14, a + 10); // strcpy to zero-terminate

    std::cout << b << '\n';   // 08/20/2007 14:25
}

Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
#include <cstring>
using namespace std;

const char base[] = "--/--/---- ----";
const int mapping[] = { 6, 7, 8, 9, 0, 1, 3, 4, 11, 12, 13, 14 };

int main()
{
   char a[] { "200708201425" };
   char b[strlen(base)+1];

   strcpy( b, base );
   for ( int i = 0; i < strlen(a); i++ ) b[mapping[i]] = a[i];

   cout << a << '\n';
   cout << b << '\n';
}
Very nice. You can avoid strlen:

1
2
3
char b[sizeof base];

for ( int i = 0; a[i]; i++ ) b[maping[i]] = a[i];

Very nice also! That's both occurrences of strlen gone.

Do you know any way to initialise b directly with base and avoid the strcpy too? The obvious didn't work because of the const-ness of base or decay to a pointer.
Last edited on
Do you know any way to initialise b directly with base

No, like you say it's basically a pointer, so you need to use strcpy to copy what it points to. In fact base may as well just be const char* base since making it const char base[] actually creates a char array of the appropriate size and copies the string literal into it. So that's a way to avoid one copy, although one that only happens on initialization.
Do you need base at all?

1
2
3
4
5
6
7
8
9
10
int main()
{
   char a[] = "200708201425";
   char b[] = "--/--/---- ----";

   for ( int i = 0; a[i]; i++ ) b[mapping[i]] = a[i];

   cout << a << '\n';
   cout << b << '\n';
}

Do you need base at all?

It depends on exactly how it's used in the actual program, but for this case you don't really need base. It just gives the initial string a name, which may or may not be useful in general.

And it is possible to copy the string without strcpy but it requires wrapping it in a struct:

1
2
3
4
5
6
7
struct Base {
    static char b[];
} base;
char Base::b[] = "--/--/---- ----";

// ...
   Base b{ base };

But surely that's overkill just to avoid strcpy!
And it ruins the clean simplicity of the original code.
Last edited on
For a one-off timestamp I wouldn't need base, and I could initialise b[] once and for all.

However, I was envisaging the program having to deal with multiple timestamps, and so needing a master skeleton to copy from.

But I can definitely see why we would want to use std::string rather than c-strings in reality!
Topic archived. No new replies allowed.