Как извлечь подстроку из строки в C ++?

0

Я искал тысячи вопросов и ответов о том, что я собираюсь задать, но я все еще не нашел способ сделать то, что я собираюсь объяснить.

У меня есть текстовый файл, из которого я должен извлечь информацию о нескольких вещах, причем все они имеют следующий формат:

"string1":"string2"

И после этого есть больше информации, я имею в виду:

Текстовый файл выглядит примерно так:

LINE 1 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "string1": "string2" XXXXXXXXXXXXXXXXXXXXXXXXXX "string3": "string4" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX... ('\n')

LINE 2 XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX "string5": "string6" XXXXXXXXXXXXXXXXXXXXXXXXX "string7": "string8" XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX...

XXX представляет ненужную информацию, которая мне не нужна, а theEntireString (строка, используемая в примере кода) хранит всю информацию одной строки, а не всю информацию текстового файла.

Я должен сначала найти содержимое строки1 и сохранить содержимое строки2 в другую строку без кавычек. Проблема в том, что я должен остановиться, когда я обновляю последнюю цитату, и я не знаю, как именно это сделать. Я полагаю, что мне нужно использовать функции find() и substr(), но, несмотря на неоднократные попытки, мне это не удалось.

Я сделал что-то вроде этого:

string extractInformation(string theEntireString)
{
  string s = "\"string1\":\"";    
  string result = theEntireString.find(s);
  return result;
}

Но таким образом я полагаю, что храню в строке последнюю цитату и остальную часть строки.

  • 0
    Вам действительно нужна хорошая книга по программированию, и чтобы начать с основ .... но, find принимает аргумент именно той строки, которую вы хотите найти (возможно, "\": \ "") и возвращает позицию в поиске строка, где шаблон был найден. substr (не substring) занимает начальную позицию, за которой следует количество символов для выбора. Так что, возможно, std::string string1 = theEntireString.substr(1, theEntireString.find("\":\"")-1);
  • 0
    O (n ^ 2), если вы сканируете все, O (n) с алгоритмом сопоставления с образцом или подобным.
Теги:
string

5 ответов

0
Лучший ответ

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

#include <iostream>
using namespace std;

string extractInformation(size_t p, string key, const string& theEntireString)
{
  string s = "\"" + key +"\":\"";
  auto p1 = theEntireString.find(s);
  if (string::npos != p1)
    p1 += s.size();
  auto p2 = theEntireString.find_first_of('\"',p1);
  if (string::npos != p2)
    return theEntireString.substr(p1,p2-p1);
  return "";
}

int main() {
  string data = "\"key\":\"val\" \"key1\":\"val1\"";
  string res = extractInformation(0,"key",data);
  string res1 = extractInformation(0,"key1",data);
  cout << res << "," << res1 << endl;
}

Выходы:

val,val1
  • 0
    Ваше решение идет отлично, но в моем текстовом файле формат строковых данных = "XXXXX" ключ ":" val "XXXXX" ключ1 ":" val1 "XXXXXXX" вместо строковых данных = "XXXXX \" ключ \ ": \" val \ "XXXXX \" key1 \ ": \" знач1 \ "XXXXXXX"
  • 0
    Обратите внимание, что обратная косая черта необходима только для того, чтобы экранировать кавычки ". Так что "XXXXX\"key\":\"val\"XXXXX\"key1\":\"val1\"XXXXXXX" на диске станет string data = "XXXXX"key":"val"XXXXX"key1":"val1"XXXXXXX" в коде cxx. Если вы измените код для чтения файла или из stdin, вы увидите.
Показать ещё 1 комментарий
1

Функция "найти" просто дает вам позицию согласованной строки, чтобы получить результирующую строку, необходимую для использования функции "subst". Попробуй это

string start,end;
start = theEntireString.substr(1,theEntireString.find(":")-2);
end = theEntireString.substr(theEntireString.find(":")+2,theEntireString.size()-1);

Это решит вашу проблему

Удачи...

0

Вам не нужна строковая операция. Я надеюсь, что XXXXX не содержит никаких "", поэтому вы можете прочитать обе строки непосредственно из файла:

ifstream file("input.txt");
for( string s1,s2; getline( getline( file.ignore( numeric_limits< streamsize >::max(), '"' ), s1, '"' ) >> Char<':'> >> Char<'"'>, s2, '"' ); )
    cout << "S1=" << s1 << " S2=" << s2 << endl;

маленькая вспомогательная функция Char:

template< char C >
std::istream& Char( std::istream& in )
{
    char c;
    if( in >> c && c != C )
        in.setstate( std::ios_base::failbit );
    return in;
}
0
#include <regex>
#include <iostream>

using namespace std;

const string text = R"(
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string1":"string2"XXXXXXXXXXXXXXXXXXXXXXXXXX"string3"  :"string4" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
XXXXXXXXXXXXXXXXXXXXXXXXXXXX"string5":  "string6"XXXXXXXXXXXXXXXXXXXXXXXXXX"string7"  :  "string8" XXXXXXXXXXXXXXXXXXXXXXXXXXXX...
)";

int main() {
    const regex pattern{R"~("([^"]*)"\s*:\s*"([^"]*)")~"};
    for (auto it = sregex_iterator(begin(text), end(text), pattern); it != sregex_iterator(); ++it) {
        cout << it->format("First: $1, Second: $2") << endl;
    }
}

Output:

First: string1, Second: string2
First: string3, Second: string4
First: string5, Second: string6
First: string7, Second: string8
0

Два шага:

Сначала мы должны найти положение : и соединить строку на две части:

string first = theEntireString.substr(0, theEntireString.find(":"));
string second = theEntireString.substr(theEntireString.find(":") + 1);

Теперь нам нужно удалить "":

string final_first(first.begin() + 1, first.end() - 1);
string final_second(second.begin() + 1, second.end() - 1);
  • 0
    Но таким образом в строке «final_second» вы сохраняете оставшуюся часть строки и не останавливаетесь, когда вы повторяете последнюю цитату. Я отредактировал пост, объясняющий это, извините.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню