Reputation: 33
I wish to insert some characters into a string in C:
Example: char string[100] = "20120910T090000";
I want to make it something like "2012-09-10-T-0900-00"
My code so far:
void append(char subject[],char insert[], int pos) {
char buf[100];
strncpy(buf, subject, pos);
int len = strlen(buf);
strcpy(buf+len, insert);
len += strlen(insert);
strcpy(buf+len, subject+pos);
strcpy(subject, buf);
}
When I call this the first time I get: 2012-0910T090000
However when I call it a second time I get: 2012-0910T090000-10T090000
Any help is appreciated
Upvotes: 3
Views: 3871
Reputation: 36092
You could do something like this:
char src[100] = "20120910T090000";
char mask[] = "NNNN-NN-NN-C-NN-NN-NN";
char dest[100] = {0};
for (size_t s = 0,m = 0, d = 0; s < strlen(src) && m < strlen(mask); ++m)
{
switch (mask[m])
{
case 'N':
assert(isdigit(src[s]));
dest[d++] = src[s++];
break;
case 'C':
assert(isalpha(src[s]));
dest[d++] = src[s++];
break;
default:
dest[d++] = mask[m];
break;
}
}
Upvotes: 1
Reputation: 755044
Here's some working code, which gives me the output:
String: <<20120910T090000>>
String: <<2012-0910T090000>>
String: <<2012-09-10T090000>>
String: <<2012-09-10-T090000>>
String: <<2012-09-10-T-090000>>
String: <<2012-09-10-T-0900-00>>
It uses memmove()
because it is guaranteed that the strings being copied around overlap.
#include <assert.h>
#include <string.h>
#include <stdio.h>
static void insert(char *str, size_t len, char c, size_t pos)
{
memmove(&str[pos+1], &str[pos], len - pos + 1);
str[pos] = c;
}
int main(void)
{
char string[25] = "20120910T090000";
// I want to make it something like "2012-09-10-T-0900-00"
char inschr[] = "-----";
int inspos[] = { 4, 7, 10, 12, 17 };
enum { NUMCHR = sizeof(inschr) / sizeof(inschr[0]) };
enum { NUMPOS = sizeof(inspos) / sizeof(inspos[0]) };
assert(NUMCHR == NUMPOS + 1);
size_t length = strlen(string);
printf("String: <<%s>>\n", string);
for (int i = 0; i < NUMPOS; i++)
{
insert(string, length, inschr[i], inspos[i]);
length++;
printf("String: <<%s>>\n", string);
}
return(0);
}
Of course, I'm assuming C99 support with the for
loop notation. Note, too, that in classic C style, the code does not take the size of the target string, so it does not ensure that there is no buffer overflow. It wouldn't be all that hard to add the parameter and do the check; the problem area is how to indicate that the function failed. You could use a different interface to the function, taking arbitrary length strings to be inserted at arbitrary positions; it isn't significantly harder...
String: <<20120910T090000>>
String: <<2012-0910T090000>>
String: <<2012-09-10T090000>>
String: <<2012-09-10-T090000>>
String: <<2012-09-10-T-090000>>
String: <<2012-09-10-T-0900-00>>
#include <assert.h>
#include <string.h>
#include <stdio.h>
static int insert(char *str, size_t max, size_t len, char *ins, size_t pos)
{
assert(str[len] == '\0');
assert(len < max);
size_t inslen = strlen(ins);
if (len + inslen + 1 >= max)
return -1;
memmove(&str[pos+inslen], &str[pos], len - pos + inslen);
memmove(&str[pos], ins, inslen);
return len + inslen;
}
int main(void)
{
char string[25] = "20120910T090000";
// I want to make it something like "2012-09-10-T-0900-00"
char *insstr[] = { "-", "-", "-", "-", "-" };
int inspos[] = { 4, 7, 10, 12, 17 };
enum { NUMSTR = sizeof(insstr) / sizeof(insstr[0]) };
enum { NUMPOS = sizeof(inspos) / sizeof(inspos[0]) };
size_t length = strlen(string);
assert(NUMSTR == NUMPOS);
printf("String: <<%s>>\n", string);
for (int i = 0; i < NUMPOS; i++)
{
int newlen = insert(string, sizeof(string), length, insstr[i], inspos[i]);
if (newlen < 0)
{
printf("Oops! failed to insert [%s] into [%s]\n", insstr[i], string);
break;
}
length = newlen;
printf("String: <<%s>>\n", string);
}
return(0);
}
Upvotes: 2