Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Properly written for-loops, normal and inverse, C++ basics [closed]

Tags:

c++

for-loop

For loops are trivial, right? Well I was wondering about some things, probably because I am a physcist and I havent had proper programming education. Lets use a the example of having a word string and we want to print the characters seperatelly, and later on reverse order.

Q1) Should we declare a variable for the size assign it and use it or call the size() function of the string, inside the for loop

string s = "asdf";
int size = s.size();

for (int i = 0; i<size; i++){
 cout<<s[i]<<endl;
}

//or

for (int i = 0; i<s.size(); i++){
 cout<<s[i]<<endl;
}

//Q2) If we want to print the characters inversed, which is more proper? Also, do i use new variable size again?

//A)

for (int i = size-1; i>= 0; i--){
 cout<<s[i]<<endl;
}

//B)

for (int i = size; i>= 0; i--){
 cout<<s[i - 1]<<endl;
}

//C)

for (int i = size - 1; i>= 0; i--){
 cout<<s[i]<<endl;

}

//D) // I have used this one in case i had to use i for another functionality where it has to be incremented. (ok sure a.size = s.size)

for (int i = 0; i<size; i++){
 cout<<s[size - i - 1]<<endl;
// cout<<a[i]<<endl;
}

Q3) Which is the most resource/time friendly?

Q4 and most important) Which is the most proper way for other people to understand and use it and anyway be part of bigger code structure (and not my own personal bullshit)

Q5) Did I forget any other ways?

Thanks for your help.

like image 722
thahgr Avatar asked Feb 13 '23 18:02

thahgr


2 Answers

The obvious answer is that you should be using iterators:-):

for ( auto current = s.cbegin(), end = s.cend(); current != end; ++ current ) {
    std::cout << *current << std::endl;
}

For the reverse order, use crbegin() and crend() instead of cbegin() and cend(). (And this is C++11. For earlier versions, you'll have to spell out the type of the iterator std::string::const_iterator and drop the c in the names of the functions.)

If you do want to do it with indexing (e.g. because you're iterating simultaneously through several different containers), the standard idiom for forward iteration would be:

for ( int i = 0; i != s.size(); ++ i )...

For reverse iteration, I'd use:

int i = s.size();
while ( i != 0 ) {
    -- i;
    //  ...
}

(Of course, if you're iterating over several containers simultaneously, you'll have extracted the sizes previously, to verify that they are equal. And you'ld use the extracted size, rather than calling s.size() again.)

like image 185
James Kanze Avatar answered Feb 15 '23 09:02

James Kanze


The general answer to your questions: you worry too much. Decent compilers have optimizers, which can do miracles. For instance, once I replaced all i < sth.size() with separate variable and it have actually slown down my program.

Secondly: why don't you simply run these versions 10^6 times and measure them? There are no simple answers to performance questions.

Thirdly: the general rule is: write code in such way, that it will be the most readable. So, for example, I'd implement the reverse loop in the following way:

for (int i = static_cast<int>(str.size()) - 1; i >= 0; i--)
    std::cout << str[i] << endl;

This code states the intention clearly: I want to go from the end of the string to its beginning. (of course, you may use iterators, which will make the code even more readable).

std::for_each(test.rbegin(), test.rend(), [=](char c) { std::cout << c << std::endl; });
like image 35
Spook Avatar answered Feb 15 '23 09:02

Spook