Jump to content

CSV variable to array - C++


FaridAgl
 Share

Go to solution Solved by FaridAgl,

Recommended Posts

Well, you are right.

LPSTR szCSV = "1,qw.ryui-opas_fgh,6da1ef8d8fc0cafcwfcc9r34d8302cb3,asdfasda85ffcfes7f2v1sfdfsd1f4ss";

DWORD i = 0;
while (szCSV[i] != NULL)
{
    if (szCSV[i] == ',')
    {
        szCSV[i] = NULL;
    }

    i++;
}

This code gives me "Access violation writing location" error.

I'm working on a socket server, a multithread one, here it is:

#define RECV_BUF_LEN 92

DWORD WINAPI ClientSocketThread(LPVOID lpParameter)
{
    SOCKET s = *(SOCKET *)lpParameter;

    char buf[RECV_BUF_LEN];

    if (recv(s, buf, RECV_BUF_LEN, 0) <= 0)
    {
        closesocket(s);

        printf_s("recv failed.\n");
        return 0;
    }

    char msg[] = "Thanks, I've read that.";
    send(s, msg, strlen(msg), 0);

    if (shutdown(s, SD_BOTH) == SOCKET_ERROR)
    {
        closesocket(s);

        printf_s("shutdown failed.\n");
        return 0;
    }

    closesocket(s);
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA WSAData;
    if (WSAStartup(MAKEWORD(2, 2), &WSAData) != 0)
    {
        printf_s("WSAStartup failed.\n");
        goto Finish;
    }
    else
    {
        if (LOBYTE(WSAData.wVersion) != 2 || HIBYTE(WSAData.wVersion) != 2)
        {
            WSACleanup();

            printf_s("Could not find a usable version of Winsock.dll.\n");
            goto Finish;
        }
    }

    addrinfo Hints;
    ZeroMemory(&Hints, sizeof(Hints));
    Hints.ai_family = AF_INET;
    Hints.ai_socktype = SOCK_STREAM;
    Hints.ai_protocol = IPPROTO_TCP;
    Hints.ai_flags = AI_PASSIVE;

    addrinfo *Result = NULL;

    if (getaddrinfo("127.0.0.1", "1234", &Hints, &Result) != 0)
    {
        WSACleanup();

        printf_s("getaddrinfo failed.\n");
        goto Finish;
    }

    SOCKET s = socket(Result->ai_family, Result->ai_socktype, Result->ai_protocol);
    if (s == INVALID_SOCKET)
    {
        freeaddrinfo(Result);
        WSACleanup();

        printf_s("socket failed.\n");
        goto Finish;
    }

    if (bind(s, Result->ai_addr, (int)Result->ai_addrlen) == SOCKET_ERROR)
    {
        closesocket(s);
        freeaddrinfo(Result);
        WSACleanup();

        printf_s("bind failed.\n");
        goto Finish;
    }

    freeaddrinfo(Result);

    if (listen(s, SOMAXCONN) == SOCKET_ERROR)
    {
        closesocket(s);
        WSACleanup();

        printf_s("listen failed.\n");
        goto Finish;
    }

    SOCKET socket = INVALID_SOCKET;
    while (true)
    {
        socket = accept(s, NULL, NULL);
        if (socket == INVALID_SOCKET)
        {
            printf_s("accept failed.\n");
            continue;
        }

        CreateThread(NULL,
            0,
            (PTHREAD_START_ROUTINE)ClientSocketThread,
            &socket,
            0,
            NULL);
    }

    closesocket(s);
    WSACleanup();

Finish:
    system("Pause");
    return 0;
} 

It receives the message sent by the client (which will be CSV formatted), and will send the proper data back.

Currently I'm on the "CSV Parser" step! And I have to parse buf variable in the ClientSocketThread to an array, like I had explained in the first post.

Link to comment
Share on other sites

This could be one way to do what you want:

char buf[RECV_BUF_LEN] = {}; // zero-ed out

//...the rest of your code that fills the buf...

// Calculate how many chunks of strings are in your buf
int ibound = 0;
for (int i = 0; i < RECV_BUF_LEN; ++i)
{
    if (buf[i] == ',')
    {
        buf[i] = '\0';
        ++ibound;
    }
}

// Now you allocate space for calculated number of (string) pointers
char** szArr = new char*[ibound + 1];

for (int j = 0, i = 0; j <= ibound; ++j)
{
    szArr[j] = &buf[i]; // set this pointer to your array
    for (; i < RECV_BUF_LEN; ++i)
    {
        if (buf[i] == '\0')
        {
            ++i; // skip this one
            if (buf[i] == ' ') ++i; // skip "space" too
            break;
        }
    }
}

// Print elements of your array just because
for (int i = 0; i <= ibound; ++i)
printf("%i. %s\n", i, szArr[i]);

// Free dynamically allocated array (don't forget this)
delete[] szArr;

fflush(stdout); // flush to see what's printed

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

#define LPSTR char*
#define TCHAR char
#define DWORD unsigned long


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


#define RECV_BUF_LEN 92

LPSTR szCSV = "1,qw.ryui-opas_fgh,6da1ef8d8fc0cafcwfcc9r34d8302cb3,asdfasda85ffcfes7f2v1sfdfsd1f4ss";


int main() {
    TCHAR buff[92];
    LPSTR parts[4] = {buff, 0}; // Assuming there is always 4 elements?

    // Mimics the recieving from the socket
    strncpy(buff, szCSV, RECV_BUF_LEN);

    TCHAR* ch = &buff[0];
    int p = 1;

    while (*ch)
    {
        if (*ch == ',')
        {
            *ch = '\0';
            parts[p++] = ch+1;
        }

        ch++;
    }

    for (p = 0; p < 4; p++) {
        puts(parts[p]);
    }

    return(0);
}

Not very tidy, but should give you an idea of how I'd approach it.

Link to comment
Share on other sites

Just similar to my version:

Programming today is a race between software engineers striving to
build bigger and better idiot-proof programs, and the Universe
trying to produce bigger and better idiots.
So far, the Universe is winning.

Link to comment
Share on other sites

trancexx

Thank you so much, specially for the comments. I'm going to give it a try.

Mat

Thank you, I will give it a try too.

No, that's not always 4 elements, but the first character ('1' in this example) could be used to know how many elements is there.

A value of 1 means there are a total of 4 elements,

A value of 2 = 4 elements

A value of 3 = 3 elements

4 = 4 elements

5 = 3 elements

1 means Login request, 2 means CheckIn request, 3 mean Password Reset request, 4 means Password Change request and 5 means Logout request.

1 = 1,Username,PasswordAsMD5,MachineId

2 = 2,Username,PasswordAsMD5,MachineId

3 = 3,Username,Email

4 = 4,Username,CurrentPasswordAsMD5,NewPassword

5 = 5,Username,MachineId

funkey

Thanks, I will check that thread as soon as I finished with the above codes...

Link to comment
Share on other sites

char buf[RECV_BUF_LEN] = {}; // zero-ed out

//...the rest of your code that fills the buf...

// Calculate how many chunks of strings are in your buf
int ibound = 0;
for (int i = 0; i < RECV_BUF_LEN; ++i)
{
    if (buf[i] == ',')
    {
        buf[i] = '\0';
        ++ibound;
    }
}

// Now you allocate space for calculated number of (string) pointers
char** szArr = new char*[ibound + 1];

for (int j = 0, i = 0; j <= ibound; ++j)
{
    szArr[j] = &buf[i]; // set this pointer to your array
    for (; i < RECV_BUF_LEN; ++i)
    {
        if (buf[i] == '\0')
        {
            ++i; // skip this one
            if (buf[i] == ' ') ++i; // skip "space" too
            break;
        }
    }
}

// Print elements of your array just because
for (int i = 0; i <= ibound; ++i)
printf("%i. %s\n", i, szArr[i]);

// Free dynamically allocated array (don't forget this)
delete[] szArr;

fflush(stdout); // flush to see what's printed

Clueless here.  Hi.  Sorry to hijack.  Why does szArr need to be a **?  I assume that means an array of pointers to pointers?

Link to comment
Share on other sites

  • Solution

trancexx

Thanks a lot, you were really helpful, as always of course.

Here is what I came up with finally:

LPSTR *StringToCsv(CHAR buf[], int *nBound)
{
    int i = 0, j = 0;

    *nBound = 0;
    while (buf[i] != '\0')
    {
        if (buf[i] == ',')
        {
            buf[i] = '\0';
            *nBound += 1;
        }

        i++;
    }

    *nBound += 1;

    char **szArray = new char *[*nBound];
    for (j = 0, i = 0; j <= *nBound - 1; j++)
    {
        szArray[j] = &buf[i];

        while (buf[i] != '\0')
        {
            i++;

            if (buf[i] == '\0')
            {
                i++;
                break;
            }
        }
    }

    return szArray;
}

Mat, thank you too.

Link to comment
Share on other sites

Ahhhh, pointer to an array of pointers makes a lot more sense.  And I learned something new today.  Yay!  Thx trancexx.

Urm, but what could Variant*** possibly mean?  A pointer to a pointer to a pointer to a type Variant?  Also, what turn of events occurred to even create a spawn?

Edited by jaberwacky
Link to comment
Share on other sites

Oh, Variant*** is a pointer to a container of pointers to variants isn't it?

Edit, no, probably not actually.

Edited by jaberwacky
Link to comment
Share on other sites

Oh, Variant*** is a pointer to a container of pointers to variants isn't it?

 

Edit, no, probably not actually.

It's not that hard to imagine what it would be needed for.

If you look at the code posted here char*** could have been used as well to pass pointer to szArr to some function that would do allocation:

void Allocate(char*** xy, int size)
{
    *xy = new char*[size + 1];
}

//...

char** szArr;
Allocate(&szArr, ibound);
But since this is C++, it's more correct to do it like this, if you are doing it that way:

void Allocate(char**& xy, int size)
{
    xy = new char*[size + 1];
}

//...

char** szArr;
Allocate(szArr, ibound);
Edited by trancexx

♡♡♡

.

eMyvnE

Link to comment
Share on other sites

It's not that hard to imagine what it would be needed for.

Easy for you to say.

I think this seals the deal.  I'll never be ready for prime time when it comes down to c++.

Thanks for taking the time to show me that!  Appreciate it.

Link to comment
Share on other sites

That C++ code to FlowChart with this site: http://code2flow.com/

it help me to see the overall logic of the above program.

I would love a tool like that (code2flow.com), for the AutoIt language, were included in this site autoitscript.com...

 

YtcG2m.code.png

 

image.jpeg.9f1a974c98e9f77d824b358729b089b0.jpeg Chimp

small minds discuss people average minds discuss events great minds discuss ideas.... and use AutoIt....

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...