如何从C字符串中删除第一个字符?

29

请问有人能帮我吗? 我需要从C中的char * 中删除第一个字符。

例如,char * contents包含一个'\n'字符作为数组的第一个字符。 我需要检测并消除此字符,修改原始变量后经过“净化”。

谁能帮我写出代码? 我是C语言的新手,似乎就是想不出来。


2
对于C语言新手来说,阅读关于“指针算术”的内容非常有益。谷歌一下这个术语,你会得到很多结果。这将有助于理解其他人在这里所说的内容。例如:char* contents_chopped = contents + 1; - biocyberman
8个回答

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

或者,如果指针可以被修改:

if (contents[0] == '\n') contents++;

2
啊,这就是在 strings.h 中的 'mem' 函数所做的事情,太棒了。第一个建议完美地解决了问题! - Ash
3
请注意,你需要使用 memmove 而不是 memcpy,因为 memmove 能够正确处理重叠的源和目的地。 - David Gelhar
3
请注意,如果您使用++版本,则在尝试释放已增加指针时程序将会崩溃。此情况下,请使用@Grigory的建议。此外,在短字符串上,由于其初始化成本,memmove可能比简单循环执行得慢。 - ruslik
由于字符串变短,strlen(contents)也会复制终止符。 - Peter v.d. Vos

24

char* contents_chopped = contents + 1;

这将导致 contents_chopped 指向相同的字符串,除了第一个字符是在 \n 之后的下一个字符

此外,这种方法更快。


必须注意指针的有效性将取决于“contents”的有效性,因此如果您只想对“contents_chopped”进行一些快速处理,则这很好。还需要检查空字符串。 - tia
+1 如果您提供的答案是任何真实世界代码都应该使用的。仅仅为了使用字符串的尾部而复制/移动整个字符串是一种荒谬的时间浪费,但不幸的是,有许多程序实际上确实这样做... - R.. GitHub STOP HELPING ICE
我喜欢它的简单性,但你不能释放 contents_chopped,因为它需要它。 - Doug Molineux

16

如果你使用了malloc分配内存,不要只是增加指针的值,否则你的程序将会崩溃。 free函数需要原始指针。你可以复制指针,创建一个新的内存块并使用memcpy进行访问,也可以使用ptr+1等其他方式进行访问,但建议不要仅仅增加指针的值。那些建议你这样做的人给出的是危险的建议。你可以运行这个示例程序,看看当你“仅仅增加指针”的时候会发生什么。

#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);
}

提示:以下是结果:

[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

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

4
似乎你认为 char* 包含字符,但实际上它只是指向一个字节。剩下的字符串被假定为由随后的内存字节组成,直到下一个空字节。请注意,虽然 "char" 数据类型是一个字节,但按定义,它并不一定是真正的字符,需要了解 Unicode 以及一个字节不一定是一个八位字节。 char* 也不是数组,尽管可能存在一个字符数组,指针指向该数组的开头。

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
如果找到了该字符,程序会忽略该字符并继续循环。
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

这是我的代码

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;

}


-2

这是我的代码
非常简单

#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] // 这里的1表示要删除的字符数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接