我试图找到一个解决方案,但我找不到任何解决我问题的方法。
我有一个C ++程序,它接收;WITH CTE AS(
SELECT *,
ROW_NUMBER() OVER(PARTITION BY o.id ORDER BY r.datetime) RN
FROM
vw_UserView_OpenAndClosed2016 o
INNER JOIN dbo.tblcallev r ON r.callid = o.id and r.eventtype = 1081
WHERE o.SchemeName = 'INDIS' AND o.SubSymptom = 'Care' AND Closed is NULL
)
SELECT *
FROM CTE
WHERE RN=1
变量(const char*
)和大小(filedata
)。此变量的内容为 csv格式。每个字段用';'分隔。内容也是动态的,并且可能具有更多或更少的内容,因为此变量表示一组日志。还有一个分隔符filesize
来表示换行符。
filedata的示例1:
\n
fildedata示例2:
const char* filedata =
"1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
"1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68";
如果您看到示例1只有2行,示例2有3行。我不知道我有多少行。我可以有2,3,200,1000等行,const char* filedata =
"1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
"1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
"1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";
变量保存所有内容。
所以我的目标是接收这个filedata
变量(我也可以访问filesize),对于每行我需要解析字段 1和2 (时间戳和数据)正常格式)。
预期输出(对于示例2):
filedata
在示例2中,我有3行,所以我需要迭代所有行,并且每行解析特定字段,非常类似于输出。
在此之后,我选择每个解析器字段并保存到对象列表(这部分已经实现。我只是在解析1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
时遇到了问题。
答案 0 :(得分:0)
您可以使用此正则表达式
const char *regex_str = "\\d{10};[\\d,-]{10} [\\d,:]{8}"; //verified in http://regexr.com/
然后从您的输入const char *
中找到所有正则表达式 - 从finding all regex获取帮助 - 用于Windows。
在mac os std :: regex中可能无法直接使用。需要在命令行中添加-stdlib=libc++
答案 1 :(得分:0)
这是使用您想要的输出的工作代码。我将这个SO answer用于我在重复标记中引用的SO问题。我对其进行了修改,以便新行字符\n
也可以作为分隔符。因此在代码中有两个while循环。
您必须将要拥有的列数(cols
)传递给split()
函数。您也可以(可选)传递应排除的列(filtCol
)。代码下的示例使用:cols = 5
和filtCols = (1 << 1) | (1 << 3)
,这意味着除了第2列和第4列之外,所有五列都应该被解析。仅仅第1,3和5列在结果向量中。我使用了一点模式,因为它的评估速度比列表/数组更快。
#include <string>
#include <sstream>
#include <vector>
#include <iterator>
#include <iostream>
template<typename Out>
void split(const std::string& s, char delim, size_t cols, size_t filtCol, Out result)
{
std::stringstream ss;
ss.str(s);
std::string item;
/* Two while loops two separate on new line first */
while (std::getline(ss, item))
{
std::stringstream ssLine;
ssLine.str(item);
std::string itemLine;
/* Parse line and separate */
size_t curCol = 0;
while (std::getline(ssLine, itemLine, delim))
{
/* Just add column is in range and is not excluded by */
/* bit pattern! */
if (curCol < cols && (~filtCol & (1 << curCol)))
{
*(result++) = itemLine;
}
++curCol;
}
}
}
std::vector<std::string> split(const std::string& s, char delim, size_t cols, size_t filtCol = 0)
{
std::vector<std::string> elems;
split(s, delim, cols, filtCol, std::back_inserter(elems));
return elems;
}
/* Example usage */
int main()
{
const char* filedataI =
"1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
"1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
"1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";
size_t colsRange = 5; /* Parse from col 1 to 5 (all five) */
size_t colsFiltered = (1 << 1) | (1 << 3); /* Exclude col 2 and 4 */
size_t colsPerLine = 3; /* 5 - 2 = 3 */
std::vector<std::string> strVecI = split(filedataI, ';', colsRange, colsFiltered);
for (size_t idx = 0; idx < strVecI.size(); ++idx)
{
if (idx > 0 && 0 == idx % colsPerLine)
{
std::cout << std::endl;
}
std::cout << "\"" << strVecI[idx] << "\" " << " ";
}
}
需要3
列的输出(5个,其中2个被排除:cols = 5
和filtCols = (1 << 1) | (1 << 3)
),我还打印了"
和其间的三个空格:
"1496843100" "000002D8" "0x23000CCD.VARIABLE67"
"1496843100" "000002D9" "0x23000CCD.VARIABLE68"
"1496843100" "000002DA" "0x23000CCD.VARIABLE69"
答案 2 :(得分:0)
使用<regex>
库
和regex_token_iterator
作为拆分器
首先分为\n
和;
代码:
const char* filedata =
"1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
"1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
"1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";
const char* begin_f = filedata;
const char* end___f = filedata + std::string( filedata ).size();
/* first of all split by newline */
std::vector< std::string > vec_str;
std::regex regex1( "\n" );
std::regex regex2( ";" );
std::regex_token_iterator< const char* > first( begin_f, end___f, regex1, -1 ), last;
vec_str.assign( first, last );
for( std::string str1 : vec_str ){
/* then split by semicolon ; */
std::regex_token_iterator< std::string::const_iterator > first( str1.begin(),str1.end(), regex2, -1 ), last;
int counter = 2;
while( first != last && counter-- ){
std::cout << *first++ << " ";
}
std::cout << '\n';
}
输出:
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
答案 3 :(得分:0)
这是使用std::find()
的解决方案,应该非常快速有效。我的想法是你有一个外部循环,找到每个连续的行结束'\n'
和一个内部循环,找到(在该范围内)每个连续的字段结束';'
在两个循环的核心,你有机会用列做任何你喜欢的事情:
char const* filedata =
"1496843100;2017-06-07 13:45:00;000002D8;2800;0x23000CCD.VARIABLE67\n"
"1496843100;2017-06-07 13:45:00;000002D9;2800;0x23000CCD.VARIABLE68\n"
"1496843100;2017-06-07 13:45:00;000002DA;2800;0x23000CCD.VARIABLE69";
auto filesize = std::strlen(filedata);
auto line_beg = filedata;
auto line_end = filedata + filesize;
for(; auto line_pos = std::find(line_beg, line_end, '\n'); line_beg = line_pos + 1)
{
auto field_beg = line_beg;
auto field_end = line_pos;
auto field_number = 0U;
for(; auto field_pos = std::find(field_beg, field_end, ';'); field_beg = field_pos + 1)
{
++field_number;
// select the field number you want here
if(field_number == 1 || field_number == 2)
{
// do something with the field that starts at field_beg
// and ends at field_pos
std::cout << ' ' << std::string(field_beg, field_pos);
}
if(field_pos == field_end)
break;
}
std::cout << '\n';
if(line_pos == line_end)
break;
}
<强>输出:强>
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
1496843100 2017-06-07 13:45:00
答案 4 :(得分:-1)
快速解决方案:
您可以使用类似的方法来从PHP中使用explode()函数。以下是如何在C ++ enter link description here中创建爆炸函数的答案。可能您必须修改已回答的代码才能将standard C string
作为输入。
然后,如果您将拥有自己的explode()函数版本,则可以执行std::vector<std::string> lines = explode(filedata,'\n')
之类的操作。
下一步将为每个行元素做std::vector<std::string> line_elements = explode(lines[i], ';')
。然后你将拥有每个单独的字段,你可以打印/解析你想要的东西。