Получение строк в C ++ из Python - PullRequest
0 голосов
/ 12 октября 2018

Я пытаюсь отправить логические значения через сокеты с клиента (Python) на сервер (C ++).

Поэтому я использовал json, преобразовал логические значения в формат строки и отправил строку через сокеты.

Вот мой код: Клиентская часть (Python):

# TCP Client Code

host="128.0.0.1"            # Set the server address to variable host

port=8080               # Sets the variable port to 4446

from socket import *             # Imports socket module
import json

s=socket(AF_INET, SOCK_STREAM)      # Creates a socket



s.connect((host,port))          # Connect to server address
print "Successfully connected to the server and ready to send some data"

data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")

s.send(data)



msg=s.recv(1024)            # Receives data upto 1024 bytes and stores in variables msg

print "Message from server : " + msg

s.close()                            # Closes the socket
# End of code

Теперь я получаю их в формате строки вместе с тегами \ n \ t.Как я могу интерпретировать отправленные логические значения и назначить их требуемым переменным в C ++.

Вот мой код на стороне сервера (C ++):

using namespace std;
//Server side
int main(int argc, char *argv[8080])
{
bool Style1;
    //buffer to send and receive messages with
    char msg[1500];

    //setup a socket and connection tools
    sockaddr_in servAddr;
    memset((char*)&servAddr, 0,sizeof(servAddr));
    servAddr.sin_family = AF_INET;
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
    servAddr.sin_port = htons(8080);

    //open stream oriented socket with internet address
    //also keep track of the socket descriptor
    int serverSd = socket(AF_INET, SOCK_STREAM, 0);
    if(serverSd < 0)
    {
        cerr << "Error establishing the server socket" << endl;
        exit(0);
    }


    //bind the socket to its local address
    int bindStatus = bind(serverSd, (struct sockaddr*) &servAddr, 
        sizeof(servAddr));
    if(bindStatus < 0)
    {
        cerr << "Error binding socket to local address" << endl;
        exit(0);
    }
    cout << "Waiting for a client to connect..." << endl;


    //listen for up to 5 requests at a time
    listen(serverSd, 5);


    //receive a request from client using accept
    //we need a new address to connect with the client
    sockaddr_in newSockAddr;
    socklen_t newSockAddrSize = sizeof(newSockAddr);


    //accept, create a new socket descriptor to 
    //handle the new connection with client
    int newSd = accept(serverSd, (sockaddr *)&newSockAddr, &newSockAddrSize);
    if(newSd < 0)
    {
        cerr << "Error accepting request from client!" << endl;
        exit(1);
    }
    cout << "Connected with client!" << endl;


        //receive a message from the client (listen)
        cout << "Awaiting client response..." << endl;
        memset(&msg, 0, sizeof(msg));//clear the buffer

        recv(newSd, (char*)&msg, sizeof(msg), 0);
        if(!strcmp(msg, "exit"))
        {
            cout << "Client has quit the session" << endl;

        }
        string str(msg);
        cout << "Client: " << msg << endl;
        cout << ">";
        string data = "Instructions Received \n";
        memset(&msg, 0, sizeof(msg)); //clear the buffer
        strcpy(msg, data.c_str());
        if(data == "exit")
        {
            //send to the client that server has closed the connection
            send(newSd, (char*)&msg, strlen(msg), 0);

        }
        //send the message to client
        send(newSd, (char*)&msg, strlen(msg), 0);

    //we need to close the socket descriptors after we're all done



    close(newSd);
    close(serverSd);

    cout << "Connection closed..." << endl;
    return 0;   
}

Я новичок, яспасибо, ребята, что помогли мне.

К вашему сведению - если я напечатаю строку в C ++ после получения, она выглядит следующим образом

"{\" A \ ": true, \" B \ ":false, \ "C \": false, \ "D \": false} "

Спасибо ВСЕМ за ваши предложения, и я попытался использовать json в C ++ и внес некоторые изменения

#include<iostream>
#include <jsoncpp/json/json.h>
using namespace std;

    void decode()
    {
         bool a,b,c,d;
        string text = "{\"A\":true,\"B\":false,\"C\":false,\"D\":false}";
            Json::Value root;
            Json::Reader reader;
            bool parsingSuccessful = reader.parse( text, root );
            if ( !parsingSuccessful )
                    {
                        cout << "Error parsing the string" << endl;
                    }


            const Json::Value mynamesA = root["A"];
            const Json::Value mynamesB = root["B"];
            const Json::Value mynamesC = root["C"];
            const Json::Value mynamesD= root["D"];


            cout<<mynamesA<<endl;
            cout<<mynamesB<<endl;
            cout<<mynamesC<<endl;
            cout<<mynamesD<<endl;


    }

    int main()
    {   
    decode();
        return 0;
    }

Теперь его печать

true
false
false
false

, как и ожидалось.Но я хочу присвоить эти значения bool a,b,c,d; Как я могу это сделать?

Ответы [ 2 ]

0 голосов
/ 12 октября 2018

Лучше контролировать, что на самом деле отправляется.

Эта строка:

data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")

весьма подозрительна: вы используете json.dumps в том, что уже является строкой в ​​кодировке json, когда онапредполагается использовать на объекте для создания строки json.

Я проверил это в интерактивном Python и получил:

>>> data= json.dumps("{\"A\":true,\"B\":false,\"C\":false,\"D\":false}")
>>> print(data)
"{\"A\":true,\"B\":false,\"C\":false,\"D\":false}"
>>> print([(i, hex(ord(i))) for i in data])   # control individual characters
[('"', '0x22'), ('{', '0x7b'), ('\\', '0x5c'), ('"', '0x22'), ('A', '0x41'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('t', '0x74'), ('r', '0x72'), ('u', '0x75'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('B', '0x42'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('C', '0x43'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), (',', '0x2c'), ('\\', '0x5c'), ('"', '0x22'), ('D', '0x44'), ('\\', '0x5c'), ('"', '0x22'), (':', '0x3a'), ('f', '0x66'), ('a', '0x61'), ('l', '0x6c'), ('s', '0x73'), ('e', '0x65'), ('}', '0x7d'), ('"', '0x22')]

Это доказательство того, что двойные кавычки обидели (") и обратная косая черта (\) были отправлены кодом Python.

Вероятно, вам нужно было:

data = '{"A":true,"B":false,"C":false,"D":false}'  # directly store the json string

или

# build the json string from a dict
data = json.dumps({'A': True, 'B': False, 'C': False, 'D': False})
0 голосов
/ 12 октября 2018

Если возможно, лучше использовать библиотеку JSON.Вот ссылка на учебник по RapidJSON, который вы можете использовать.

Если вы хотите написать решение самостоятельно, попробуйте следующее.

Самокодированное решение

Пройдите через строку, найдите все индексы "\"" и сохраните их в векторе.Если ни одно из значений в ваших парах ключ-значение не является строкой, то вы можете использовать это для поиска ключей.Итак, если у вас есть вектор с 3 и 7, то ваш ключ начинается с 4 и заканчивается на 6.

Вы можете использовать аналогичную логику для извлечения значений.Пройдите строку и найдите первое вхождение ":".После этого найдите первое вхождение «,», которое находится после индекса последнего найденного «:».Итак, если у вас есть 9 и 15, тогда ваше значение будет начинаться с 11 и заканчиваться на 14.

Просто обратите внимание, что когда вы достигнете последнего значения, оно будет заканчиваться на "]", как в вашем примере.Поэтому, если запятая не найдена, ищите «]» или, возможно, «».

bool findKeyIndices(string s, vector<int> & kIndices) {
    string substr = "\"";
    vector<int> indices;

    size_t index = s.find(substr, 0);

    while (index != string::npos) {
         indices.push_back(index);
         s.find(substr, index+1);
    }

    if (indices.size() % 2 != 0)
          return FALSE;

    for(int x =0; x < indices.size(); x++) {
         if(indices.at(x) % 2 == 0) {
               kIndex.push_back(++x);
         } else {
               kIndex.push_back(--x)
         }
    }

    return TRUE;
} 

bool findValIndices(string s, vector<int> & vIndices){
  string start = ": ", endOne = ",", endTwo = "]";
  vector<int> indices;

  size_t index = s.find(start, 0), backupIndex;

  while (index != string::npos) {
         indices.push_back(index);

         backupIndex = index;

         s.find(endOne, index+1);
         if(index != string::npos) {
              indices.push_back(index);
         } else {
              s.find(endTwo, backupIndex + 1);
              if(backupIndex != string::npos){
                    index = backupIndex;
              } else {
                    return FALSE;
              }

         }
    }

    if (indices.size() % 2 != 0)
           return FALSE;

    for(int x =0; x < indices.size(); x++) {
         if(indices.at(x) % 2 == 0) {
               vIndex.push_back(x + 2);
         } else {
               vIndex.push_back(--x)
         }
    }

 }

Решение могло бы быть проще, если бы вы могли предположить, что значения будут только истинными или ложными.В этом случае вы можете найти начальный индекс каждого ключа и начальный индекс всех подстрок «true» и «false».Затем вы можете выяснить, какой ключ связан с истиной или ложью.

Например, если у вас [2, 10] для начальных индексов ключей и начальный индекс для "true" был 4, то ключ, начинающийся с 2, будетсвязано с истиной, так как key1-start

Улучшение алгоритма

Приведенный выше алгоритм предполагал, что ни одно из значений в ваших парах ключ-значение не является строкой.Вы можете изменить приведенный выше код, чтобы вам не приходилось делать это предположение.

Вот шаги:

  1. Найти все вхождения "\" "и сохранить индексы в векторе (назовите его quoteIndices)
  2. Найти все вхождениязапятые и хранить индексы в векторе
  3. Найти индекс символа, который можно использовать для поиска конца последнего значения. В вашем примере в комментариях это было "]".

Определите пары значений ключа, используя следующее уравнение:

quote-open-indx

Теперь x может быть либо значением, либо строкой. Используйте процесс, подобный приведенному ниже, чтобы определить, что такое x, и соответственно проанализировать.

  1. Первый и второй индексы в quoteIndices всегда будут содержать ключ. Итак, вы можете предположить, что первый конечный индекс цитаты находится в quoteIndices.at (1). Скажем так, он равен 5.
  2. Если в quoteIndices есть другое значение, такое, что оно больше 5, но меньше первого cиндекс омма, тогда ваше значение является строкой.В противном случае это не так.
...