Clayton Wahlstrom Clayton Wahlstrom - 4 months ago 23
Python Question

Slicing in C compared with Python

I have been trying to figure out a substring method like Python's splice, e.g. 'hello'[2:4].

OLD: The pointers

new
and
toret
(to return) are the same, but when stored in
hello
, it has a new address. Is there a way to maintain the address and get the slice printed out?

NEW: What is the best way to put chars in the buffer?

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

//char * substr(char *str, int start, int end);
//void substr(char *str, int start, int end);
void get_substr(char *str, int start, int end, char *buffer);

int main() {
char word[] = "Clayton";
char buffer[15];
printf("buffer is now %s",get_substr(word,2,5,buffer);
return 0;
}


void get_substr(char *str, int start, int end, char *buffer) {
int length = end - start;
printf("length %d\n",length);
//char buffer[length]; //init normal array
//assign values from *str
int i;
for (i = 0; i < length; i++) {
buffer[i] = *(str+i+start);
}
}


//char * substr(char *str, int start, int end) {
/* char * substr(char *str, int start, int end) {
int length = end - start;
printf("length %d\n",length);
char buffer[length]; //init normal array
//assign values from *str
int i;
for (i = 0; i < length; i++) {
buffer[i] = *(str+i+start);
printf("i=%d buffer[i]=%c ptr=%c\n",i,buffer[i],*(str+i+start));
}
//add endline if not present
if (buffer[length] != '\0') {
buffer[length] = '\0';
printf("buffer[%d] is %c\n",length,buffer[length]);
printf("0 added\n");
}
printf("buffer %s %p\n",buffer,buffer);
printf("len(buffer) is %d\n",strlen(buffer));
char *toret;
toret = (char*) &buffer;
printf("toret %s %p\n",toret,toret);
return toret;
} */


Sorry this may be a duplicate, but I can't find the same examples on this domain. I AM NEW TO C!

Answer

You can't return a pointer to a buffer that is declared locally within the function. That memory resides on the stack, and the next function call will likely overwrite that memory. You would need to use malloc to create the memory you need if you are going to return it to the calling function, which then needs to be cleaned up with free, once you are done with it.

That being said, it's usually not wise to allocate the memory in the called function and return it. In order to prevent the caller from forgetting to clean up the memory, I would recommend requesting a buffer into which the substring will be copied.

I would change the function signature to return a void, and take an additional buffer into which the substring will be copied:

void get_substr(char *str, int start, int end, char *buffer)

Then, in your calling function, you can do this:

int main() {
    char name[] = "Clayton";
    char buffer[10];

    get_substr(name, 0, 3, buffer);
    /* "Cla" now copied into buffer */

    printf("%s", buffer);
    return 0;
}

Alternatively, since this is a substring function, and you know that the string is completely contained within the original string, you could return the size of the string's length and a pointer to the start of the string (within the original string).

Your signature could look like this:

int substr(char *str, int start, int end, char *substr)

And usage could look like this:

int main() {
    char name[] = "Clayton";
    char *substr;
    int substr_len = substr(name, 0, 3, substr);
    /* substr now points to name, substr_len = 3 */

    /* Copy substring to buffer to print */
    char buffer[10];
    strncpy(buffer, substr, substr_len);

    printf("%s", buffer);
    return 0;
}