0

I am creating a removeNonAlphaCharacters function trying to remove all non alphabetic characters using C.

I could remove all non-alphabetic characters inside the function, but I can not pass the modified string back the original string, which means I can't override the original string directly inside the function even using double pointer. Does anyone have an idea what's going wrong in my code?

The final printf inside the main function won't print me the HelloData for me, however the one inside the removeNonAlphaCharacters function could give me the correct output.

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int removeNonAlphaCharacters(char ** source);

int main() {
    char * source = "Hello 2 Data!";
    char **sourcePointer = &source;
    int result = 0;
    result = removeNonAlphaCharacters(sourcePointer);
    printf("we have successfully removed %i characters from the string.\n", result);
    printf("The modified result is: %s", source);
    return 0;
}

int removeNonAlphaCharacters(char ** source) {
    char *dest = *source;
    size_t sourceLength = strnlen(*source, 100);
    char *str = malloc(sourceLength*sizeof(char));
    int removeNum = 0;
    for (; *dest != '\0'; dest++) {
        if (*dest >= 'A' && *dest <= 'Z' || *dest >= 'a' && *dest <= 'z') {
            *str = *dest;
            str++;
        }
        else {
            removeNum++;
            continue;
        }
    }
    printf("The modified result is: %s\n", str-(sourceLength-removeNum));
    *source = malloc((sourceLength-removeNum) * sizeof(char));
    strncpy(*source, str, 100);
    return removeNum;

I tried to use malloc to allocate memory inside the function, and it didn't work for me. And I also tried directly override the original string inside the removeNonAlphaCharacters function without allocating memory, which will end up into the Memory Error SIGBUS.

Keith Thompson
  • 254,901
  • 44
  • 429
  • 631
rui wang
  • 3
  • 2
  • 1
    Looks ok but you forgot to null terminate the `str` after the copy. Add a `*str = '\0'` after the `for` loop, does that solve the problem? – Lundin Mar 30 '23 at 06:53
  • 1
    `sizeof(char)` is, by definition, 1, so there's no need to multiply in the `malloc()` parameter. But... If there are no characters removed, `*str` will not have sufficient space for the terminating `'\0'`... Try: `char *str = malloc( sourceLength + 1 );` AND, the attempt to copy the string won't work because, in a perfect world, `str` is pointing at the end of the string... (PS: Just noticed the 2nd `malloc()` is also too short...) – Fe2O3 Mar 30 '23 at 06:59
  • 1
    That is quite a round-a-bout way to remove non-alpha characters. You can simply pass the string as a single-pointer (it points to where the actual chars are stored in memory) and then update the string in place. Simply use a *read* pointer and *write* pointer (you can simply use a write pointer if you iterate by index or don't provide a convenience return of the original pointer. The string must be mutable (not a string-literal). See [Remove Non-Alpha](https://paste.opensuse.org/2ed19a5689c9) for an example. (link good until Thu 27 Apr 2023 02:19:46 AM CDT) – David C. Rankin Mar 30 '23 at 07:20
  • 1
    Also, consider `#include ` and calling `isalpha()` instead of the long conditional -- which you should group with additional `(() || ())` for clarity. Using `isalpha((unsigned char)*dest)` is much easier than `if (('A' <= *dest && *dest <= 'Z') || ('a' <= *dest && *dest <= 'z'))` -- and much less prone to an accidental typo. – David C. Rankin Mar 30 '23 at 07:27

1 Answers1

0

The issue you have is within your function, removeNonAlphaCharacters.

You create a new string str (i.e. a pointer to a char) and as you manipulate this string, your pointer is incrementing (in the line str++) hence when you call the function strncpy, the string you are copying is a pointer to the end of the string you want (not a pointer to the start).

To fix, modify the line containing strncpy to be

strncpy(*source, str-(sourceLength-removeNum), 100);

Don't forget as well to consider adding the null termination '\0' to your new string.

xulo
  • 440
  • 3
  • 9
  • 1
    Worth mentioning that `strncpy()` is particularly inefficient for large string since it sets all characters past the end of the string to the nul-character. See [man 3 strncpy](https://man7.org/linux/man-pages/man3/strcpy.3.html) – David C. Rankin May 01 '23 at 06:06