string.find function returning odd numbers - c++

I am trying to find the position at which a character was found.
const char* normalize(std::string path)
{
std::cout << "executed " << path << std::endl;
//"foo//\\\bar////bar2///../.\bar2" -- foo/bar/bar2
std::size_t found;
std::size_t found2;
std::size_t curchar = 0;
std::string final;
std::string buffer;
bool notdone = true;
while (notdone) {
//std::cout << "loop" << std::endl;
//find the current element
// can be / or \
found = path.find("/", curchar);
found2 = path.find("\\",curchar);
std::cout << found << std::endl;
SDL_Delay(2000);
if (found != std::string::npos && found2 != std::string::npos) {
if (found < found2){
//read from the curchar to the slash
if (curchar-found > 1){
buffer = path.substr(curchar,found-curchar-1);
//add to path
final = final + "/" + buffer;
}
curchar = found+1;
//buffer will be the file/component
}else{
if (curchar-found2 > 1){
buffer = path.substr(curchar,found2-curchar-1);
//add to path
final = final + "/" + buffer;
}
curchar = found2+1;
}
}else if(found != std::string::npos){
//std::cout << "loop2" << found == std::string::npos << std::endl;
//std::cout << "loop2 " << path.substr(curchar, 1) << std::endl;
if (curchar-found > 1){//
buffer = path.substr(curchar,found-curchar-1);
//add to path
final = final + "/" + buffer;
}
curchar = found+1;
}else if(found2 != std::string::npos){
std::cout << "loop3" << std::endl;
if (curchar-found2 > 1){
buffer = path.substr(curchar,found2-curchar-1);
//add to path
final = final + "/" + buffer;
}
curchar = found2+1;
}else{
std::cout << "finishing" << std::endl;
final = final + "/" + path.substr(curchar,path.size()-curchar);
notdone = false;
}
}
return final.c_str();
}
normalize("test/");
This code should print out '4', but it instead prints out 18. It prints out 18 in an infinite loop. However, if I use std::cout << path.find("/", curchar) << std::endl it does print 4. At first I thought that it wasn't actually returning std::size_t but I checked and it was.

Your following line is creating the problem
//find the current element
// can be / or \
found = path.find("/", curchar);
I ran on my linux terminal and GCC treated as next line as continuation of comment of above line.
basic.cpp:18:9: warning: multi-line comment [-Wcomment]
// can be / or \
^
basic.cpp: In function ‘const char* normalize(std::string)’:
basic.cpp:21:22: warning: ‘found’ may be used uninitialized in this function [-Wmaybe-uninitialized]
std::cout << found << std::endl;
^
Now due to above comment style, your next line(code) was treated as comment. As found was not initialized so it had garbage value which screwed up your logic as it did not go inside the path where you have reset the flag notdone.
However GCC or any other compiler should give warning(usage of uninitialize variable) and if we would have carefully read, we might have back-trace and understood the problem.
Solution for this would be to change the comment style as
/* // can be / or \ */

Related

Why is the line end character not included in the char*?

Function TrimRight takes a line and removes all spaces at the end.
void TrimRight(char *s) // input "somestring " (3 spaces at the end)
{
// Here s == "somestring \0" and strlen(s) == 14
int last = strlen(s) - 2;
std::cout << "Last1: " << s[last] << std::endl; // Last == ' '
while (s[last] == ' ')
{
--last;
}
std::cout << "Last2: " << s[last] << std::endl; // Last == 'g'
s[last + 1] = '\0';
// Here s == "somestring" and strlen(s) == 10
}
Questions is why s!= "somestring/0" after TrimRight(s)?
I'm using MVS 2017. Thanks.
You thought after TrimRight(s), s become something\0.
But in TrimRight(s) function, while loop just passed from last index.
Pass mean it didn't delete whitespace and \0.
so s is not something\0. It is something\0 \0 because of "just pass".

How to implement VERIFY command on NIST PIV cards?

I must be doing something wrong, but I can't see what.
I'm trying to get the VERIFY command to show the number of attempts remaining. (I was trying to enter the PIN as well, but cut back to this when I couldn't get anything to work.) Here's the code fragment that I've been trying:
for (unsigned int basebyte = 0x00; basebyte != 0x100; basebyte += 0x80) {
for (unsigned char add = 0x01; add != 0x20; ++add) {
smartcard::bytevector_t b;
b.push_back(0x00); // CLA
b.push_back(0x20); // INS
b.push_back(0x00); // P1
b.push_back(basebyte + add); // P2 ("the sensible ranges are 0x01..0x1F and 0x81..0x9F")
//b.push_back(0x00); // Lc field -- length of the following data field
b = card.rawTransmit(b);
if (!card.status()) {
cout << "Received error '" << card.status() << "'" << endl;
} else {
if (b[0] == 0x6a && b[1] == 0x88) {
// "Referenced data not found"
continue;
}
cout << " Attempts remaining (" << std::hex << (basebyte + add) << std::dec << "): ";
cout << std::hex;
for (smartcard::bytevector_t::const_iterator i = b.begin(), ie = b.end();
i != ie; ++i) cout << std::setfill('0') << std::setw(2) << int(*i) << ' ';
cout << std::dec << endl;
}
}
}
The rawTransmit function...
bytevector_t rawTransmit(bytevector_t sendbuffer) {
SCARD_IO_REQUEST pioSendPci, pioRecvPci;
if (mProtocol.value() == SCARD_PROTOCOL_T0) {
pioSendPci = pioRecvPci = *SCARD_PCI_T0;
} else if (mProtocol.value() == SCARD_PROTOCOL_T1) {
pioSendPci = pioRecvPci = *SCARD_PCI_T1;
} else {
std::ostringstream out;
out << "unrecognized protocol '" << mProtocol.str() << "'";
throw std::runtime_error(out.str());
}
DWORD rlen = 256;
bytevector_t recvbuffer(rlen);
mResult = SCardTransmit(mHandle, &pioSendPci, &sendbuffer[0],
DWORD(sendbuffer.size()), &pioRecvPci, &recvbuffer[0], &rlen);
recvbuffer.resize(rlen);
return recvbuffer;
}
(bytevector_t is defined as std::vector<unsigned char>.)
All the cards using protocol T0 return 0x6a 0x88 ("Referenced data not found") for all P2 values. All the cards using T1 do the same, except when P2 is 0x81 -- then they say 0x69 0x84 ("Command not allowed, referenced data invalidated").
The cards in question definitely DO have PINs, and I can verify the PIN in the "Security Token Configurator" program provided by the middleware vendor, so I know that the card, reader, and middleware stuff are all working.
It's probably obvious, but I'm new to smartcard programming. Can anyone give me a clue where I'm going wrong?
The Global PIN has ID 00 and the PIV Card Application PIN has 80 (hex) so your tests do not include the known PIV card PIN ID's.

Printing out HTML tags from a string

I am trying to print all the html tags that are contained inside a string. Something seems to be wrong with the logic of code here, I keep getting a never ending loop.
string fileLine;
string strToPush;
fileLine ="<html> sdad </b>as"; // My string that I want to find tags from
cout << fileLine << '\n';
while(!fileLine.length()==0)
{
if(fileLine.at(0)=='<')
{
strToPush = "";
while(!fileLine.at(0)=='>')
{
strToPush = strToPush + fileLine.at(0);
fileLine.erase (0);
}
cout << endl << "HTML Tag detected: " << strToPush <<endl;
}
else
{
fileLine.erase (0);
}
}
I suspect you are getting tripped by operator precedence. The line
while(!fileLine.length()==0)
is equivalent to
while( (!fileLine.length()) == 0 )
What you probably meant to do is:
while( !(fileLine.length() == 0) )
You can simplify that to:
while( !fileLine.empty() )
Similarly, change the line
while(!fileLine.at(0)=='>')
to
while ( fileLine.at(0) != '>' )

ifstream.read only reads half the file

I'm trying to make a simple image converter (ppm format to a custom one) and i'm having a problem with the ifstream.read method. Despite having this:
int rows,cols, maxV;
char header [100], *ptr;
std::ifstream im;
//open image in binary format
im.open(name.c_str(), std::ios::in | std::ios::binary);
if (!im)
{
std::cout << "Can't read image!" << std::endl;
exit(1);
}
//read the header of the image
im.getline(header, 3,'\n');
//test if header is P6
if ((header[0] != 80) || (header[1] != 54))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
}
//get next line for height and width
im.getline(header,100,'\n');
//dont read the comments
while (header[0] == '#')
im.getline(header,100,'\n');
//number of columns, rows
cols = strtol(header, &ptr, 0);
rows = strtol(header, &ptr, 0);
maxV = strtol(header, &ptr, 0);
const int rows1=rows;
const int cols1=cols;
Component * tbuffer;
const_cast<Component*> (tbuffer);
tbuffer = new Component[rows1*cols1 * 3];
im.read((char *)tbuffer, cols*rows * 3);
std::cout << tbuffer[3000000] << std::endl;
im.close();
It only reads 2.700.007 elements out of 4.320.000 of the image i'm trying to read. so tbuffer[3.000.000] will "cout" NULL. Am i missing anything?
Edit: About component:
typedef unsigned char Component;
Edit2: The image is 1200*1200 (cols*rows).
2.700.007 is the last index of the tbuffer with a value in it. the rest of the tbuffer remains empty
The PPM format that you read does not guarantee that the magic number P6 is followed ended by a newline, nor that the rest of the header is followed by a newline, nor that lentgh, heigth and maxV are on the same line.
But the main problem that you have is
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(header, &ptr, 0); // you start again at the begin of the header
maxV = strtol(header, &ptr, 0); // and another time !!
So your rows and maxV might not be the values in the file. You should --regardless of the other changes mentionned above-- rather use:
cols = strtol(header, &ptr, 0); // you start at the begin of the header
rows = strtol(ptr, &ptr, 0); // continue after the first number
maxV = strtol(ptr, &ptr, 0); // ...
But keep also in mind that you should not assume that the three are on the same line. And that there might be additional comments.
I propose you the following utility function to skip whitespace and comments according to the PPM format:
ifstream& skipwcmt(ifstream& im) {
char c;
do {
while ((c = im.get()) != EOF && isspace(c)) ;
if (isdigit(c))
im.unget();
else if (c == '#')
while ((c = im.get()) != EOF && c != '\n' && c != '\r');
} while (isspace(im.peek()));
return im;
}
You can use this function for reading the header as here:
// ...
// check magic number
im.read(header, 2);
if ((header[0] != 'P') || (header[1] != '6'))
{
std::cout << "Image" << name << "is not .ppm format" << std::endl;
exit(1);
}
skipwcmt(im) >> cols;
skipwcmt(im) >> rows;
skipwcmt(im) >> maxV;
if (!isspace(im.get())) { // folowed by exactly one whitespace !
std::cout << "Image" << name << "has a corrupted header" << std::endl;
exit(1);
}
// display the header to check the data
cout << "cols=" << cols << ", rows=" << rows << ", maxcol=" << maxV << endl;
Remark: I don't know if the files you have to read are guaranteed to have maxV<=255. In theory you could have values up to 65535 in which case you'd need to read 2 bytes for a color cmponent instead of one.

missing data in popen call

my program compiles without error and appears to run through all of the steps correctly. It is supposed to make a php call and return data. tcpdump does show the request going out so popen is being executed, but the receiving party never updates.
The only discrepancy I can find, is that the command variable appears to be missing data.
# .trol.o
market max price is 0.00638671 at position 0
php coin.php 155 0.006387
0.00638672
the second line in the output is the command I am sending to popen
cout << command << endl; -> php coin.php 155 0.006387
that number is supposed to be the same as the one under it 0.00638672
The number 6 and the number 2 have been chopped off somehow.
How do I get the correct data into my popen command?
code:
void mngr(){
//vector defs
vector<std::string> buydat;
vector<std::string> markdat;
vector<std::string> pricedat;
vector<std::string> purchaseid;
vector<double> doublePdat;
vector<double> doubleMdat;
doublePdat.reserve(pricedat.size());
doubleMdat.reserve(markdat.size());
char buybuff[BUFSIZ];
char command[70];
char sendbuy[12];
buydat = getmyData();
markdat = getmarketbuyData();
//string match "Buy" and send results to new vector with pricedat.push_back()
for(int b = 2; b < buydat.size(); b+=7){
if ( buydat[b] == "Buy" ) {
pricedat.push_back(buydat[b+1]);
}
}
transform(pricedat.begin(), pricedat.end(), back_inserter(doublePdat), [](string const& val) {return stod(val);});
transform(markdat.begin(), markdat.end(), back_inserter(doubleMdat), [](string const& val) {return stod(val);});
auto biggestMy = std::max_element(std::begin(doublePdat), std::end(doublePdat));
std::cout << "my max price is " << *biggestMy << " at position " << std::distance(std::begin(doublePdat), biggestMy) << std::endl;
auto biggestMark = std::max_element(std::begin(doubleMdat), std::end(doubleMdat));
std::cout << "market max price is " << *biggestMark << " at position " << std::distance(std::begin(doubleMdat), biggestMark) << std::endl;
if (biggestMy > biggestMark){
cout << "Biggest is Mine!" << endl;
}
else if (biggestMy < biggestMark){
//cout << "Biggest is market!";
*biggestMark += 0.00000001;
sprintf(sendbuy,"%f",*biggestMark);
sprintf(command, "php coin.php 155 %s",sendbuy);
FILE *markbuy = popen(command, "r");
if (markbuy == NULL) perror ("Error opening file");
while(fgets(buybuff, sizeof(buybuff), markbuy) != NULL){
size_t h = strlen(buybuff);
//clean '\0' from fgets
if (h && buybuff[h - 1] == '\n') buybuff[h - 1] = '\0';
if (buybuff[0] != '\0') purchaseid.push_back(buybuff);
}
cout << command << endl;
cout << *biggestMark << endl;
}
}
I would try to use long float format instead of float as the type of biggestMark should be evaluated as iterator across doubles. I mean try to change sprintf(sendbuy,"%f",*biggestMark); to sprintf(sendbuy,"%lf",*biggestMark);. Hope this would help.