29

Can anyone please help me? I need to remove the first character from a char * in C.

For example, char * contents contains a '\n' character as the first character in the array. I need to detect and eliminate this character, modifying the original variable after its been "sanitized".

Can anyone help me with the code? I'm completely new to C, and just can't seem to figure it out.

Bill the Lizard
  • 398,270
  • 210
  • 566
  • 880
Ash
  • 24,276
  • 34
  • 107
  • 152
  • 2
    For a C newbie, it is very beneficial to read about `pointer arithmetic`. Google the term, you will get many hits. This will help to understand what others are talking about here. For example: `char* contents_chopped = contents + 1;`. – biocyberman Jun 03 '14 at 08:51

8 Answers8

69
if (contents[0] == '\n') 
    memmove(contents, contents+1, strlen(contents));

Or, if the pointer can be modified:

if (contents[0] == '\n') contents++;
ruslik
  • 14,714
  • 1
  • 39
  • 40
  • 2
    ahh, thats what the 'mem' functions do in strings.h cool. That first suggestion works perfectly! – Ash Nov 28 '10 at 07:03
  • 3
    and note that you need to use `memmove`, not `memcpy`, because `memmove` is required to handle overlapping source/destination correctly. – David Gelhar Nov 28 '10 at 07:14
  • 3
    Also note that if you use `++` version, then the program will crash if you try to free the incremented pointer. Use @Grigory suggerstion in that case. Also, on short strings, `memmove` could perform slower that a simple loop because of its initialization cost. – ruslik Nov 28 '10 at 07:24
  • Because the strings becomes shorter, the strlen(contents) also copies the terminator. – Peter v.d. Vos Feb 08 '23 at 10:39
24

char* contents_chopped = contents + 1;

This will result in contents_chopped pointing to the same string, except the first char will be the next after \n

Also, this method is faster.

  • Must note that the pointer validity will depend on the validity of `contents`, so this is good if you only want do some quick process on `contents_chopped`. Also need to check for empty string. – tia Nov 28 '10 at 07:10
  • +1 for giving the answer that any real-world code should use. Copying/moving an entire string just to make use of its tail is a ridiculous waste of time, but there are sadly many programs that actually do such things... – R.. GitHub STOP HELPING ICE Nov 28 '10 at 14:28
  • I like how simple it is but you can't free contents_chopped, since it needs that. – Doug Molineux Jul 10 '12 at 20:39
16

Do not just increment the pointer if you have malloc'd any memory or your program will crash. free needs the original pointer. You can copy the pointer, make a new chunk of memory and memcpy it, access it as ptr+1 or any of a bunch of other ways, but the people who say just increment the pointer are giving you dangerous advice. You can run this sample program and see what happens when you "just increment the pointer".

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main(void)
{
    char *str = (char *)malloc(10);
    strcpy(str, "1234567890");
    printf("%s\n", str);
    str++;
    printf("%s\n", str);
    free(str);
}

Hint: Here's the result:

[mfisch@toaster ~]$ ./foo
1234567890
234567890
*** glibc detected *** ./foo: free(): invalid pointer: 0x08c65009 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6(+0x6b591)[0x724591]
/lib/tls/i686/cmov/libc.so.6(+0x6cde8)[0x725de8]
/lib/tls/i686/cmov/libc.so.6(cfree+0x6d)[0x728ecd]
./foo[0x80484e3]
/lib/tls/i686/cmov/libc.so.6(__libc_start_main+0xe6)[0x6cfbd6]
./foo[0x80483f1]
======= Memory map: ========
001c9000-001e4000 r-xp 00000000 08:01 2883609    /lib/ld-2.11.1.so
001e4000-001e5000 r--p 0001a000 08:01 2883609    /lib/ld-2.11.1.so
001e5000-001e6000 rw-p 0001b000 08:01 2883609    /lib/ld-2.11.1.so
006b9000-0080c000 r-xp 00000000 08:01 3015690    /lib/tls/i686/cmov/libc-2.11.1.so
0080c000-0080d000 ---p 00153000 08:01 3015690    /lib/tls/i686/cmov/libc-2.11.1.so
0080d000-0080f000 r--p 00153000 08:01 3015690    /lib/tls/i686/cmov/libc-2.11.1.so
0080f000-00810000 rw-p 00155000 08:01 3015690    /lib/tls/i686/cmov/libc-2.11.1.so
00810000-00813000 rw-p 00000000 00:00 0
00e4d000-00e4e000 r-xp 00000000 00:00 0          [vdso]
00fe0000-00ffd000 r-xp 00000000 08:01 2883667    /lib/libgcc_s.so.1
00ffd000-00ffe000 r--p 0001c000 08:01 2883667    /lib/libgcc_s.so.1
00ffe000-00fff000 rw-p 0001d000 08:01 2883667    /lib/libgcc_s.so.1
08048000-08049000 r-xp 00000000 08:01 9700477    /home/mfisch/foo
08049000-0804a000 r--p 00000000 08:01 9700477    /home/mfisch/foo
0804a000-0804b000 rw-p 00001000 08:01 9700477    /home/mfisch/foo
08c65000-08c86000 rw-p 00000000 00:00 0          [heap]
b7600000-b7621000 rw-p 00000000 00:00 0
b7621000-b7700000 ---p 00000000 00:00 0
b776f000-b7770000 rw-p 00000000 00:00 0
b7780000-b7783000 rw-p 00000000 00:00 0
bfc22000-bfc37000 rw-p 00000000 00:00 0          [stack]
Aborted
mfisch
  • 979
  • 9
  • 15
  • 3
    Good point, this is happening to me right now since I am using the increment method, I am also seeing a similar error to what you show here. The only problem with this answer, is there's no code solution. – Doug Molineux Jul 10 '12 at 20:38
4

It sounds as if you're under the impression that a char* "contains" characters. It does not. It merely points at a byte. The rest of the string is implied to consist of the subsequent byte in memory up until the next null byte. (You should also be aware that although the 'char' data type is a byte, by definition, it is not really a character - please be aware of Unicode - and nor is a byte necessarily an octet.)

The char* is not an array, either, although there may exist an array of characters such that the pointer is pointing to the beginning of that array.

Karl Knechtel
  • 62,466
  • 11
  • 102
  • 153
2
#include <stdio.h>
#include <string.h>

int main ()
 {
char src[50] = "123456789123434567678";

char dest[16]={0};
 memcpy(dest, src+1,sizeof(src));
 printf("%s\n",dest);
 return(0);
}

src+1 -> indicate how many char you want to remove
0

If it finds the character it basically ignores the character and continues to loop.

void remove_character(char* string, char letter) {

int length = strlen(string);
int found = 0;

for (int i = 0; i < length; ++i)
{
    if (string[i] == letter)
    {
        found = 1;
        continue;
    }

    if (found == 1)
    {
        string[i-1] = string[i];
    }          
}

if (found == 1)
{
    string[length - 1] = '\0';
}

}

-1

Here is my code

char  * bastakiniSil(char *contents){
char *p = malloc( sizeof(*p) * strlen(contents) );
int i;
for(i=0; i<strlen(contents); i++)
{
    p[i]=contents[i+1];
}

return p;

}

Samir
  • 6,405
  • 5
  • 39
  • 42
-2

Here is my code
So simple

#include <stdio.h>
#include<stdlib.h>
int main()
{
    char *str=(char *)malloc(100*sizeof(char));
    scanf("%s",str);
    str=&str[1];
    printf("%s",str);
    return 0;
}

str=&str[1] // here 1 indicates how many characters to remove.

dlyaswanth
  • 31
  • 3