Reputation: 631
I want to write a C function that removes a portion of a string for a given index range.
For example, if the input string is "ABCDEFGHIJK" and the start index is 2 and the end index is 5 then the output should be: "ABGHIJK".
I am attempting to do this using two functions, one function that gets the substring we want to delete:
void get_substring(char string[], char substring[], int start, int end) {
strncpy(substring, string + start, end - start + 1);
}
and then a second function that deletes this substring:
void remove_portion(char string[], char substring[]) {
// memmove?
}
Another possibility I was thinking about is to directly modify the original string without using a substring:
void remove_portion(char string[], int start, int end) {
// if end is less then the length of the string, then
// copy everything after string[end] into a temp string
// Then replace string[start] with '\0' and then concatenate
// string and temp.
// If end is greater than the length of string then just replace
// string[start] with '\0'.
}
Is this the correct approach? Are there any built in functions from string.h that can be useful here?
Upvotes: 5
Views: 531
Reputation: 21320
It was pointed out to me that using strcpy()
for this is wrong, because "copying that takes place between objects that overlap" is undefined in the standard (ISO/IEC 9899:1999 7.21.2.4).
Here is a version that uses memmove()
, with some checks for valid indices. It swaps the indices if the first is larger than the second, and returns NULL if the indices are out of bounds:
char * remove_portion(char *str, int start, int end)
{
int str_len = strlen(str);
int temp;
if (start > end) {
temp = start;
start = end;
end = temp;
}
if (end > (str_len - 1) || start < 0 || end < 0) {
str = NULL;
} else {
int ncopy = str_len - end;
memmove(&str[start], &str[end+1], ncopy);
}
return str;
}
Of memmove()
the standard says: "Copying takes place as if the n characters from the object pointed to by s2 are first copied into a temporary array of n characters that does not overlap the objects pointed to by s1 and s2, and then the n characters from the temporary array are copied into the object pointed to by s1." (ISO/IEC 9899:1999 7.21.2.2)
So memmove()
is specifically designed to handle situations such as copying a part of an array to itself.
Upvotes: 0
Reputation: 1289
New to C myself, but this worked for me:
void remove_portion(char str[], int start, int end) {
assert((end > start) && (strlen(str) > end));
char out[strlen(str) - (end - start)];
int i, j = 0;
for (i = 0; str[i] != '\0'; i++) {
if ((i < start) || (i > end))
out[j++] = str[i];
}
out[j] = '\0';
strcpy(str, out);
}
Upvotes: 1
Reputation: 417
I would go with using memmove as in the 2nd approach:
void remove_portion(char string[], int start, int end)
{
if (start>=0 && end>=start && start<strlen(string) && end<strlen(string)) { // some more sanity checking (EDIT added later)
memmove(string+start, string+end+1, strlen(string)-(end+1)+1); // final +1 to copy string terminator
}
}
Also note that in your first example (with strncpy) is not going to to copy the ending string terminator \0 to substring. So you'll need to add
substring[end - start + 1]= '\0';
to that.
Upvotes: 5
Reputation: 107
Use this :
void remove_portion( char * str, int start, int end){
char* stro = calloc(strlen(str - (end-start+1)), sizeof(char));
strncpy(stro,str,start);
strcat(stro,&str[end]);
strcpy(str,stro);
}
Add conditions also.
Upvotes: 1