Разбить строку, полученную из файла, по пробелу и записать в переменные

322
24 октября 2017, 02:37

Всем привет!

Помогите разобраться, я запрашиваю файл *.txt с сервера

Он содержит 1 строку вида:

1 42500fd28e98c73a8b85c0b9ba0c0f57 ead084f7fe56a29ce4534117a7eb3fbf ea9bf8de9bf008dfc94ecde7260f4409

const char *response = httpClient.getString().c_str();
    httpClient.end();
    const char *esp_md5 = strchr(response, ' ') + 1;
    const char *fs_md5 = strchr(esp_md5, ' ') + 1;
    const char *mcu_md5 = strchr(fs_md5, ' ') + 1;
    ota_latest = strtol(response, NULL, 10);
    strncpy(ota_latest_esp_md5, esp_md5, 32);
    ota_latest_esp_md5[32] = '\0';
    strncpy(ota_latest_fs_md5, fs_md5, 32);
    ota_latest_fs_md5[32] = '\0';
    strncpy(ota_latest_mcu_md5, mcu_md5, 32);
    ota_latest_mcu_md5[32] = '\0';

Переменные:

long ota_latest = VERSION;
char ota_latest_esp_md5[33] = "";
char ota_latest_fs_md5[33] = "";
char ota_latest_mcu_md5[33] = "";

Как эти данные разбить по пробелу и записать в соответствующие переменные? Данный вариант не работает.

Answer 1

Первый вариант:

// суем:
#include <string.h>
#include "string_array.h"
....
string response = httpClient.getString().c_str();
httpClient.end();
// создаем обьект:
StringArray z;
// разбиваем:
z.explode(" ", response);
// используем как хотим, например:
for(int i = 0; i < z.length(); ++i){
   std::string s = z.get(i);
   printf("строка номер %d такая: %s", i, s.c_str());
}
....

string_array.h:

//---------------------------------------------------------------------------
#ifndef string_arrayH
#define string_arrayH
#include <vcl.h>
#include <string>
#include <stdio.h>
#ifndef AS
#define AS AnsiString
#endif
AnsiString s2as(std::string a){
  AS b = a.c_str();
  return b;
}
std::string s2as(AS a){
  std::string b = a.c_str();
  return b;
}
AnsiString std_str2as(std::string a){
  return s2as(a);
}
class StringArray{
public:
    StringArray(){
        len=0;
        allocated=false;
    }
    void explode(std::string delim, std::string cont){
      if(delim=="")return;
        signed int sum=0;
        signed int loc = - signed(delim.length());
        signed int locs=0;
        do{
            locs = loc+delim.length();
            loc = cont.find( delim, locs);
            sum++;
        }while(loc != std::string::npos);
        if(allocated){
            delete [] strs;
        }
        strs = new std::string[sum];
        len = sum;
        allocated=true;
        if(cont.find( delim, 0) == std::string::npos){
            strs[0] = cont;
            return;
        }
        // now parcing again and putting all the parts:
        sum = 0;
        loc = - signed(delim.length());
        do{
            locs = loc+delim.length();
            loc = cont.find( delim, locs);
            strs[sum] = cont.substr(locs, loc-locs);
            sum++;
        }while(loc != std::string::npos);
    }
  std::string implode(std::string delim=""){
      std::string r="";
      if(!allocated)return "ERROR:not allocated";
      int i;
      for(i=0;i<length()-1;++i){
         r+=strs[i]+delim;    
      }
      return r+strs[i];
  }
    void dump(){
        printf("\nelemelts num: %d\n", len);
        if(!allocated)return;
        for(int i=0;i<length();++i){
            printf("str[%d] = %s\n", i, strs[i].c_str());
        }
    }
  std::string str(int i){
    if(allocated && i>=0 && i < length())
      return strs[i];
    return "";
  }
  std::string get(int i){ return str(i); }
  int length(){ return len; }
private:
    bool allocated;
    int len;
    std::string    *strs;
};
// и как бонус - функция - точный аналог phpшной str_replace:
AS str_replace(AS search, AS replace, AS s){
  if(!s.Pos(search)) return s;
  StringArray sa;
  sa.explode(s2as(search), s2as(s));
  return s2as(sa.implode(s2as(replace)));
}
//---------------------------------------------------------------------------
#endif

Второй более изящный, мне больше нравится:

#include <iostream>
#include <vector>
#include <string>
// ...другие хедеры
std::vector<std::string> explode(std::string str, char delim = ' ');
void main() 
{
// .. твой код
  string response = httpClient.getString().c_str();
  httpClient.end();
  vector<string> v = explode(" ", str);
    for(int i=0; i<v.size(); i++)
        cout <<i << " ["<< v[i] <<"] " <<endl;
}
std::vector<std::string> explode(std::string str, char delim = ' ') {
    std::vector<std::string> result;
    std::stringstream stream(str);
    std::string buffer = "";
    while (std::getline(stream, buffer, delim)) {
        result.push_back(buffer);
    }
    return result;
}
Answer 2

Запустил данный код, и всё работает.

#include <stdio.h>
#include <string.h>
int main()
{
    char ota_latest_esp_md5[33] = "";
    char ota_latest_fs_md5[33] = "";
    char ota_latest_mcu_md5[33] = "";

    const char *response = "1 42500fd28e98c73a8b85c0b9ba0c0f57 ead084f7fe56a29ce4534117a7eb3fbf ea9bf8de9bf008dfc94ecde7260f4409";

    const char *esp_md5 = strchr(response, ' ') + 1;
    const char *fs_md5 = strchr(esp_md5, ' ') + 1;
    const char *mcu_md5 = strchr(fs_md5, ' ') + 1;
    //ota_latest = strtol(response, NULL, 10);
    strncpy(ota_latest_esp_md5, esp_md5, 32);
    ota_latest_esp_md5[32] = '\0';
    strncpy(ota_latest_fs_md5, fs_md5, 32);
    ota_latest_fs_md5[32] = '\0';
    strncpy(ota_latest_mcu_md5, mcu_md5, 32);
    ota_latest_mcu_md5[32] = '\0';

    printf("1 - %s\n", ota_latest_esp_md5);
    printf("2 - %s\n", ota_latest_fs_md5);
    printf("3 - %s\n", ota_latest_mcu_md5);
    return 0;
}
Answer 3

Чтобы прочитать из файла разделённые пробелом значения в отдельные переменные, можно operator>>(std::basic_istream) использовать:

const size_t N = 33;
file >> ota_latest
     >> std::setw(N) >> ota_latest_esp_md5
     >> std::setw(N) >> ota_latest_fs_md5
     >> std::setw(N) >> ota_latest_mcu_md5;

Это работает для обычных файлов:

std::ifstream file("input.txt");

для строки:

std::string s = "1 42500fd28e98c73a8b85c0b9ba0c0f57 ead084f7fe56a29ce4534117a7eb3fbf ea9bf8de9bf008dfc94ecde7260f4409";
std::stringstream file(s);

В общем случае HTTP клиент может тело ответа также в виде потока отдать:

Poco::URI uri {"http://example.com/input.txt"};
Poco::Net::HTTPStreamFactory factory;
std::unique_ptr<std::istream> pFile(factory.open(uri));
// std::istream& file = *pFile;
READ ALSO
Ошибка при подключении файла

Ошибка при подключении файла

Добрый деньПытаюсь решить одну задачу, надо, чтобы читались данные из файла

360
Необычный ввод строки [требует правки]

Необычный ввод строки [требует правки]

Есть задача: вводится просто строка с цифрами и пробелами и задача вычленить из неё цифры для последующих с ними манипуляций(желательно в int)Например...

371
Версия приложения VS C++

Версия приложения VS C++

Где в VS можно указать версию приложения или библиотеки разработанной на С++?

212
Прохождение бинарного дерева (post-order)

Прохождение бинарного дерева (post-order)

Здравствуйте, как на с/с++ написать нерекурсивный обход бинарного дерева через стек методом post-order (сначала листья, потом корень)?

311