Ben C-M Ben C-M - 3 months ago 12
C Question

C: Passing and returning pointers to a char*

I'm trying to parse a char* through multiple functions (each extract a portion of the message) and am having trouble passing the pointers between functions. In the portion of the message I'm having trouble with, there is an integer followed by a space character, followed by a double.

This is all running on an STM32F4:

main function:

char* myMsg = NULL;
char* nLink = NULL;

SerialQueue_pop(&myMsg, &tablet_queue); //Extract a char* from a buffer
uint8_t id = extract_gset_id(myMsg, (char*)&nLink); //Extract the integer from the char*
real value = extract_gset_value((char*)&nLink); //Extract the real (float) from the char*


functions:

int8_t extract_gset_id(char* message, char* pEnd)
{
char** ptr;
if ((strlen(message)-13)>0){
int8_t val = (int8_t)( 0xFF & strtol(message+13, &ptr,10));
*pEnd = ptr;
return val;
}
return -1;
}

real extract_gset_value(char* message)
{

if ((strlen(message))>0){
char arr[8];
real val = strtod(message, NULL);
snprintf(arr, 8, "%2.4f", val);
return val;
}
return -1;

}


The first function call should extract an integer starting at character 13 of the string. This works fine, and if I read the return pointer (nLink) after the strtol call, it is pointing to the correct location (at the space right after the integer). However, when I read string from the pointer in my main function or in the second function, it is not pointing to the correct location.

What I'm trying to do is have the main function pass a pointer to the array that gets updated by the first function, then the second function takes that pointer and uses it.

Any help would be appreciated.

Answer

Full fixed code, stubbed to be sure it's working:

#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
typedef unsigned char int8_t; // I had to guess
typedef double real;

int8_t extract_gset_id(const char* message, char** pEnd)
 { 

    if ((strlen(message)-13)>0){
        int8_t val = (int8_t)( 0xFF & strtol(message+13, pEnd,10));
        return val;
    }
    return -1;
}

real extract_gset_value(const char* message)
 { 

    if ((strlen(message))>0){
        //char arr[8];
        real val = strtod(message, NULL);
        //snprintf(arr, 8, "%2.4f", val); // this line is useless
        return val;
    } 
    return -1;

}
int main()
{
char* myMsg = NULL;
char* nLink = NULL;


//SerialQueue_pop(&myMsg, &tablet_queue); //Extract a char* from a buffer
myMsg = "abcdefghijklm129   5678.0";
int8_t id = extract_gset_id(myMsg, &nLink); //Extract the integer from the char*
real value = extract_gset_value(nLink); //Extract the real (float) from the char*
printf("%d, %lf\n",(int)id,value);
}

You had most of the types wrong, specially in the extract_gset_id routine.

First parameter is the message pointer, OK Second parameter is a pointer on a pointer on a char (set as output) that the inner strtol sets when it finishes parsing the integer, so you know where to resume parsing. You have to pass the pointer as a pointer so it can change the value in the main.

Once you have parsed the integer, the rest was almost ok. Notice that I don't need to cast anything. When you're casting char ** to char * something is wrong.