C String Pointer Function strdel

|▌冷眼眸甩不掉的悲伤 提交于 2019-12-11 10:46:57

问题


Can someone please explain me why I get "Segmentation fault..." and how to fix it on this bit of code?

#include<stdio.h>

int str_length(char *s) {
    int length = 0, i;
    for(i = 0; *s; i++) {
        s++;
    }
    return i;
}

char *strdel(char *s, int pos, int n) {
    int i;
    char *p, str[] = "";
    p = str;
    for(i = 0; i < str_length(s) - n + 1; i++)  {
        if(i >= pos) {
            *(p + i) = *(s + i + n);
        }
        else {
            *(p + i) = *(s + i);
        }
    }
    s = str;
    return s;
}

int main() {
    char *str = "abcdef";
    printf("str_lengh: %d\n", str_length(str));
    printf("strdel: %s\n", strdel(str, 1, 2));
    return 0;
}

And I get this output:

str_lengh: 6
strdel: adef
Segmentation fault (core dumped)

Also, is there a better way to create a function: char *strdel(char *s, int pos, int n); that deletes the n characters from position pos than the one I did?


回答1:


I think you are writing all over the stack here...

char *strdel(char *s, int pos, int n) {
    int i;
    char *p, str[] = "";
    p = str; // p points to str which is "" and is on the stack with length 0.
    for(i = 0; i < str_length(s) - n + 1; i++)  {
        if(i >= pos) {
            *(p + i) = *(s + i + n); // now you are writing onto the stack past p
        }
        else {
            *(p + i) = *(s + i);// now you are writing onto the stack past p
        }
    }
    s = str; // now s points to space on stack
    return s; // now you return a pointer to the stack which is about to disapear 
}

Whenever you write past p, which is often, you are running into Undefined Behavior. UB You are writing into space which has not been allocated on the heap or on the stack.

You can write a version of strdel that works only on s. Something like this if I understand strdel right: (roughly, not tested!, needs bounds checking on pos and n )

char *strdel(char *s, int pos, int n) {
    char *dst = s + pos, *src = s + pos + n;
    while(*src) {
        *dst++ = *src++;
    }
    *dst = 0;
    return s;
}



回答2:


I'll throw in my solution for the second part as well. Here's my strdel

char * strdel(char * s, int pos, int n){ 
    memmove(s + pos, s + pos + n, strlen(s) - pos - n + 1); 
    return s;
}

It doesn't copy, it doesn't do bounds checking and the return-value is rather redundant (as it's equal to the input s). So all-in-all it's very standard-C-library-like.

Warning! Cannot be used for string-constants as it modifies s (hence no const char * s).




回答3:


To address the second part of your question, I would have written it something like this (assuming you're going to be passing in string constants and therefore must make a copy of the incoming string):

/*
 * Returns a copy of the NUL terminated string at s, with the
 * portion n characters long starting at position pos removed.
 */
char* strdel(char* s, int pos, int n)
{
    int size = strlen(s);
    char* t = malloc(size - n);
    memcpy(t, s, pos);
    memmove(t + pos, s + pos + n, size - n + 1);
    return t;
}


来源:https://stackoverflow.com/questions/19696338/c-string-pointer-function-strdel

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!