How to remove first character from C-string?
Asked Answered
B

8

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.

Bridgetbridgetown answered 28/11, 2010 at 6:58 Comment(1)
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;.Ives
L
69
if (contents[0] == '\n') 
    memmove(contents, contents+1, strlen(contents));

Or, if the pointer can be modified:

if (contents[0] == '\n') contents++;
Lacking answered 28/11, 2010 at 7:0 Comment(4)
ahh, thats what the 'mem' functions do in strings.h cool. That first suggestion works perfectly!Bridgetbridgetown
and note that you need to use memmove, not memcpy, because memmove is required to handle overlapping source/destination correctly.Conformity
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.Lacking
Because the strings becomes shorter, the strlen(contents) also copies the terminator.Lathery
G
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.

Galvanotropism answered 28/11, 2010 at 7:2 Comment(3)
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.Ancona
+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...Sacellum
I like how simple it is but you can't free contents_chopped, since it needs that.Weeny
C
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
Conation answered 25/5, 2011 at 16:52 Comment(1)
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.Weeny
H
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.

Hippodrome answered 30/11, 2010 at 6:33 Comment(0)
D
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
Denys answered 26/3, 2018 at 5:35 Comment(0)
E
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';
}

}

Evante answered 1/3, 2022 at 18:47 Comment(0)
T
-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;

}

Transitory answered 24/12, 2017 at 20:40 Comment(0)
W
-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.

Whitewall answered 30/1, 2021 at 6:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.