#c #c 11
Вопрос:
Я работаю над фрагментом кода и столкнулся здесь с небольшой проблемой. В целом проблема заключается в разделителе строк и разделении строки C std::.
Строка, которая у меня есть, это:
std::string nStr =
R"(
"0000:ae:05.2:
Address: 0000:ae:05.2
Segment: 0x0000
")";
Обычно вышеперечисленное намного больше и содержит гораздо больше записей данных.
Разделитель, который я установил, — это»:», так как это будет самый распространенный разделитель, который у меня есть в данных.
То, что я хочу получить, — это 2 строки, т. е. Строка 1 = Адрес и строка 2 = 0000:ae:05.2, но мне также нужно, чтобы 1-я строка обрабатывалась аналогично, поэтому в основном все должно начинаться со строки 1 = заголовок и строки 2 = 0000:ae:05.2
Мой код выглядит так на данный момент:
int main(int argc, char* argv[])
{
std::string nStr =
R"(
"0000:ae:05.2:
Address: 0000:ae:05.2
Segment: 0x0000
")";
std::string tLine1="", tLine2="";
//nStr = nStr.erase(nStr.find_last_not_of("nrt"));
const std::string delimiter = ": ", delim2=":";
std::string::size_type pos = nStr.find(delimiter);
std::string::size_type pos2 = nStr.find(delim2);
if(nStr.npos != pos){
tLine2 = nStr.substr(pos 1);
tLine1 = nStr.substr(0, pos);
}
else if(nStr.npos != pos2){
tLine1 = nStr.substr(0, pos2);
tLine2 = "blank";
}
else
std::cout << "Delimiter not specified!n";
Что это работает для разделителя «main»,»:», а не для «:». Также он не читает все разделители»:».
Мой вывод будет: tLine1= «0000:ae:05.2: Адрес tLine2= 0000:ae:05.2 Сегмент: 0x0000
Есть какие-нибудь мысли о том, как это можно сделать правильно? Или как подойти к этому лучше? Заранее спасибо.
Комментарии:
1. Я не уверен, какова ваша цель или в чем проблема. Вы ищете первое вхождение «: «и устанавливаете tLine2 для всего после разделителя, а tLine1 для всего перед разделителем. И, похоже, это то, что вы получаете. Возможно ли, что вы хотите сначала разделить строку на разрывы строк и проверить наличие разделителей для каждой строки?
2. Здравствуйте, мне нужно получить следующее: tLine1 = 0000:ae:05.2; tLine2=заголовок; tLine1 = «Адрес»; tLine2=0000:ae:05.2; tLine1 = «Сегмент»; tLine2=0x0000 Я думаю, что пропустил это в описании. Извинения.
Ответ №1:
Приведенный ниже код делает то, что вы хотите сделать.
#include<iostream>
#include<string>
int main(int argc, char* argv[])
{
std::string nStr =
R"(0000:ae:05.2:Address: 0000:ae:05.2 Segment: 0x0000
)";
std::string tLine1 = "", tLine2 = "";
const std::string delimiter = ": ";
size_t pos = 0;
while ((pos = nStr.find(delimiter)) != std::string::npos) {
tLine1 = nStr.substr(0, pos);
nStr.erase(0, pos delimiter.length());
tLine2 = nStr;
break;
}
std::cout << "tLine1 = " << tLine1<<"n";
std::cout << "tLine2 = " << tLine2<<"n";
}
Выход:
tLine1 = 0000:ae:05.2:Address
tLine2 = 0000:ae:05.2 Segment: 0x0000
Комментарии:
1. Возможно, объяснение того, почему этот код работает, в то время как исходный код не поможет. Или, по крайней мере, объясните, почему символы новой строки в исходной строке создают ошибку.
2. Это здорово. Боюсь, что я дал не самое лучшее описание. Извините. Цель состоит в том, чтобы разделить это следующим образом. tLine1: 0000:ae:05.2, а затем заголовок tLine2: Теперь, как вы можете видеть в моем R»(строка, в которой есть новая строка непосредственно после знака:, не похожая на стандартный разделитель a «: «Теперь все остальные следующие строки будут tLine1: «0000:ae:05.2: и tLine2: «Адрес», разделенный «: »
Ответ №2:
Хорошо, из того, что я могу понять из ваших комментариев, вы хотите разделить исходную строку на строки, а затем разделить отдельные строки, используя «:» в качестве разделителя. За исключением первой строки, которая имеет только одно значение. Таким образом, результирующая пара для этой строки должна иметь значение из строки и строковый литерал «заголовок».
#include <iostream>
#include <string>
#include <utility>
auto splitLine(const std::stringamp; line) {
using namespace std::string_literals;
auto delimiterPos = line.find(": ");
if (delimiterPos != std::string::npos) {
return std::make_pair(line.substr(0, delimiterPos),
line.substr(delimiterPos 2));
}
return std::make_pair(line.substr(1, line.size() - 2), "header"s);
}
int main(int argc, char* argv[]) {
std::string nStr =
R"(
"0000:ae:05.2:
Address: 0000:ae:05.2
Segment: 0x0000
")";
std::size_t newLinePos;
do {
newLinePos = nStr.find("n");
std::string line = nStr.substr(0, newLinePos);
nStr = nStr.substr(newLinePos 1);
// To ignore empty lines and the last line that just contains a double quote
if (line.size() == 0 || line == """) {
continue;
}
auto lines = splitLine(line);
std::cout << "line1: " << lines.first << "n";
std::cout << "line2: " << lines.second << "n";
} while (newLinePos != std::string::npos);
}
Я не уверен на 100%, какая часть каждой строки считается первым значением, а какая-вторым. Похоже, вы переключаете это между вопросом и каждым комментарием. Но вы должны быть в состоянии изменить это в соответствии со своим желанием.
Еще один аспект, который я не до конца понял, — это расположение исходной строки. Кажется, он начинается с нового символа строки. И конец новой строкой, за которой следует двойная кавычка. Я должен был поймать именно их.
И первая строка «заголовка» начинается с двойной кавычки и заканчивается двоеточием. Я просто ожидаю, что так будет всегда, и удалил первый и последний символ из указанной строки.
Было бы полезно, если бы у нас был лучший пример для входящих данных.
Комментарии:
1. Это абсолютно идеально. Спасибо.
2. Привет, могу я спросить, почему за заголовком стоит буква «s»? Никогда такого не видел, тбх …
3. В связи с
using namespace std::string_literals;
тем, что в начале функции она сообщает компилятору, что строковый литерал имеет не типconst char*
, а типstd::string
. Что гарантирует, чтоstd::make_pair(...)
возвращает один и тот же тип для обоих операторов возврата функции. В противном случае компилятор жалуется, что один возвращает astd::pair<std::string, std::string>
, а другой возвращает astd::pair<std::string, const char*>
.4. Спасибо за объяснение. Не знал, что тбх.