1
// The first example:
char text[] = "henri";
char *p;
p = text;
*(p + 1) = 'E'; // Output = hEnri
// Now If we want to remove the "e" ie hnri, we would go for?????
     *(p + 1)=????? 

The obvious answer is to copy the rest of the array "back" one position. But this seems... unpleasant. Surely there is some better way?

Mohit Jain
  • 43,139
  • 57
  • 169
  • 274

7 Answers7

4

Copying is the best solution and really the only solution when you're removing elements from an array. (You can special case the element at the end of the array, but that's it.) I don't understand why it's so terrible.

You need to do one of two things. Both involve some copying.

1) Copy the 'n' to where the 'E' is, the 'r' to where the 'n' is, the 'i' to where the 'r' is, and then null terminate it.

2) Copy the 'h' to where the 'E' is and then always use the pointer to the 'h's new location. This may not always be an option.

Evan Shaw
  • 23,839
  • 7
  • 70
  • 61
  • You may as well copy pointers and save a bit of cycles if the string is very long and allocated on the heap. moving pointers is more efficient (like the linked list for example) – the_drow May 30 '10 at 00:15
3
*++p = 'h';
puts(p);
John Kugelman
  • 349,597
  • 67
  • 533
  • 578
1

You'd have to move all the remaining characters up one. There's no way to say "skip this char".

while (*p)
{
    *p = *p++;
}

edit: ugh, how did I make that mistake? Now fixed. p will still be non-null at the end of the string, but *p will not.

Vicky
  • 12,934
  • 4
  • 46
  • 54
  • 1
    Two bugs here: 1. `while(p)` will continue looping until p is NULL, you want `while(*p)` 2. Even then, you need to copy the ending `'\0'` – BlueRaja - Danny Pflughoeft May 21 '10 at 18:24
  • @BlueRaja: the *p was a complete brainfade, thanks. But you don't need to copy the terminating 0, that will be done by the last iteration of the loop. – Vicky May 21 '10 at 18:26
  • Doesn't `*p=*p++` cause undefined behaviour because you modify `p` and read it (not just to determine the value to store) without an intervening sequence point? Moreover I can't see a way of ordering the modifications that would do the right thing (it definitely doesn't work with `gcc`). If you change it to `*p=*(p+1);++p;` it does work, though. – Mike Dinsdale May 21 '10 at 19:58
  • @Mike Dinsdale: I thought the assignment was a sequence point, so it would read, modify, increment. If it doesn't work in gcc I must be wrong though - I didn't actually try it. – Vicky May 21 '10 at 20:10
  • @Vicky: according to the answers to [this question](http://stackoverflow.com/questions/1860461/why-is-i-i-1-unspecified-behavior) the assigment isn't a sequence point for non-user-defined types. I'm not sure it would help even if it was, though, because even though the increment would then be guaranteed to happen before the assignment, it's undefined whether it happens before `*p` (the first arg of `=`) is evaluated (if we can believe [Wikipedia](http://en.wikipedia.org/wiki/Sequence_point) ;)) – Mike Dinsdale May 21 '10 at 20:24
  • and even if it did turn out to be defined, could it really work? For example, if it was equivalent to `char q=*p;p++;*p=q` it would overwrite memory indefinitely with the first letter in the string, or if it was equivalent to `char q=*p;*p=q;p++` it won't do anything... – Mike Dinsdale May 21 '10 at 20:31
0

move the characters down by 1 after it (including the null at the end)

you'll end up with two nulls at the end, by the way.

corsiKa
  • 81,495
  • 25
  • 153
  • 204
0

This is not copying the array. I'm moving the data within the same array.

for (p = text + 1; *p != '\0'; ++p) {
  *p = *p + 1;
}

A hackier solution is to put the 'h' where the 'e' was, and return a pointer to the new beginning.

*p + 1 = *p;
p = p + 1;
Adrian McCarthy
  • 45,555
  • 16
  • 123
  • 175
0

This should do it:

memmove(p+1, p+2, 4);

We move four characters because we want to copy the null terminator as well.

Michael Chinen
  • 17,737
  • 5
  • 33
  • 45
0

There is no way to remove anything from a C string without copying the following characters to fill in the hole.

But you could change your data structure and use something other than a string. For example, you could use an array or linked list of string pieces. This is sometimes called a "rope."

Of course, when you need to pass the data to some other function that expects a C string you have to copy out the entire thing.

Zan Lynx
  • 53,022
  • 10
  • 79
  • 131