简体   繁体   中英

How to concatenate char array elements and cast/convert them to float?

I am using Winsock, I want to send some values from Simulink to my own program and then I'll use that values in my mathematical equations. My computer is 64-bits, so that a char is 2 bytes and a float is 8 bytes. I want to get 3 elements in my buffer so that I declared my buffer as char buffer[12]. Now I need to merge buffer[0],buffer[1],buffer[2],buffer[3] and buffer[4],buffer[5],buffer[6],buffer[7] and ... so on and want to have a value like 12.23456. How can I do this and cast (or convert) it to float in order to use that values in my mathematical equations?

Here what I tried so far:

#pragma once 
#pragma comment(lib, "Ws2_32.lib")
#include <Windows.h>
#include <WinSock.h>
#include <string.h>
#include <iostream>


using namespace std;
int main(){

    WSAData wsaData;
    WORD DllVersion = MAKEWORD(2,2);
    int startup_RetVal = WSAStartup(DllVersion,&wsaData);

    SOCKET sSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);

    SOCKADDR_IN addr;

    addr.sin_addr.s_addr = inet_addr("127.0.0.1");
    addr.sin_family = AF_INET;
    addr.sin_port = htons(2222);

    bind(sSocket, (SOCKADDR*)&addr, sizeof(addr));
    char buf[12];

    recvfrom(sSocket,buf,sizeof(buf),NULL,NULL,NULL);

    char myString[4];
    strcpy(myString,buf[0]);
    strcat(myString,buf[1]);
    strcat(myString,buf[2]);
    strcat(myString,buf[3]);

    //cast it to float

    return 0;

}

This code does not compile because it has errors about strings.

There is some confusion in your question. A char occupies 1 byte, 64-bit system or not, and a float occupies 4 bytes. However, you should express the size of a float simply as sizeof(float) to avoid an unnecessary assumption.

Your Windows PC is a little-endian system and I assume that Simulink is transmitting the values to your program as 32-bit little-endian floats, so there is no endian-conversion to worry about. (But check the Simulink settings in case I am wrong either about the 32-bit or the little-endian).

I also assume the values are being transimitted such that you can count on receiving 3 at time, as you want to (though I don't know why you require them bundled in 3s).

In that case, your receive buffer, now declared as char buf[12]; should be declared as char buf[sizeof(float) * 3];

Then, delete:

char myString[4];
strcpy(myString,buf[0]);
strcat(myString,buf[1]);
strcat(myString,buf[2]);
strcat(myString,buf[3]);

//cast it to float

and replace it with:

float af[3];
for (unsigned i = 0; i < 3; ++i) {
    memcpy(af + i,buf + (i * sizeof(float)),sizeof(float));
}

This will copy 3 consecutive floats from buf into the 3 floats af[0] , af[1] , af[2] . Read about memcpy here .

That is the sufficient to solve your problem. But I would strongly suggest that you check the return value of recvfrom and act accordingly. If the call has been successful it will return the number of bytes received as int ; otherwise SOCKET_ERROR .

You need the return value to be 3 * sizeof(float) for this code to work. More flexible code would just ensure that it is a multiple of sizeof(float) and then extract as many floats as you have got. And in any case you need to handle SOCKET_ERROR .

As to the string-related compilation errors you were seeing, they were due to the same mistake in your call strcpy(myString,buf[0]) and in each your calls strcat(myString,buf[n]) . The signature of strcpy is:

char * strcpy ( char * destination, const char * source );

and that of strcat is:

char * strcat ( char * destination, const char * source );

In each case the second argument must be a const char * and in each case you are passing a char . That is what the compiler's error messages were telling you:

error C2664: 'strcpy' : cannot convert parameter 2 from 'char' to 'const char *'
error C2664: 'strcat' : cannot convert parameter 2 from 'char' to 'const char *'

Using C++11, you can do it painlessly in this way:

#include <iostream>
using namespace std;

int main()
{
    char buf[13] = "1.2378.40.00";

    for(int n=0; n<3; ++n){
        string s {buf[n*4],buf[n*4+1],buf[n*4+2],buf[n*4+3]};
        double value = stof(s);
        cout << value << endl;
    }
}

stof() is new since C++11. As is the initialization of s via an initializer list.

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