1

I want to loop from 33 - 47 and - 58 to 64 and 91 to 96 from ASCII table and then display all together , but I think i am doing it in the wrong way. how can I fix it?

I am using windows 8 with codeblocks as IDE

int main()
{
    for(int i=33; i<=47 ;i++){
        for(int j=58; j<=64;j++){
             for(int z=91; z<=96;z++){
                std::cout << (char)z;
            }
        }
    }
    return 0;
}

once the loop is done it should displayed like this

!"#$%&'()*+,-./:;<=>?@[]^_`{|}~

cyb3rpunk
  • 61
  • 7
  • 3
    You want a single stretch of output, but you have a triple *nested* loop. *Why did you nest the loops* ? Wouldn't it make more sense to have three *distinct* loops each covering one of the three segments you desire? – WhozCraig Feb 16 '19 at 00:14
  • I have three distinct loops will I need to join all together? right? – cyb3rpunk Feb 16 '19 at 00:19
  • *once the loop is done* -- That's your mistake -- you think you code one loop (if you use your technique). Doesn't it make more sense to print the first set of characters in a loop, then print the second set of characters in a loop, then print the third set of characters in a loop? Each one of those loops has nothing to do with the other -- they are all separate. – PaulMcKenzie Feb 16 '19 at 00:27
  • 1
    Code::Blocks has a GDB (Gnu DeBugger) front end that's not bad. If you want to see what your program is doing, step through the code and watch. – user4581301 Feb 16 '19 at 00:31

3 Answers3

5

The way that you have nested these loops every iteration of loop one will run the entirety of loop two, and every iteration of loop two will run the entirety of loop three.

Since you only want a single output string you can achieve what you want with three separate loops.

int main()
{
    for(int i=33; i<=47 ;i++)
    {
        std::cout << (char)i;
    }
    for(int j=58; j<=64;j++)
    {
        std::cout << (char)j;
    }
    for(int z=91; z<=96;z++)
    {
        std::cout << (char)z;
    }
    return 0;
}

Hopefully this page can offer a more thorough explanation of for loop nesting https://www.tutorialspoint.com/cplusplus/cpp_nested_loops.htm

Kieran
  • 224
  • 1
  • 6
4

Lets go a step back...

A typical for loop looks like this (for details I refer you to cppreference):

for ( init; condition; increment) {
    loop-body
}

and is equivalent to:

{
    init;
    while(condition) {
        loop-body
        increment
    }
}

Everything you put in the loop body will be executed repedeatly until the condition is false (ie while it is true). For example in

for (int i= start; i < stop; ++i) foo(i);

the function foo will be called (stop-start)-times.

Your code

To see what your code is actually doing you can add some couts

int main() {
    for(int i=33; i<=47 ;i++){
        for(int j=58; j<=64;j++){
            for(int z=91; z<=96;z++){
                std::cout << "i = " << i;
                std::cout << "j = " << j;
                std::cout << "z = " << z;
            }
        }
    }
}

or use a debugger.

Nested Loops

To be clear: You do not need to nest the loops in your code and (nested) loops are not something desireable in general. That being said, just a random example where you could use a nested loop is to print a rectangle of *

int height = 5;
int width = 5;
for (int i=0; i<height; ++i) { 
    for (int j=0; j<width; ++j) { 
        std::cout << "*";
    }
    std::cout << "\n";
}

Loops?

I want to loop from 33 - 47 and - 58 to 64 and 91 to 96 from ASCII table and then display all together

Just do one thing after the other

for (char c=33; c<48; c++) { std::cout << c; }
for (char c=58; c<65; c++) { std::cout << c; }
for (char c=91; c<97; c++) { std::cout << c; }

No Loops

once the loop is done it should displayed like this

!"#$%&'()*+,-./:;<=>?@[]^_`{|}~

It is not really clear why you want to loop in the first place. If you want to print that characters you can print them via

std::cout << "!\"#$%&'()*+,-./:;<=>?@[]^_`{|}~\n";

just note that you have to espace the " (ie put a \ in front).

Loops

If you do write loops, try to avoid magic numbers. Instead give your numbers meaningful names as in start/stop or height/width vs 33/48. When you can, use iterators instead of indexes. Range-based for loops even allow you to ignore the iterators, as in

std::string outp = "!\"#$%&'()*+,-./:;<=>?@[]^_`{|}~";
for (auto letter : outp) std::cout << letter;
463035818_is_not_an_ai
  • 109,796
  • 11
  • 89
  • 185
  • @cyb3rpunk Recommended reading: [What is a magic number, and why is it bad?](https://stackoverflow.com/questions/47882/what-is-a-magic-number-and-why-is-it-bad). in the case of characters there is an extra nasty surprise: Not all C++ implementations use ASCII encoding. – user4581301 Feb 16 '19 at 21:41
  • @cyb3rpunk consider `height` and `widht`, they are both `5`. If I had written `5` in the loops directly I could not tell the difference anymore between `5` and `5`. In the example they appear only once each, but if I had used the values elsewhere it would already be difficult to change one of the values but not the other. This problem does not exist when you give the values names. – 463035818_is_not_an_ai Feb 17 '19 at 03:45
  • @cyb3rpunk actually I consider maintenance a secondary problem. It hurts readability to have a `5` when you actually mean `widht` – 463035818_is_not_an_ai Feb 17 '19 at 03:47
2

You're dealing with three ranges of values, so you want a loop to go through the ranges. For each range, you want a loop to go through the values in that range.

You could do it like this:

int main()
{
    std::vector<std::pair<int, int>> v{{33, 47}, {58, 64}, {91, 96}};
    for (auto p : v)
    {
        for (int i = p.first; i <= p.second; i++)
        {
            std::cout << static_cast<char>(i);
        }
    }
    return 0;
}
Sid S
  • 6,037
  • 2
  • 18
  • 24