3
\$\begingroup\$

I'm learning C++ and here I've written a little toy program that is supposed to list all the arguments passed to it through the command line.

#include <iostream>;
using namespace std;

int main (int argc, char *argv[]) {
  for (int number = 1; number < argc; ++number) {
    cout << argv[number] << endl;
  }
  return 0;
}

It is possible to use indexing instead and rewrite it in the following way:

#include <iostream>
using namespace std;

int main (int argc, char *argv[]) {
  int i;

  for (int j = 1; j < argc; ++j) {
    i = 0;
    while (argv[j][i]) {
      cout << argv[j][i];
      ++i;
    }
    cout << endl;
  }
   return 0;
}

I personally like the first version more. It doesn't need one more variable and it doesn't need one more cycle, so making use of pointers here seems like a good idea: it helps improve readability and as far as I know performance.

Is this actually a good alternative to the second version that uses indexing? And if so, how could it be improved?

\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

Is this actually a good alternative to the second version that uses indexing? And if so, how could it be improved?

I'm not sure what you're asking here. Obviously the first version is fine; obviously the second version is pretty silly (because it does the same thing as the first version but in a more confusing and verbose way).

As for "using indexing", doesn't the first version also use indexing? What do you think argv[i] is, if not "indexing"? It sure seems like you've got the hang of "indexing" well enough. :)


Your second program is also silly in that it uses a while loop instead of a for loop, even though you have all three pieces of a for-loop (initialization, condition, and increment) in close proximity. Why didn't you use a for loop? Just for practice with different kinds of loops? In that case, I'd dock you points for not using a do-while loop! ;)


To nitpick as long as I'm here:

  • Everyone will tell you (so you might as well start listening now) that using namespace std is a bad habit. Write std::cout and std::endl explicitly.

  • You have a stray ; on line 1 — a transcription error, since the compiler wouldn't accept it if you actually tried to compile that.

  • Your second program uses saner loop index names: i and j. Naming a loop control variable number is more likely to confuse the reader than help them.

  • Explicit return 0 from main is unnecessary in C++ (and also in C, as of 18 years ago). Omitting it from simple programs like this can help the reader focus on the important stuff instead of the boilerplate.

Putting it all together:

#include <iostream>

int main(int argc, char **argv)
{
    for (int i = 1; i < argc; ++i) {
        std::cout << argv[i] << std::endl;
    }
}
\$\endgroup\$
5
  • \$\begingroup\$ Wow thank you a lot for the very informative reply! Well actually the first program was written by myself and the second one I copy-pasted from the textbook I'm reading...I consider myself an advanced programmer in Python and some other script languages but I'm new to C++, so yeah std::cout and std::endl are like from MODULE import FUNCTION in Python, but again it's what is written in the textbook which seems to be quite old...Thank you for all the tips. \$\endgroup\$
    – CodeFish
    Mar 21, 2017 at 10:29
  • \$\begingroup\$ Oh just noticed it, I meant to say using std::FUNCTION; in C++ is akin to from MODULE import FUNCTION in Python. If I'm not mistaken. \$\endgroup\$
    – CodeFish
    Mar 21, 2017 at 10:44
  • \$\begingroup\$ @CodeFish: C++'s name-lookup rules are fundamentally different from Python's, but yeah that's a good way to think about it. (1) using namespace std; cout << m; is like from std import *; cout(m). (2) using std::cout; cout << m is like from std import cout; cout(m). (3) std::cout << m is like import std; std.cout(m). My impression is that in Python: (1) is bad, (2) is okay/good, and (3) is good. In C++, especially for namespace std: (1) is bad, (2) is okay, and (3) is best. \$\endgroup\$ Mar 21, 2017 at 18:21
  • \$\begingroup\$ @CodeFish: C++ never does "runtime imports" at all, so the short answer is "NO." I left out something from my parallels: (1) #include <iostream> using namespace std;..cout << m; is like from std import *..cout(m). (2) #include <iostream> using std::cout;..cout << m; is like from std import cout..cout(m). (3) #include <iostream>..std::cout << m; is like import std..std.cout(m). The "import" (parsing of the std module) still happens only once at the top of the file. The only difference is how you're allowed to refer to the std.cout variable later. Does that help? \$\endgroup\$ Mar 21, 2017 at 22:41
  • \$\begingroup\$ oh silly me...that was a stupid question of mine...yeah indeed...the lib is called iostream and it is loaded only once. Thank you! \$\endgroup\$
    – CodeFish
    Mar 21, 2017 at 22:58
2
\$\begingroup\$

Everythin Quuxplusone said:

Let's give you a couple of other concepts to look up.

#include <iostream>
#include <algorithm>
#include <iterator>

int main (int argc, char *argv[]) {
  std::copy(argv + 1, argv + argc, std::ostream_iterator<std::string>(std::cout, "\n"));
}
  • Tip 1: Use algorithms rather than loops.
    Here: std::copy()
  • Tip 2: Algorithms use iterators that mark the beginning and end of stuff.
    Here: argv + 1 is the beginning
    and argv + argc points at the end.
  • Tip 3: Don't worry about std::ostream_iterator<std::string> yet.
    Just accept it prints your stuff.
\$\endgroup\$
3
  • \$\begingroup\$ Thank you a lot for the useful tips but they are too advanced for me at the moment hehe I first want to finish the textbook I'm reading to grasp the most basic things..but from Quuxplusone's answer I'm forced to draw the conclusion that the book is quite old and teaches some bad habits. \$\endgroup\$
    – CodeFish
    Mar 21, 2017 at 10:36
  • \$\begingroup\$ but yeah I think it would be the right thing to teach myself good habits from the beginning...thank you one more time. \$\endgroup\$
    – CodeFish
    Mar 21, 2017 at 12:14
  • \$\begingroup\$ I think describing this answer as "concepts to look up" is much more accurate than describing it as "tips". ;) Writing a simple program like this in terms of ostream_iterator is IMHO on the same level as writing "hello world" as for (auto&& ch : "hello world!\n") std::cout.put(ch);. In both cases, @CodeFish would do well to study these examples until he understands them thoroughly; but also in both cases, if anyone seriously writes code like this for hello world, I wouldn't work with them. ;) \$\endgroup\$ Apr 2, 2017 at 18:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.