• XSS.stack #1 – первый литературный журнал от юзеров форума

Парсинг подстроки на C++

user_47

(L3) cache
Пользователь
Регистрация
25.06.2023
Сообщения
210
Решения
2
Реакции
93
Гарант сделки
2
Всем традиционный привет!

Это опять я с очередным г#вновопросом:(

Стоит задача спарсить подстроку по двум меткам. Первая метка обозначает начало подстроки. Вторая метка соответственно конец. Раньше исходную строку закидывал в string и всё работало. Теперь её засунул в char* чтобы закосить под профи:) Получил такой код:

#include <Windows.h>
#include <iostream>
#include <cstring>


char* pars_url(char* str, const char* substr_begin, const char* substr_end, int& error) {
// Ищем начальную подстроку
char* start = strstr(str, substr_begin);
if (start == nullptr) {
error = 1; // Начальная подстрока не найдена
return nullptr;
}

// Сдвигаемся по длине начальной подстроки
start += strlen(substr_begin);

// Ищем конечную подстроку
char* end = strstr(start, substr_end);
if (end == nullptr) {
error = 2; // Конечная подстрока не найдена
return nullptr;
}

// Вычисляем длину искомой подстроки
size_t length = end - start;

// Выделяем память для новой строки
char* result = new char[length];

// Копируем найденную подстроку в новую строку без использования strncpy
for (size_t i = 0; i < length; ++i) {
result = start;
}


error = 0; // Успешное выполнение
return result;
}

int main() {

char str[] = "adsfadsip^192.168.0.12^endsfgfdjfdkjf;alk";
const char* substr_begin = "ip^";
const char* substr_end = "^end";
int error;
char* result_ch = pars_url(str, substr_begin, substr_end, error);

if (error == 0) {
std::cout << "Extracted IP: " << result_ch << std::endl;
}
else {
std::cerr << "Error: " << error << std::endl;
}
return 0;
}


На выходе получаю вроде как достаточный результат.

Снимок.JPG

Только что это за еб#нь в конце в виде каких то кругляков? перепроверил размерность переменной result_ch, пробовал разные функции типа strncpy. Результат один. Грёб##ый С++, да простит меня его создатель за такие слова. Целый день убил на казалось бы простую вещь. Под конец дня одни эмоции накопились, сдаюсь.

Подскажите как вытащить подстроку без всяких непонятных излишеств?

P.S. Не могу код отредактировать. При клике по кнопке окрывается какое то левое окно. Так что сорян.
Снимок экрана_2025-05-11_19-19-15.png
 
Последнее редактирование:
У тебя проблема в том, как ты копируешь подстроку.

Вот этот кусок:
C++:
for (size_t i = 0; i < length; ++i) {
    result = start;
}

Это вообще не копирует строку, вместо копирования символов ты просто result = start делаешь.
Ни одного символа не переносишь, по сути, всё что ты выделил через new char[length], ты просто игнорируешь.

И даже если бы ты копировал правильно, ты не добавил '\0' в конец строки, а без него std::cout будет читать дальше в память, пока случайно не найдёт ноль. Отсюда и мусор в выводе.

Фикс -
C++:
char* result = new char[length + 1];

for (size_t i = 0; i < length; ++i) {
    result[i] = start[i];
}
result[length] = '\0';

Полная функция -
C++:
char* pars_url(char* str, const char* substr_begin, const char* substr_end, int& error) {
    char* start = strstr(str, substr_begin);
    if (!start) {
        error = 1;
        return nullptr;
    }

    start += strlen(substr_begin);

    char* end = strstr(start, substr_end);
    if (!end) {
        error = 2;
        return nullptr;
    }

    size_t length = end - start;
    char* result = new char[length + 1];

    for (size_t i = 0; i < length; ++i) {
        result[i] = start[i];
    }
    result[length] = '\0';

    error = 0;
    return result;
}

IP вытаскивается, мусора нет.
 
в этой строке не перенеслись почему то при копировании кода сюда.
result = start;

Не думал насколько критично '\0' дописывать в конце строки. Большая благодарность за подсказку!
Век живи, век учись!
 
Если уж ты решил юзать stl то нет смысла в таком парсинге - заюзай регекс из стандартной либы плюсовой

C++:
std::smatch match;
 std::string text = "adsfadsip^192.168.0.12^endsfgfdjfdkjf;alk";
 if (std::regex_search(text, match, std::regex("(\\d{1,3}(\\.\\d{1,3}){3})"))) {
     std::cout << match[1];
 }
 
Если уж ты решил юзать stl то нет смысла в таком парсинге - заюзай регекс из стандартной либы плюсовой

C++:
std::smatch match;
 std::string text = "adsfadsip^192.168.0.12^endsfgfdjfdkjf;alk";
 if (std::regex_search(text, match, std::regex("(\\d{1,3}(\\.\\d{1,3}){3})"))) {
     std::cout << match[1];
 }
Регулярки это последнее дело за что хотелось бы браться:(
 
Регулярки это последнее дело за что хотелось бы браться:(
Coming from a Perl old timer):
Literal matching -> repetition (* + ? {m,n}) -> greediness/laziness.
char classes / escapes -> anchors -> grouping/backrefs -> substitutions.
Stop here for 90% of needs: go deeper only if perf or nested matches force it.
 
Coming from a Perl old timer):
Literal matching -> repetition (* + ? {m,n}) -> greediness/laziness.
char classes / escapes -> anchors -> grouping/backrefs -> substitutions.
Stop here for 90% of needs: go deeper only if perf or nested matches force it.
боюсь что не совсем понял смысл сообщения:) даже переводчик не помог)
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх