How to use variable string in a loop? - c++

I have written a program in which I save an image during a loop, with this command
writeimagefile("f:\\chkng\\otp.bmp",0,0,scn,scn);
This command is from graphics.h, which writes the image file in the given location. How should I save the image every loop with a different name? i.e otp1.bmp, otp2.bmp, otp3.bmp.

for (int i = start; i != end; ++i )
{
char filename[100];
sprintf(filename, "f:\\chkng\\otp%d.bmp", i);
writeimagefile(filename,0,0,scn,scn);
}

For this, I'm assuming that your loop is index based (counts from 0 to a max). I'm also assuming that you've included string.
int max = 1; //example
for(int i=0;i<max;i++){
std::string filename = "f:\\chkng\\otp" + std::to_string(i) + ".bmp";
writeimagefile(filename.c_str(),0,0,scn,scn);
}
Explanation:
What I'm doing here is using a loop, building a string with a number in the filename as requested, and calling your function with the c_str version (what your function wants) of the filename we just built.

For loops work well for counting things, and in many languages the example you're showing can be done by concatenating the count into the filename string. Try something like the following:
for (int count = startingNumber; count <= endingNumber; count++)
{
writeimagefile("f:\\chkng\\otp" + count + ".bmp",0,0,scn,scn);
}

Related

Character pointers messed up in simple Boyer-Moore implementation

I am currently experimenting with a very simple Boyer-Moore variant.
In general my implementation works, but if I try to utilize it in a loop the character pointer containing the haystack gets messed up. And I mean that characters in it are altered, or mixed.
The result is consistent, i.e. running the same test multiple times yields the same screw up.
This is the looping code:
string src("This haystack contains a needle! needless to say that only 2 matches need to be found!");
string pat("needle");
const char* res = src.c_str();
while((res = boyerMoore(res, pat)))
++res;
This is my implementation of the string search algorithm (the above code calls a convenience wrapper which pulls the character pointer and length of the string):
unsigned char*
boyerMoore(const unsigned char* src, size_t srcLgth, const unsigned char* pat, size_t patLgth)
{
if(srcLgth < patLgth || !src || !pat)
return nullptr;
size_t skip[UCHAR_MAX]; //this is the skip table
for(int i = 0; i < UCHAR_MAX; ++i)
skip[i] = patLgth; //initialize it with default value
for(size_t i = 0; i < patLgth; ++i)
skip[(int)pat[i]] = patLgth - i - 1; //set skip value of chars in pattern
std::cout<<src<<"\n"; //just to see what's going on here!
size_t srcI = patLgth - 1; //our first character to check
while(srcI < srcLgth)
{
size_t j = 0; //char match ct
while(j < patLgth)
{
if(src[srcI - j] == pat[patLgth - j - 1])
++j;
else
{
//since the number of characters to skip may be negative, I just increment in that case
size_t t = skip[(int)src[srcI - j]];
if(t > j)
srcI = srcI + t - j;
else
++srcI;
break;
}
}
if(j == patLgth)
return (unsigned char*)&src[srcI + 1 - j];
}
return nullptr;
}
The loop produced this output (i.e. these are the haystacks the algorithm received):
This haystack contains a needle! needless to say that only 2 matches need to be found!
eedle! needless to say that only 2 matches need to be found!
eedless to say that eed 2 meed to beed to be found!
As you can see the input is completely messed up after the second run. What am I missing? I thought the contents could not be modified, since I'm passing const pointers.
Is the way of setting the pointer in the loop wrong, or is my string search screwing up?
Btw: This is the complete code, except for includes and the main function around the looping code.
EDIT:
The missing nullptr of the first return was due to a copy/paste error, in the source it is actually there.
For clarification, this is my wrapper function:
inline char* boyerMoore(const string &src, const string &pat)
{
return (const char*) boyerMoore((const unsigned char*) src.c_str(), src.size(),
(const unsigned char*) pat.c_str(), pat.size());
}
In your boyerMoore() function, the first return isn't returning a value (you have just return; rather than return nullptr;) GCC doesn't always warn about missing return values, and not returning anything is undefined behavior. That means that when you store the return value in res and call the function again, there's no telling what will print out. You can see a related discussion here.
Also, you have omitted your convenience function that calculates the length of the strings that you are passing in. I would recommend double checking that logic to make sure the sizes are correct - I'm assuming you are using strlen or similar.

Byte length of a MySQL column in C++

I am using C++ to write a program for a MySQL database. I am trying to check a condition by comparing the length of a column (in bytes) to pass/fail. Here is the code:
while (row = mysql_fetch_row(result))
{
lengths = mysql_fetch_lengths(result);
num_rows = mysql_num_rows(result);
for (i = 0; i < num_fields; i++)
{
if (strstr(fields[i].name, "RSSI") != NULL)
{
if (lengths[*row[i]] == ??)
printf("current value is %s \t", row[i]);
}
}
}
So basically what i am trying to do is to look for the string "RSSI" in the columns and if the string is present i want to print that value. The values in each column are 3 bytes in length if present . So how do i check if lengths [*rows[i]] is 3 bytes in length? Thanks
According to the official MySQL documentation mysql_fetch_lengths returns an array of unsigned long with the lengths of the columns of the current row. Although the description isn't clear whether it's in bytes or something else, the example shown clarifies it.
So you should be checking directly to 3.
Also, there are some syntactic and semantic errors, and a possible refactoring in your code, among them the following:
Given the lengths variable is an array with the current rows' lengths, the expression lengths[*row[i]] should just be lengths[i] because i is the index of the current column.
The two ifs inside the for could be merged with the && operator for better readability.
Some variables are not defined or used correctly.
The code would look like this:
// Properly assign a value to fields variable.
fields = mysq_fetch_fields(result);
// Getting the number of fields outside the loop is better.
num_fields = mysql_num_fields(result);
while (row = mysql_fetch_row(result))
{
lengths = mysql_fetch_lengths(row);
for (i = 0; i < num_fields; i++)
if (strstr(fields[i].name, "RSSI") != NULL && lengths[i] == 3)
printf("current value is %s \t", row[i]);
printf("\n"); // For better output print each row in a new line.
}
You should really read the documentation carefully in order to avoid compilation or logic errors for using the wrong function.
I think there is a typo:
dev docs states:
(http://dev.mysql.com/doc/refman/5.0/en/mysql-fetch-lengths.html)
...
num_fields = mysql_num_fields(result);
lengths = mysql_fetch_lengths(result);
for(i = 0; i < num_fields; i++)
NOT
lengths = mysql_fetch_lengths(row);

Looping through a string, more than one char gets output

I am using C++ and SDL to make a game for fun.
I show the kill count on the screen by turning it into a surface using TTF_RenderText, which needs a const char*. There are gaps in between where I want the individual digits to be shown so I split up the string into individual chars.
This is the code I wrote to split up the string and render it on the screen:
SpareStream.str("");
SpareStream << Kills;
std::string KillsString = SpareStream.str();
for (int i = 0; i <= 4; i++)
{
if(i < KillsString.size())
{
std::string Cheat = KillsString.substr(i,i+1);
const char *KillsChar = Cheat.c_str();
Message = TTF_RenderText_Solid(EightBitLimit,KillsChar,White);
}
else Message = TTF_RenderText_Solid(EightBitLimit,"0",White);
ApplySurface(540 + (45 * i),(500 - HUD->h) + 24,Message,Screen);
}
However, when the kill count exceeds more than 100, this happens:
the tens and ones are shown where only the tens should be.
Why is this happening?
from my reference, std::string::substr is:
string substr (size_t pos = 0, size_t len = npos) const;
Thats a start/length pair, not start/end, so you need:
std::string Cheat = KillsString.substr(i,1);
btw, while start/length pairs are rarely use for containers in teh standard library, they were so universal for char* management in C that it does frequently turn up in the string classes.

Zipping increment file names using Zip Utils

Hello I've been using "Zip Utils" from
http://www.codeproject.com/Articles/7530/Zip-Utils-clean-elegant-simple-C-Win32
to zip files and folders. the easy thing is if the file name is known i just need to do something like this
HZIP hz; DWORD writ;
hz = CreateZip(_T("filename\\image1.zip"),0);
The problem is I get errors when trying to zip files by incrementing file names within a loop
int i= 0;
for(i=0; i<record; i++)
{
ZipAdd(hz,_T("doc"+i+1+".kml"), _T("filename\\doc"+i+1+".kml"));
}
This is not the most efficient way to write the code but it illustrates the concept. Use to_string( ... ) to convert a number to a string for concatenation. It requires a long long argument, not an int.
long long i;
string filepath1, filepath2;
for(i=0; i<record; i++)
{
filepath1 = "doc" + to_string(i + 1) + ".klm";
filepath2 = "GenFiles\\doc" + to_string(i + 1) + ".klm";
ZipAdd(hz,filepath1,filepath2);
}

Do I need more space?

I have code that is supposed to separate a string into 3 length sections:
ABCDEFG should be ABC DEF G
However, I have an extremely long string and I keep getting the
terminate called without an active exception
When I cut the length of the string down, it seems to work. Do I need more space? I thought when using a string I didn't have to worry about space.
int main ()
{
string code, default_Code, start_C;
default_Code = "TCAATGTAACGCGCTACCCGGAGCTCTGGGCCCAAATTTCATCCACT";
start_C = "AUG";
code = default_Code;
for (double j = 0; j < code.length(); j++) { //insert spacing here
code.insert(j += 3, 1, ' ');
}
cout << code;
return 0;
}
Think about the case when code.length() == 2. You're inserting a space somewhere over the string. I'm not sure but it would be okay if for(int j=0; j+3 < code.length(); j++).
This is some fairly confusing code. You are looping through a string and looping until you reach the end of the string. However, inside the loop you are not only modifying the string you are looping through, but you also change the loop variable when you say j += 3.
It happens to work for any string with a multiple of 3 letters, but you are not correctly handling other cases.
Here is a working example of the for loop that is a bit more clear it what it's doing:
// We skip 4 each time because we added a space.
for (int j = 3; j < code.length(); j += 4)
{
code.insert(j, 1, ' ');
}
You are using an extremely inefficient method to do such an operation. Every time you insert a space you are moving all the remaining part of the string forward and this means that the total number of operations you will need is in the order of o(n**2).
You can instead do this transormation with a single o(n) pass by using a read-write approach:
// input string is assumed to be non-empty
std::string new_string((old_string.size()*4-1)/3);
int writeptr = 0, count = 0;
for (int readptr=0,n=old_string.size(); readptr<n; readptr++) {
new_string[writeptr++] = old_string[readptr];
if (++count == 3) {
count = 0;
new_string[writeptr++] = ' ';
}
}
A similar algorithm can be written also to work "inplace" instead of creating a new string, simply you have to first enlarge the string and then work backward.
Note also that while it's true that for a string you don't need to care about allocation and deallocation still there are limits about the size of a string object (even if probably you are not hitting them... your version is so slow that it would take forever to get to that point on a modern computer).