local char pointers inside a function

61 Views Asked by At

I'm trying to code a function to filter non-alphabetic characters from a string in C.

So inside the function wordFilter I initialize a char array in order to store there the filtered string and then assign it to the pointer so I can return it.

However, it turns out that whenever the function is executed after the first time, it seems that the char array "reference" still keeps the value it when the last execution was done. Is there a way to make the "reference" array to be empty every time at the beginning of the execution of the function.

Here is my code:

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

char *wordFilter(char *string) {
    char reference[strlen(string)];
    int index = 0;
    while (*string) {
        if (isalpha(*string)) {
            reference[index] = *string;
            index++;
        }
        string++;
    }
    char *ptr = malloc(sizeof(char) * index);
    ptr = reference;
    return ptr;
}

int main() {
    char input[256];
    char *ptr = input;
    char input2[256];
    fgets(input, 256, stdin);
    
    char reference[256];
    for (int pos = 0; sscanf(ptr, "%s%n", input2, &pos) == 1; ptr += pos) {
        printf("%s ", wordFilter(input2));
    }
    return 0;
} 
2

There are 2 best solutions below

2
jason44107 On BEST ANSWER

The main problem is this line: ptr = reference; That doesn't copy the characters of reference into ptr. As Eugene pointed out, that line causes the variable ptr to point to the stack-allocated reference array, leaking the memory you malloced.

Here are the changes I recommend:

  1. Allocate reference like char reference[strlen(string) + 1]; to allow room for the terminating null.
  2. After the while loop, null-terminate reference like this: reference[index] = '\0';
  3. Instead of using a malloc and copying the string, use strdup(reference) to heap-allocate a duplicate of reference, and then you can return what you get from strdup.
0
chqrlie On

The assignment ptr = reference; makes ptr point to the local array reference and overwrites the pointer to allocated memory, causing a memory leak, ie: the allocated block cannot be freed as its address is no available.

Returning ptr effectively returns a pointer to a local array that goes out of scope immediately, accessing it in the calling function has undefined behavior.

char reference[strlen(string)]; is potentially too small for words entirely composed of letters: there is no space for the null terminator that is required for prinf to determine the end of the string.

Instead of allocating memory, you should pass a pointer to a destination array.

Here is a modified version:

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

char *wordFilter(char *dest, const char *string) {
    size_t index = 0;
    while (*string) {
        if (isalpha((unsigned char)*string)) {
            dest[index] = *string;
            index++;
        }
        string++;
    }
    dest[index] = '\0';
    return dest;
}

int main(void) {
    char input[256];

    if (!fgets(input, 256, stdin))
        return 1;
    
    char buf1[256];
    char buf2[256];
    int pos;
    for (char *ptr = input; sscanf(ptr, "%s%n", buf1, &pos) == 1; ptr += pos) {
        printf("%s ", wordFilter(buf2, buf1));
    }
    printf("\n");
    return 0;
}