Understanding bracketless for/if combination in C/C++ - c++

I have the following code segment:
for ( SID_AND_ATTRIBUTES* it = ptg->Groups; end != it; ++it )
if ( EqualSid( it->Sid, pAdminSid ) )
break;
bIsAdmin = end != it;
Irritatingly, when step-by-step debugging in VS, the final line is executed with each of the for iterations. I was expecting the above code segment would behave identical to:
for ( SID_AND_ATTRIBUTES* it = ptg->Groups; end != it; ++it ) {
if ( EqualSid( it->Sid, pAdminSid ) )
break;
}
bIsAdmin = end != it;
Can somebody explain why this is not the case?

When there is "only one semicolon", there is no need for braces. Although I'm one of those people that like to put extra braces in my code, just in case. It never hurts, really...
As to the stepping behaviour, I've seen this too in both Visual Studio and Eclipse debuggers. I think it reflects the "end of the loop has to be on some line" - so if there is no ending brace, the last line within the loop contains the "is the loop finished" step. Annoying it is indeed.

Related

deleting a bunch of llvm instructions

I was wondering how we can delete a bunch of instructions in LLVM.
I tried the following ( based on a post from llvm-dev mailing list )
// delete all instructions between [start,end)
void deleteAllInstructionsInRange(Instruction* startInst,Instruction* endInst)
{
BasicBlock::iterator it(startInst);
BasicBlock::iterator it_end(endInst);
it_end--;
Instruction* currentInst ;
while(it != it_end )
{
currentInst = &*it;
// this cannot be done at the end of the while loop.
// has to be incremented before "erasing" the instruction
++it;
if (!currentInst->use_empty())
{
currentInst->replaceAllUsesWith(UndefValue::get(currentInst->getType()));
}
currentInst->eraseFromParent();
}
}
Everything works as expected except for the last iteration.
Anyone understand why ? ( I've tried using gdb but it gives a segfault error in
the last iteration)
The way your loop is built makes the inner code try to delete what is an invalid iterator: it == it_end. A simple if (it == it_end) continue; after it++ will help.
Not sure how LLVM iterables are built, but for the stl containers, erase will return an incremented iterator, so you won`t even need the weird loop. A brief look at the docs seem to confirm this.

Execution order of code with continue;?

I usually work with C#, so please bear with me. Also, the code was written by someone else.
The code essentially outputs some information to a text file, and for some reason, at midnight, the file was only exported with carriage returns and line separators (ie. no actual data).
After debugging it, I noticed that the debugger breaks on a continue;, but then anything after that line in the FOR loop (in init2) is not being executed.
Due to the complexity of the code, I had to remove most of it. But I've included where all the FOR loops are. I just need to know what the CONTINUE is doing that skips where the "important stuff" is being output.
Any help is appreciated. Thanks.
for ( init1; condition; increment ) {
for ( init2; condition; increment ) {
CODE;
for ( init3; condition; increment ) {
CODE;
if (condition) {
CODE;
}
CODE;
}
if (condition) continue; //Always breaks here
CODE; //Never breaks here
if (condition) { //Never breaks here, so important stuff is not output to file.
for ( init4; condition; increment ) {
fprintf_s(fp, "Output important stuff");
}
fprintf_s(fp, "\n");
}
}
if (statement) { //This code runs and the following is printed.
fprintf_s(fp, "----------------------------------------------------------\n");
}
}
It seems like the problem is your condition inside the if statement. I'm not sure that we can provide you further help if we don't see the actual code.

whats wrong with this c++ piece of code?

In this piece of code, in every iteration of while loop, a line is read from a file. The line is something like:
13,4636137,29464742,29464746,995560164
for every number specified in bold, the existence of that number as a key in a std::map is checked in a for loop. If the key exists, then the value is appended to the string. Then the string is written to the file.
If one of keys not exist in the map, then for that line nothing should be written to the file. (bool is_points_in_range)
But in practice, in the cases that the last point (outside of for loop) is not in key list, the program logic performs well.
Why the boolean operator does not change in for loop?
vector<string> res;
ifstream infile;
map<string, string> m;
while(infile.getline(buffer, LINE_BUFFER_LEN))
{
line=string(buffer);
res = SplitBySep(line, ",");
bool is_points_in_range=true;
string geo_file_line;
for (int i=2;i<res.size()-1;i++){
if ( m.find(res[i]) == m.end() ) {
is_points_in_range=false;
break;
} else {
geo_file_line= geo_file_line.append(m[res[i]]).append("^");
}
}
if ( m.find(res[res.size()-1]) == m.end() ) {
is_points_in_range=false;
} else {
geo_file_line= geo_file_line.append(m[res[res.size()-1]]).append("\n");
}
if (is_points_in_range){
fprintf(fp_geo, "%s",geo_file_line.c_str());
}
}
res.size()-1 is extremely dangerous. res.size() is an unsigned type, and subtracting one from it when res.size() is 0 is going to give you a very large unsigned integer due to wraparound.
So your program is essentially undefined when res is unpopulated.
I'm amazed your compiler didn't warn you. Do you have warnings switched off?
It looks like
m.find(res[i]) == m.end()
is never true.
Are you sure that this table is fulled properly? res[i]
It is better to ask that why this conditional statement does not work well?
We know that for obtaining that a key exists in a std::map, we can use:
if ( m.find("f") == m.end() ) {
// not found
} else {
// found
}
as indicated in this question.
But for
map<string, string> m;
this statement does not work well. I dont have any 29464742 key (I am sure), but when I search for this key the else part is executed. Also when I use m.count('29464742') , 1 is returned. I don't know why?
I corrected my code with this conditional statement:
if ( m["f"] == "" ) {
// not found
} else {
// found
}
This works for me and my problem is solved.

Alternative to break?

I'm pretty new to c++, and I was told not to use a 'break' statement. I was curious what are some alternatives to a 'break'? (using the example of the code below)
void remove_comments( ifstream& fileIn , ofstream& fileOut)
{
string line;
bool flag = false;
bool found = false;
while (! fileIn.eof() )
{
getline(fileIn, line);
if (line.find("/*") < line.length() )
flag = true;
if (! flag)
{
for (int i=0; i < line.length(); i++)
{
if(i<line.length())
if ((line.at(i) == '/') && (line.at(i + 1) == '/'))
break;
else
fileOut << line[i];
}
fileOut<<endl;
}
if(flag)
{
if(line.find("*/") < line.length() )
flag = false;
}
}
}
In my opinion using break is quite OK but if your task is to do the job without it then let's do this without it. The very same problem can be solved by using several differently structured codesnippets that use different control flow statements from C++. This problem can also be solved without break. I recommend you to break your function into a central function and several helper functions. Since I don't want to solve the problem instead of you I help just with instructions and with some "pseudo code"-ish something.
You have an input text that consists of commented and noncommented sections in turns. You want to do the following in a loop:
// I refer to non-commented text as "writable"
writable_begin = 0
while (writable_begin < text_len)
{
writable_end, comment_type = find_next_comment_begin(writable_begin);
write_out_text(writable_begin, writable_end);
if (comment_type == singleline)
writable_begin = find_singleline_comment_end(writable_end);
else
writable_begin = find_multiline_comment_end(writable_end);
}
You have to find out how to implement the helper functions/methods I used in my pseudo code, they can easily be implemented without break. If you solve the problem with helper functions you also get a much nicer looking solution than your current spaghetti code that uses complex control flow statements. Many bugs can easily hide in such code.
Tip: Your helper functions will search the end of the commented text in a loop but instead of break you can simply use return to exit the helper func with the result.
You could rewrite the loop
for (int i=0;
i < line.length() &&
!(i+1 < line.length() && (line.at(i) == '/') && (line.at(i + 1) == '/'));
++i)
{
fileOut << line[i];
}
fileOut<<endl;
Breaking is sometimes necessary -- without breaks you might crash into the stuff ahead and hurt yourself.
You may also hurt yourself by thinking poorly and then solving the problem in a cryptic manner that even you won't understand 6 months later.
Lastly -- whoever told you not to use a "break" .. give him a break -- never stop by him/her/it for advise.
BTW -- work on your indentation and curlies -- not good.
You could - and should - rewrite that loop. Mankarse showed one option, but that's got all those weird and difficult to understand conditions in the for loops.
You should learn to leverage the power of the standard library. For example, this code will remove all the characters that follow a C++ style line comment from the string stored in line:
// Find the first instance of two forward slashes in the line
// and return an iterator to that.
auto begin_comment = line.find("//");
// We found it! Remove all characters from that point on
if (begin_comment != std::string::npos)
line.erase (begin_comment, line.end());
fileOut << line << std::endl;
Consider how you could also take small chunks of code like that and put them into functions, which you will call to do work on your behalf. This will not only keep the code more readable, but it will get you into the habit of designing interfaces, which is a very important skill to have.
As a sidenote, your indentation is really bad and you must work on it. Look at this gem:
for (int i=0; i < line.length(); i++)
{
if(i<line.length())
if ((line.at(i) == '/') && (line.at(i + 1) == '/'))
break;
else
fileOut << line[i];
}
Which of those two if statements does the else match up against? Are you immediately and completely sure that you are right?
To be sure, the compiler doesn't need indentation and couldn't care less for it. But you do, and you will soon find out that as your code grows more complex, unless it's properly indented, it will be impossible to understand.

Resetting a loop in a loop

I am very curious to learn why the below code does not run in a continuous loop. And I'm also looking for some ways to achieve what I want to achieve--which is resetting a loop inside of the loop. I need to do this because I need to account for each element in a container. The reason why this is because I might start off in the middle, and need to loop back around to check the others / and need to recheck other information too. So on with my little test example:
for ( int i = 0; i != 10; i++ ) {
std::cout << std::endl << "TEST: " << i << std::endl;
if ( i++ == 10 ) {
i = 0;
} else {
i--;
}
}
Is there any particular reason why the above does not work? I am very interested in knowing why, so I can learn how everything works. This also leads into a much bigger problem I am facing. Which is the below code. I am using MSVC++ 2010 Express. Also, this is one thread, so other data is not accessing it. It is an unordered_map using STL. its size if 2 (i checked).
for (game_player_client_map::const_iterator it = gpc_map_ptr->begin(); it != gpc_map_ptr->end(); ++it) {
if ( it++ == gpc_map_ptr->end() ) {
cout << endl << "IT == gpc_map_ptr->end()" << endl;
it = gpc_map_ptr->begin();
} else {
it--;
}
}
I appreciate any feedback SO has to offer, and any new things to learn :-) If further information is needed I will provide. Thank you for your time.
Because the condition is checked before the body of the loop is entered. When i == 10, the loop is broken, before your code can execute at the time that i++ would evaluate to 10.
Remember that postincrement increments the variable and returns the old value. So if i is 9, i++ evaluates to 9 also, but the next time you use i, it will be 10.
If you want the variable to be incremented and use the new value in an expression, use preincrement:
if (++i == 10) // changes i to i + 1 and checks if the new value of i is 10
You could completely ditch the increment however, and just use i + 1. That way you don't have to de-increment i in the else block.
Your misunderstanding of postincrement is probably also the source of the bug in the second block of code you posted. You can change it to preincrement, or if it is a random-access iterator, you can do the same thing as mentioned above and check if it + 1 == gpc_map_ptr->end() and not have to de-increment it in the else block.