简体   繁体   中英

Strcpy() not copying the second character in a string

I have been running into issues with the strcpy() function in C. In this function I take a string in buffer and the string contains a something along the lines of '(213);'and I am trying to remove the brackets so the output would be something like 200;.

for (i = 0; i < bufferlen; i++) {
        // check for '(' followed by a naked number followed by ')'
        // remove ')' by shifting the tail end of the expression
        // remove '(' by shifting the beginning of the expression
        if((buffer[i] == '(') && (isdigit(buffer[i+1]))){

            int numberLen = 0;
            int test =0;
            i++;
            while((isdigit(buffer[i]))){
                i++;
                numberLen++;
            }


            if(buffer[i] == ')'){
                int numberStart = i - numberLen-1;
                strcpy(&buffer[i], &buffer[i+1]);
                strcpy(&buffer[numberStart], &buffer[numberStart+1]);

                printf("buffer = %s\n", buffer);
            }
        }
    }

However, the output is as follows

buffer before strcpy(&buffer[i], &buffer[i+1]); = (213);

buffer after strcpy(&buffer[i], &buffer[i+1]); = (213;

buffer after strcpy(&buffer[numberStart], &buffer[numberStart+1]); = 23;;

for some reason the second strcpy function removes the second value of the string. I have also tried strcpy(&buffer[0], &buffer[1]); and still end up with the same results. Any insight as to why this is occurring would be greatly appreciated.

Continuing from the comment, strcpy(&buffer[i], &buffer[i+1]); where source and dest overlap results in Undefined Behavior , use memmove , or simply use a couple of pointers instead.

The prohibition on using strings that overlap (ie are the same string) is found in C11 Standard - 7.24.2.3 The strcpy function

If I understand your question and you simply want to turn "'(213)'" into "213" , you don't need any of the string.h functions at all. You can simply use a couple of pointers and walk down the source-string until you find a digit. Start copying digits to dest at that point by simple assignment. When the first non-digit is encountered, break your copy loop. Keeping a flag to indicate when you are " in " a number copying digits will allow you to break on the 1st non-digit to limit your copy to the first sequence of digits found (eg so from the string "'(213)' (423)" , only 213 is returned instead of 213423 ). You could do somehting like:

char *extractdigits (char *dest, const char *src)
{
    /* you can check src != NULL here */
    char *p = dest;     /* pointer to dest (to preserve dest for return) */
    int in = 0;         /* simple flag to break loop when non-digit found */

    while (*src) {              /* loop over each char in src */
        if (isdigit(*src)) {    /* if it is a digit */
            *p++ = *src;        /* copy to dest */
            in = 1;             /* set in-number flag */
        }
        else if (in)            /* if in-number, break on non-digit */
            break;
        src++;                  /* increment src pointer */
    }
    *p = 0;             /* nul-terminate dest */

    return dest;        /* return pointer to dest (for convenience) */
}

A short example would be:

#include <stdio.h>
#include <ctype.h>

#define MAXC 32

char *extractdigits (char *dest, const char *src)
{
    /* you can check src != NULL here */
    char *p = dest;     /* pointer to dest (to preserve dest for return) */
    int in = 0;         /* simple flag to break loop when non-digit found */

    while (*src) {              /* loop over each char in src */
        if (isdigit(*src)) {    /* if it is a digit */
            *p++ = *src;        /* copy to dest */
            in = 1;             /* set in-number flag */
        }
        else if (in)            /* if in-number, break on non-digit */
            break;
        src++;                  /* increment src pointer */
    }
    *p = 0;             /* nul-terminate dest */

    return dest;        /* return pointer to dest (for convenience) */
}

int main (void) {

    char digits[MAXC] = "";
    const char *string = "'(213}'";

    printf ("in : %s\nout: %s\n", string, extractdigits (digits, string));
}

Example Use/Output

$ ./bin/extractdigits
in : '(213}'
out: 213

Look things over and let me know if you have further questions.

A method by filtering '(' and ')' in place. Time complexity is O(N).

int main(void) {
    char buffer[] = "(213)";
    int bufferLen = 5;

    int left = -1;
    for (int right = 0; right < bufferLen; ++right) {
        if ((buffer[right] != '(') && (buffer[right] != ')')) {
            ++left;
            buffer[left] = buffer[right];
        }
    }

    buffer[++left] = '\0';

    printf("%s", buffer);

    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM