I've added
and works now.Code:#include <sstream>
Actually, the it prints faster the output!
Thanks again
Printable View
I've added
and works now.Code:#include <sstream>
Actually, the it prints faster the output!
Thanks again
Hello 2kaud,
Having the blocks in a single string I was able to print 2 parameters for each block. Parameter 2 is fine
since I need to print it literaally, but for first one I need to convert it to decimal.
I've added the lines in red to main function but is not converting to decimal the first 6 numbers (3 bytes).
Thanks for any suggestion again.Code:int main()
{
FileFields ff;
bVec bv;
int blk = 0;
string block;
stringstream ss;
unsigned int x;
if (!ff.open("binary.txt")) {
cout << "Cannot open file!" << endl;
return 1;
}
while (ff.getField(bv)) {
conString(bv, block);
ss << hex << block.substr(0,6);
ss >> x;
cout << x << ","<< block.substr(6,16) <<endl;
}
return 0;
}
Not sure how you expect an unsigned int to hold a decimal value. :confused: But why do you have hex in there to pipe the data to the stringstream though? What's the point? A number is a number, you can format it to hex when you display that number as a string at a later time.
You mean like this
Code:int main()
{
FileFields ff;
if (!ff.open("binary.txt")) {
cout << "Cannot open file!" << endl;
return 1;
}
bVec bv;
for (int blk = 0; ff.getField(bv); blk++) {
cout << "block " << blk << endl;
//display(bv);
string block;
conString(bv, block);
istringstream iss(block.substr(0, 6));
unsigned long int x = 0;
iss >> hex >> x;
cout << x << ","<< block.substr(6,16) <<endl;
}
return 0;
}
Hello 2kaud,
Exactly. It works just fine. Thanks for the correction. I know a new function to operate on strings now.
What I have now replaces the use of first regex I posted in previous post, I'll try to follow thinking how to get the second pattern
if I not able to do it by regex.
I have this now:
Question: How to begin the loop from block 1? I have changed the "for loop" from blk=1, but still prints block 0. I don't need to process the block 0.Code:int main()
{
FileFields ff;
if (!ff.open("binary.txt")) {
cout << "Cannot open file!" << endl;
return 1;
}
bVec bv;
for (int blk = 0; ff.getField(bv); blk++) {
string block;
conString(bv, block);
istringstream iss(block.substr(0, 6));
unsigned long int x = 0;
iss >> hex >> x;
cout << x << ","<< block.substr(6,16)<< "," << block.substr(22,16) <<endl;
}
return 0;
}
Thanks again
ff.getField() will always return the blocks starting from block 0. If you don't want to process a particular block, just ignore it in the loop.
Code:for (int blk = 0; ff.getField(bv); blk++) {
if (blk == 0) continue;
cout << "block " << blk << endl;
......
}
Hello 2kaud,
Thanks for that. It works. I'm learning each time.
I was able to work in VisualStudio with regex and I've been able to use regex and obtain almost the output I want, the code below is having one of the blocks in str variable, now I'd like to convert this code in a function.
The code it works using "cout", but instead of print, I want to store each cout print in a variable in order to return this unique string(outstr) to main function. So main function would look like this:
The code I've been working with regex and works and which I'd like to convert in OutStr function is:Code:for (int blk = 0; ff.getField(bv); blk++) {
if (blk == 0) continue;
string block;
string outstr; //New output string taken as input the string "block"
conString(bv, block);
//Give block as entry string to new function OutStr and receive outstr as ouput string.
OutStr(block,outstr);
cout << outstr << endl;
}
Thanks in advance for any help.Code:#include "stdafx.h"
#include <iostream>
#include <string> //Only to pause display in Visual Studio
#include <regex>
#include <sstream> // std::ostringstream
using namespace std;
int main()
{
string str(
"00000253206445018934551f81474554768fffff0015000a4800015a000242000160000133000136"
"00013700015b00016600016500017700017800017e00016900006a00007900009300012200002100"
"010900010a00012600010200010400010500010600011000010800012b00002c00012d00012e0001"
"5500015600072a00002f0000300000310000ff7900800932c90688888000a000800935c906000080"
"00000080093cc906888880008000800943c90688888000800005900f0102000000308147526905ff"
"ffff00910f01020000013a81475269559fffff009310010c0000009f8147526905ffffff0101960f"
"010e000000eb81475269596fffff00970f01010006f69981475269563fffff00940e000100000100"
"0100ffff0000010195060003790001ea058200370601000001006500000002000002001800000003"
"00000300170000000400000400010000000500000500150000000a00ffff006500000007802ec918"
"009181475269539fffffff009181475269539fffff000103ca030808fecb0a000000000000000000"
"00cc0101811bc90b009181475269567fffffffca06000000000000cb0103cc0101");
regex re1("(.{6,18})(532064[^f]*).(814[^f]*)");
regex re2("ff79(0080.{4}c906)?(.*)?05(9.{32,34}(.*)?)940e(.{28})");
regex re3("(9[0-367a-b])([0-9][0-9a-f]|0[e-f]|0[1-9a])(0[0-9a])(..)(.{8})([^f]*)(f*)?(0[0-1])(0[0-1])?");
smatch m;
smatch n;
regex_search(str, m, re1); //Search regex1
unsigned long int p1;
stringstream s1;
s1 << hex << m[1];
s1 >> p1;
cout << p1 << "|" << m[2] << "|" << m[3]; //Instead of print I want to append in a variable
regex_search(str, n, re2); //Search regex2
string p2;
stringstream s2;
s2 << n[3];
s2 >> p2;
//Iterate to match all occurrences of regex3 in string "h"
regex_iterator<string::iterator> rit(p2.begin(), p2.end(), re3);
regex_iterator<string::iterator> rend;
//ptrdiff_t const match_count(distance(sregex_iterator(p2.begin(), p2.end(), re3),sregex_iterator()));
unsigned int p3;
int lim;
while (rit != rend) {
if (rit->str(9) != ""){
lim = 9;
}
else{
lim = 8;
}
cout << "|"; //Instead of print I want to append in a variable
for (int i = 4; i <= lim; i++){
stringstream s3;
if (i != 6 && i != 7 && i < lim){
s3 << hex << rit->str(i);
s3 >> p3;
cout << p3 << ","; //Instead of print I want to append in a variable
}
else if (i == 6){
cout << rit->str(i) << ","; //Instead of print I want to append in a variable
}
else if (i != 7 && i == lim){
s3 << hex << rit->str(i);
s3 >> p3;
cout << p3; //Instead of print I want to append in a variable
}
}
++rit;
}
//split by byte group 5 of regex2
string h1;
stringstream s10;
s10 << n[5];
s10 >> h1;
unsigned int j11;
for (int j = 0; j <= h1.size() / 2 - 1; j++){
cout << "|"; //Instead of print I want to append in a variable
stringstream s11;
s11 << hex << h1.substr(2 * j, 2);
s11 >> j11;
cout << j11; //Instead of print I want to append in a variable
}
//Only to pause display in Visual Studio
string var;
getline(cin, var);
///////////////////////////////////////////////////
}
You're almost got it. You can convert a string stream to a string by using .str(). So if you have a string called outstr, you can do outstr += s3.str() etc. With strings, you can use + to concatenate several strings and use += to append to an existing string so
becomesCode:stringstream s1;
s1 << hex << m[1];
s1 >> p1;
cout << p1 << "|" << m[2] << "|" << m[3];
and similar for the other places you want to append to a string variable.Code:stringstream s1;
s1 << hex << m1 << "|" << m[2] << "|" << m[3];
outstr += s1.str();
OutStr will be defined as
with the body taken from your test main function.Code:void OutStr(const string& block, string & outstr)
{
....
}
Thanks one more time 2kaud,
I've tested like you say in the way below:
It works almost the same but I'm nt sure why with this construction m[1] is not converted to decimal, for example, "000002" remains the same in the output when I'd like only "2".Code:stringstream s1;
s1 << hex << m[1] << "|" << m[2] << "|" << m[3];
outstr += s1.str();
Hello 2kaud,
I could fix the printing to decimal values.
Now I don't know why is giving error out of range.
The code with new function and main function is:
I continue seeing what happensCode:void OutString(const string& str, string & outstr) {
regex re1("(.{6,18})(532064[^f]*).(814[^f]*)");
regex re2("ff79(0080.{4}c906)?(.*)?05(9.{32,34}(.*)?)940e(.{28})");
regex re3("(9[0-367a-b])([0-9][0-9a-f]|0[e-f]|0[1-9a])(0[0-9a])(..)(.{8})([^f]*)(f*)?(0[0-1])(0[0-1])?");
smatch m;
smatch n;
regex_search(str, m, re1); //Search regex1
unsigned long int p1;
stringstream s1;
s1 << hex << m[1];
s1 >> p1;
outstr += to_string(p1) + "|" + m[2].str() + "|" + m[3].str();
regex_search(str, n, re2); //Search regex2
string p2;
stringstream s2;
s2 << n[3];
s2 >> p2;
//Iterate to match all occurrences of regex3 in string "h"
regex_iterator<string::iterator> rit(p2.begin(), p2.end(), re3);
regex_iterator<string::iterator> rend;
//ptrdiff_t const match_count(distance(sregex_iterator(p2.begin(), p2.end(), re3),sregex_iterator()));
unsigned int p3;
int lim;
while (rit != rend) {
if (rit->str(9) != ""){
lim = 9;
}
else{
lim = 8;
}
outstr += "|";
for (int i = 4; i <= lim; i++){
stringstream s3;
if (i != 6 && i != 7 && i < lim){
s3 << hex << rit->str(i);
s3 >> p3;
outstr += to_string(p3) + ",";
}
else if (i == 6){
outstr += rit->str(i) + ",";
}
else if (i != 7 && i == lim){
s3 << hex << rit->str(i);
s3 >> p3;
outstr += to_string(p3);
}
}
++rit;
}
//split by byte group 5 of regex2
string h1;
stringstream s10;
s10 << n[5];
s10 >> h1;
unsigned int j11;
for (int j = 0; j <= h1.size() / 2 - 1; j++){
outstr += "|";
stringstream s11;
s11 << hex << h1.substr(2 * j, 2);
s11 >> j11;
outstr += to_string(j11);
}
}
int main()
{
FileFields ff;
if (!ff.open("binary.txt")) {
cout << "Cannot open file!" << endl;
return 1;
}
bVec bv;
for (int blk = 0; ff.getField(bv); blk++) {
if (blk == 0) continue;
string block;
string outstr;
conString(bv, block);
OutString(block, outstr);
cout << outstr << endl;
}
//Only to pause display in Visual Studio
string name;
getline(cin, name);
///////////////////////////////////////////////////
return 0;
}
As I haven't got regex, I can't test and see what is going on. What line is giving the error?
Your code just assumes that strings and containers have at least n items without checking if this is the case. For example:
What if m is empty? What if it has less than 4 items (or 3 items)? What would happen if you attempt to access something that isn't there?Code:s1 << hex << m[1];
s1 >> p1;
outstr += to_string(p1) + "|" + m[2].str() + "|" + m[3].str();
What if n had less than 4 items in it? That n[3] would not be legal.Code:s2 << n[3];
I don't know what str() is, but from the looks of it, the argument seems to be an index of some sort. If so, what if there are less than 9 items in str()?Code:if (rit->str(9) != ""){
An out of range error is usually caused by doing just that -- accessing an item that is out of the range of available items. Your code is susceptible to this since it doesn't check for these things.
Also, you should step through the code with the debugger, and see where the program breaks down. That should be what you're doing while you're writing this program. You can't write programs if you aren't able to debug them.
Regards,
Paul McKenzie
Hello 2kaud and Paul,
Thanks for the comments and help.
I've been testing and I added some if statement in order to check if searched pattern exists, and now I don't get the error.
My issue now is that when I execute the program it runs very slow even if I disable the function that processes each block with regex (OutString). Running the program with the same binary I posted and without using the regex function it prints each block slow :(.
I'm attaching the program.exe and the source code I have so far.
I don't know if the info that is printed when compile or when debug could help to make it faster.
This is what I get.
When Compile
When run debugCode:1>------ Build started: Project: ReadBlockFromBinary, Configuration: Debug Win32 ------
1> Skipping... (no relevant changes detected)
1> ReadBlockFromBinary.cpp
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========
PS: To test the program, the binary.txt must be located in C:\.Code:'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Users\Philidor\Documents\Visual Studio 2013\Projects\ReadBlockFromBinary\Debug\ReadBlockFromBinary.exe'. Symbols loaded.
'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Windows\SysWOW64\ntdll.dll'. Cannot find or open the PDB file.
'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Windows\SysWOW64\kernel32.dll'. Cannot find or open the PDB file.
'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Windows\SysWOW64\KernelBase.dll'. Cannot find or open the PDB file.
'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcp120d.dll'. Cannot find or open the PDB file.
'ReadBlockFromBinary.exe' (Win32): Loaded 'C:\Windows\SysWOW64\msvcr120d.dll'. Cannot find or open the PDB file.
The program '[3332] ReadBlockFromBinary.exe' has exited with code 0 (0x0).
Thanks in advance.
Never time a Debug build. You must build a Release version and see what happens. According to your screenshot, you're building/running debug builds, and debug builds by their very nature are slow. Build a release version.
Second, you shouldn't be timing screen I/O, only raw processing. Remove the calls to write to the screen and then time things to see how long it takes to finish (and again, time a Release build, not Debug build).
Regards,
Paul McKenzie
Hello Paul,
You're correct. Thank you. I only did build (F7) and when I execute that *.exe file it runs faster. What I still see is that the last block it tooks more time to be processed. I think is because the last block contain a lot of filling zeros not only the bytes that really belongs to last block.
How can be modified the conString function in order to stop when end of file is reached? the end of file is the sequence FF 78.
Another question: Where should be removed the calls to the screen within visual c++ project? in the source code or is there some other files that automatically creates visual studio to print on screen?
Thanks in advance.