Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 5.00/4: Рейтинг темы: голосов - 4, средняя оценка - 5.00
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
1

Неправильная запись const char* в std::string

17.01.2019, 16:47. Показов 650. Ответов 14
Метки нет (Все метки)

Привет, делаю Web-Парсер на плюсах и Python (на Питоне только Web пока что). В данный момент занимаюсь запросами. Решил пойти по-простому пути:
Код
1) С помощью библиотек Питона, я создаю скрипт внутри C++
2) Этот скрипт совершает запрос, с помощью моей библиотеки для запросов на Питоне
3) Далее этот же скрипт создает временный файл, в который помещает ответ сервера
4) Завершаем работу интерпретатора, далее извлекаем данные файла в строку C++ таким образом:
    1. while (!temp_file.eof()) (знаю, что eof не самый лучший выбор, но в данном контексте все стабильно работает), порциями заносим в строку новые данные
    2. конкатенируем со строкой
5) Удаляем временный файл
На 4 пункте застопорился, а именно не могу понять, почему строка не может нормально записываться.
Отлаживал, смотрел, считывание верное, но именно запись ведется неверно.

Описал проблему, описал работу алгоритма, вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#define PART_SIZE     256
#define TEMP_FILENAME "temp.request"
 
//...
 
void  WebRequests::completeRequest() {
    if (!response.empty())  //std::string response
        response.clear();
 
    Py_Initialize();
 
    std::ostringstream python_code;
    python_code <<
        "from Parser.Python.Web.WebRequests import WebRequest as wr\n" <<
        "request = wr(('" << hostname << "', " << port << "))\n" <<
        "request.set_request('''" << request.str().c_str() << "'''.encode())\n" <<
        "response = request.get_response()\n" <<
        "temp_file = open('" << TEMP_FILENAME << "', 'tw')\n" <<
        "temp_file.write(response)\n" <<
        "temp_file.close()\n";
 
    PyRun_SimpleString(python_code.str().c_str());
 
    Py_Finalize();
 
    std::ifstream temp_file(TEMP_FILENAME, std::ios::binary);
    char* response_part;                                       //data processed on parts
 
    while (!temp_file.eof()) {
        response_part = new char[PART_SIZE];
 
        temp_file.getline(response_part, PART_SIZE);
        response += response_part;
 
        delete response_part;
    }
 
    temp_file.close();
    remove(TEMP_FILENAME);
}
Пробовал с std::ostringstream, точно такая же ерунда.

Добавлено через 2 минуты
Строка на выходе получается примерно такой:
Код
    response = "</html>nter>nginx/1.12.1</center>/center>d>ed, 01 Jan 2020 00:00:00 GMT"
Добавлено через 23 секунды
Как можно видеть, все шиворот-навыворот
0

Помощь в написании контрольных, курсовых и дипломных работ здесь.

Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.01.2019, 16:47
Ответы с готовыми решениями:

ошибка в программе (cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*')
int main() { string fileName, currWord, currMax = &quot;&quot;; cin&gt;&gt;fileName; ...

Std::string в const char*
можно ли std::string превратить в const char* и как это сделать?

Сравнение std::string с const char *
В структуре определено неявное преобразование в std::string и const char * и наоборот: public...

(std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&
astxx::manager::connection::connection(std::basic_string&lt;char, std::char_traits&lt;char&gt;,...

14
24 / 22 / 5
Регистрация: 13.11.2012
Сообщений: 49
17.01.2019, 17:15 2
Экранировать спецсимволы?
Цитата Сообщение от pavel2210057 Посмотреть сообщение
"request = wr((\'"
0
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
17.01.2019, 17:20  [ТС] 3
Pavell, повторяю, запрос проходит успешно, именно где-то в строках [26:39] затаилась проблема.

Добавлено через 58 секунд
Хотя ничего не отрицаю, возможно где-то еще накосячил, но точно не в кавычках. (насколько я знаю в Питоне одинарные и двойные различий не имеют, в отличии от PHP)
0
зомбяк
1533 / 1178 / 332
Регистрация: 14.05.2017
Сообщений: 3,824
17.01.2019, 17:30 4
Цитата Сообщение от pavel2210057 Посмотреть сообщение
где-то еще накосячил, но точно не в кавычках
Пишешь строку в коде С++, а не из файла считываешь, так что тут кавычки как раз влияют, их все надо экранировать:

C++
1
2
3
4
5
6
7
        "from Parser.Python.Web.WebRequests import WebRequest as wr\n" <<
        "request = wr((\'" << hostname << "\', " << port << "))\n" <<
        "request.set_request(\'\'\'" << request.str().c_str() << "\'\'\'.encode())\n" <<
        "response = request.get_response()\n" <<
        "temp_file = open(\'" << TEMP_FILENAME << "\', \'tw\')\n" <<
        "temp_file.write(response)\n" <<
        "temp_file.close()\n";
0
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
17.01.2019, 17:33  [ТС] 5
TRam_, вы можете быть бесконечно правы, но скрипт работает идеально! У меня ответ пишется в файл, я приостанавливал выполнение программы и проверял, что в файле. Там все красиво, как полагается. Полный ответ сервера.
0
2228 / 1731 / 865
Регистрация: 21.12.2010
Сообщений: 3,074
Записей в блоге: 11
17.01.2019, 17:37 6
неправильно удаляете delete[] response_part;
0
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
17.01.2019, 17:48  [ТС] 7
igorrr37, прокол нашел, но проблема не исчезла. Отладчиком прогнал по циклу: response_part принимает правильные значения на каждой итерации. Именно что-то с стринговой переменной...
0
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
17.01.2019, 18:19 8
В строковом литерале " ' " не обрабатывается как спецсимвол. Коментировать его надо, если '\''.

Хотя формально применение delete вместо delete[] является UB, на деле для POD типов для них в текущих реализациях компиляторов разницы нет. Так что это тоже не приводило к ошибке.

Добавлено через 24 минуты
Тут еще есть проблема, которая выплывет, если строка будет больше 255-ти символов, но в целом код выглядит валидно. Предлагаю просмотреть эволюцию переменной response между итерациями.
0
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
17.01.2019, 21:21  [ТС] 9
Цитата Сообщение от Mirmik Посмотреть сообщение
Тут еще есть проблема, которая выплывет, если строка будет больше 255-ти символов
Пока что не встречал ответы, в которых было бы больше символов в строке. Если конечно не найдется умник, который решит написать HTML-код страницы в одну строку.
Цитата Сообщение от Mirmik Посмотреть сообщение
Предлагаю просмотреть эволюцию переменной response между итерациями.
Смотрел еще до публикации поста. На каждой итерации, начиная со второй, она принимает неверное значение. Я потому и решил спросить на форуме, потому что это очень странное поведение, на мой взгляд.
Буквально пара итерации:
Код
    1 итерация:
        response_part = "HTTP/1.0 400 Bad Request"
        response =      "HTTP/1.0 400 Bad Request";

    2 итерация:
        response_part = "Server: ngjit"
        response =      "Server: ngjitBad Request"
(Специально отправил на сервер (cyberforum, кстати) пустой запрос, поэтому не смотрите на "Bad Request")
Как видите, 1 итерация проходит нормально, пустая строка + response_part стала равна response_part.
Но во 2 уже начинается беспредел: почему "HTTP/1.0 400 Bad Request" + "Server: ngjit" стало вдруг равно "Server: ngjitBad Request"?

Единственное, где я вижу возможную проблему, так это распределение в памяти. Хотя это было бы странно, но может барахлит итератор класса std::string. Это ну ооочень вряд ли (это все-таки std), но я уже не представляю просто.

Добавлено через 1 час 38 минут
Правда ни у кого нет идей?
0
15124 / 8122 / 1961
Регистрация: 30.01.2014
Сообщений: 13,808
17.01.2019, 21:23 10
pavel2210057, Прикрепите полученный скриптом файл сюда без изменений, будет проще.
0
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
17.01.2019, 21:36  [ТС] 11
DrOffset, обычный такой ответ с ошибкой запроса. Но ладно.
0
Вложения
Тип файла: txt temp.txt (405 байт, 8 просмотров)
Параллельный Кот
1902 / 825 / 349
Регистрация: 25.03.2016
Сообщений: 2,041
17.01.2019, 22:16 12
Уважаемый pavel2210057, научитесь пользоваться отладчиком. Если бы вы им воспользовались, то увидели бы, что строка формируется без проблем.
Неправильная запись const char* в std::string


А вы похоже сделали отладочную печать. Что пошло не так? А то, что строка содержит символы \r, или по другому - возврат каретки. При выводе в окно консоли этот символ выполняет возврат курсора в начало строки, и следующие символы начинают заменять ранее напечатанные. Вот пример демонстрации этого эффекта:

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <string>
using namespace std;
 
int main() {
    string s = "Hello \rGoodbye, Vasya!";
    cout << s << endl;
 
    return 0;
}
Проверьте, что напечатает эта программа. Но это будет точно не то, что вы видите в тексте программы.
1
techpriest
634 / 213 / 57
Регистрация: 27.02.2014
Сообщений: 1,180
17.01.2019, 22:55 13
Дополню. Наблюдаемый эффект связан с тем, что функция getlineизымает символы переноса строки. Поэтому в responce от \r\n остается только \r.
1
15124 / 8122 / 1961
Регистрация: 30.01.2014
Сообщений: 13,808
17.01.2019, 23:44 14
Цитата Сообщение от Mirmik Посмотреть сообщение
Наблюдаемый эффект связан с тем, что функция getlineизымает символы переноса строки. Поэтому в responce от \r\n остается только \r.
Дополню тоже. Я специально попросил файл, т.к. это показалось мне странным. getline - это текстовая функция и не должна оставлять \r в строке. Про виндовые переносы строк она знает и обрабатывает их корректно \r\n интерпретируются как \n. Но если посмотреть на файл в шестнадцатеричном редакторе, то будет видно, что переносы строк там кодируются не как \r\n, а как \r\r\n и именно поэтому в строку попадает "лишний" \r, который обеспечивает такой наблюдаемый эффект.
Чтобы исправить код, нужно сделать так:
C++
1
temp_file.getline(response_part, PART_SIZE, '\r');
1
60 / 27 / 24
Регистрация: 28.09.2017
Сообщений: 399
18.01.2019, 07:11  [ТС] 15
Цитата Сообщение от valen10 Посмотреть сообщение
научитесь пользоваться отладчиком. Если бы вы им воспользовались, то увидели бы, что строка формируется без проблем.
Я то как раз-таки умею им пользоваться, я выше показывал значение переменной на различных итерациях, так что не надо так говорить.
А вот все остальное, что писали вы и еще два добрых человека - верно. И правда надо было проверить файл в 16-ричном формате.
Теперь на всю жизнь запомню, спасибо огромное!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
18.01.2019, 07:11

Преобразовать const unsigned char* в std::string (или _bstr_t )
Здравствуйте старшие товарищи! Есть функция, которая возвращает результат типа const unsigned...

Запрошено преобразование от ‘const std::string*’ к нескалярному типу ‘std::string’
private: std::string firstName; }; std::string ClientData::getFirstName() const{ ...

ошибка error: cannot convert 'std::string {aka std::basic_string<char>}' to 'std::string* {aka std::basic_stri
на вод поступают 2 строки типа string. определить количество вхождений строки 2 в строку 1 ошибка...

Ошибка при компиляции "Cannot convert `std::string' to `const char*"
Подскажите пожалуйста.Компилятор указывает на 13-ой позиции на ошибку типа: cannot convert...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.