C and C++ Timesaving Tips

Please support our C++ advertiser: Intel Parallel Studio Home
Closed Thread

Join Date: Apr 2004
Posts: 4,362
Reputation: Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future 
Solved Threads: 242
Team Colleague
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline Offline
long time no c

Re: C and C++ Timesaving Tips

 
0
  #11
Mar 22nd, 2005
Finding Array Size

Starting Out
When first starting out, we might write some code that initializes an array, perhaps does some manipulation, and then displays the results. It might look something like this (contrived example):
void foo(void)
{
   int array[10];
   int i;
   /* Initialize array. */
   for ( i = 0; i < 10; ++i )
   {
      array[i] = i;
   }
   /* Perform calculations. */
   for ( i = 0; i < 10; ++i )
   {
      array[i] *= 2;
   }
   /* Print array. */
   for ( i = 0; i < 10; ++i )
   {
      printf("%d,", array[i]);
   }
   putchar('\n');
}
We notice that if we want to change the array dimension, there are several lines of code to edit to make the change. Maintaining code like this is more difficult because in larger sets of code, finding all of the places that need to be changed becomes less trivial.

Using a Symbolic Constant
To avoid this, it is often recommended to use a symbolic constant instead.
#define SIZE 10

void bar(void)
{
   int array[SIZE];
   int i;
   /* Initialize array. */
   for ( i = 0; i < SIZE; ++i )
   {
      array[i] = i;
   }
   /* Perform calculations. */
   for ( i = 0; i < SIZE; ++i )
   {
      array[i] *= 2;
   }
   /* Print array. */
   for ( i = 0; i < SIZE; ++i )
   {
      printf("%d,", array[i]);
   }
   putchar('\n');
}
Now we can see we only need to change the #define to make a change to the array size. Unfortunately, purveyors of this wisdom often stop there.

The debugging hazard that this leads to often materializes itself in some header that is used to declare dozens of such constants. Some may like this, but I've found this to be a maintenance headache as well. For example, let's take a look at this code fragment.
  1. for ( i = 0; i < ASIZE; ++i )
  2. {
  3. printf("%d,", array[i]);
  4. }
Is it correct? You can't tell from this alone. You have to find the declaration of the array and double check. That alone is probably not that big of a deal, except when you have data that may be declared far away from this section of code.

Another Way
A cure is such an old piece of code, it's hard to imagine more people aren't aware of it long before they've learned a struct. It works by dividing the total size of the array (in bytes) by the size of the first element of the array (in bytes); this gives the number of elements. This is calculated at compile time.
void baz(void)
{
   int array[10];
   size_t i;
   /* Initialize array. */
   for ( i = 0; i < sizeof array / sizeof *array; ++i )
   {
      array[i] = i;
   }
   /* Perform calculations. */
   for ( i = 0; i < sizeof array / sizeof *array; ++i )
   {
      array[i] *= 2;
   }
   /* Print array. */
   for ( i = 0; i < sizeof array / sizeof *array; ++i )
   {
      printf("%d,", array[i]);
   }
   putchar('\n');
}
Now if you want to change the size of the array, you do it in only one place, and that place happens to be right where you define the array. If we saw the following fragment, is it correct?
  1. for ( i = 0; i < sizeof array / sizeof *array; ++i )
  2. {
  3. printf("%d,", array[i]);
  4. }
If array is an array in scope, yes.

Further Considerations
Some programmers may prefer to use a macro to make it easier to read; either of these are examples.
  1. #define ARRAYSIZE(x) (sizeof(x)/sizeof(*(x)))
  2. #define NELEM(x) (sizeof(x)/sizeof(x[0]))
So another way to write this is as follows.
void qux(void)
{
   int array[10];
   size_t i;
   /* Initialize array. */
   for ( i = 0; i < ARRAYSIZE(array); ++i )
   {
      array[i] = i;
   }
   /* Perform calculations. */
   for ( i = 0; i < NELEM(array); ++i )
   {
      array[i] *= 2;
   }
   /* Print array. */
   for ( i = 0; i < ARRAYSIZE(array); ++i )
   {
      printf("%d,", array[i]);
   }
   putchar('\n');
}
Use With Functions
Finally, if you pass "the array" to a function, you are really only passing a pointer to the first element of the array. In such cases, you should also pass a size parameter to the function.
void fum(int *array, size_t size)
{
   size_t i;
   /* Initialize array. */
   for ( i = 0; i < size; ++i )
   {
      array[i] = i;
   }
   /* Perform calculations. */
   for ( i = 0; i < size; ++i )
   {
      array[i] *= 2;
   }
   /* Print array. */
   for ( i = 0; i < size; ++i )
   {
      printf("%d,", array[i]);
   }
   putchar('\n');
}

int main(void)
{
   int myarray[25];
   foo();
   bar();
   baz();
   qux();
   fum(myarray, ARRAYSIZE(myarray));
   return 0;
}
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Quick reply to this message  
Join Date: Sep 2004
Posts: 7,717
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 733
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: C and C++ Timesaving Tips

 
0
  #12
Apr 7th, 2005
This one is entertaining, and useful too. We all know ("we" being C++ programmers who came from C or still use C extensively) that scanf will eat up a format nice and pretty:
  1. scanf ( "%d-%d-%d", &m, &d, &y );
If the input stream does not contain an integer followed by a '-' followed by an integer (shush Dave, and humor me), followed by a '-' followed by an integer, the call will fail. Sadly, this useful feature isn't available in C++ unless you use scanf. Using iostreams, you would be forced to do something painful like this (with suitable error handling, of course):
  1. cin>> m;
  2. if ( cin.peek() == '-' )
  3. cin.ignore();
  4. cin>> d;
  5. if ( cin.peek() == '-' )
  6. cin.ignore();
  7. cin>> y;
Wouldn't it be nice if we could just do this and be done with it?
  1. cin>> m >>"-">> d >>"-">> y;
Well, unfortunately it's not quite that easy. One could overload operator>> for a pointer to const char, but that kind of invades the implementation's personal space and therefore, is not portable.

To do it would be trivial though:
  1. istream& operator>> ( istream& in, const char *s )
  2. {
  3. while ( *s != '\0' && in && in.peek() == *s ) {
  4. in.get();
  5. ++s;
  6. }
  7.  
  8. if ( *s != '\0' )
  9. in.setstate ( ios::failbit );
  10.  
  11. return in;
  12. }
This was my solution (more or less). I didn't need something portable, and the benefit of clarity was a decisive factor. Looking toward portability though, just as a mental exercise, I also considered the manipulator approach:
  1. class scan {
  2. public:
  3. scan ( const char *init ): fmt ( init ) {}
  4. friend istream& operator>> ( istream& in, const scan& s )
  5. {
  6. while ( *s.fmt != '\0' && in && in.peek() == *s.fmt ) {
  7. in.get();
  8. ++s.fmt;
  9. }
  10.  
  11. if ( *s.fmt != '\0' )
  12. in.setstate ( ios::failbit );
  13.  
  14. return in;
  15. }
  16. private:
  17. mutable const char *fmt;
  18. };
It's almost as simple, but using it requires a bit more work:
  1. cin>> m >> scan ( "-" ) >> d >> scan ( "-" ) >> y;
On a similar note, I also found a similar manipulator useful. The following manipulator will discard all characters in the stream up to (and including) a user defined character delimiter:
  1. class moveto {
  2. public:
  3. moveto ( istream::int_type init ): ch ( init ) {}
  4. friend istream& operator>> ( istream& in, const moveto& d )
  5. {
  6. if ( in.rdbuf()->in_avail() > 0 )
  7. in.ignore ( numeric_limits<streamsize>::max(), d.ch );
  8.  
  9. return in;
  10. }
  11. private:
  12. istream::int_type ch;
  13. };
This is slightly more complicated than the usual "empty the buffer" call to ignore, designed to flush the stream of interactive input. That job could be performed with a simple moveto request:
  1. cin>> moveto ( '\n' );
But, moveto is useful in parsing as well.

One can easily imagine how useful these manipulators can be. Not only does the scanf behavior of eating a format work with standard input and output, a clever programmer could easily pair them with stringstreams, fstreams, or even custom streams to solve a whole slew of formatted parsing problems without hacking together something big and ugly.

And with a little bit of extra work, the scan manipulator can be extended to more accurately mimic scanf's format processing.
I'm here to prove you wrong.
Quick reply to this message  
Join Date: Mar 2004
Posts: 219
Reputation: BountyX is an unknown quantity at this point 
Solved Threads: 7
BountyX's Avatar
BountyX BountyX is offline Offline
Code Guru

Re: C and C++ Timesaving Tips

 
0
  #13
Apr 19th, 2005
I know this may not seem like a super time saving technique, but the way you name your variables will help save time and reduce compile time errors.. Having a conventional variable naming format will help keep things organized and easy to read.

Styles

Typically, most variable names get the every other word capitalized. Functions get the first letter of each word capitalized and constants get all of the letters capitalized.

Example:

Variable: First letter of every other word capitalized.
  • char theName[20];
Functions: First letter of each word capitalized .
  • void GetTheName();
Constants: All capitals
  • #define THENAME 20
Of course, sometimes choosing a good variable name can take a long time!
A Hacker's Mind:
"I thought what I'd do was, I'd pretend I was one of those deaf-mutes..." - J.D.Salinger
Quick reply to this message  
Join Date: Apr 2004
Posts: 4,362
Reputation: Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future 
Solved Threads: 242
Team Colleague
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline Offline
long time no c

Re: C and C++ Timesaving Tips

 
0
  #14
May 13th, 2005
Reading an Integer

This is in many FAQs elsewhere, so this is just my repackaging of it here.

C Version
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
   char response[32];
   /*
    * Prompt for input.
    */
   fputs ( "Enter your number: ", stdout );
   fflush ( stdout );
   /*
    * Read user response.
    */
   if ( fgets ( response, sizeof response, stdin ) != NULL )
   {
      /*
       * Attempt to convert user's response into an integer using strtol. The
       * second parameter to strtol allows for greater error checking if used.
       */
      int value = strtol ( response, NULL, 10/* radix or base */ );
      /*
       * No error checking was done, but attempt to display integer value.
       */
      printf ( "value = %d\n", value );
   }
   return 0;
}

/* my output
Enter your number: 12345
value = 12345
*/
C++ Version
#include <iostream>
#include <string>
#include <sstream>

int main(void)
{
   std::string response;
   /*
    * Prompt for input.
    */
   std::cout << "Enter your number: ";
   /*
    * Read user response.
    */
   std::cin >> response;
   /*
    * Attempt to convert user's response into an integer using a stringstream.
    */
   std::istringstream convert(response);
   int value;
   if ( convert >> value )
   {
      std::cout << "value = " << value << std::endl;
   }
   return 0;
}

/* my output
Enter your number: 456879
value = 456879
*/
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Quick reply to this message  
Join Date: May 2005
Posts: 232
Reputation: Dogtree is an unknown quantity at this point 
Solved Threads: 3
Dogtree's Avatar
Dogtree Dogtree is offline Offline
Posting Whiz in Training

Re: C and C++ Timesaving Tips

 
1
  #15
May 19th, 2005
Koenig Lookup

There are three ways to use a name nested in a namespace. Making the namespace open to the current scope with a using directive:
  1. using namespace std;
  2.  
  3. cout << "Hello world!" << endl;
Making only select names open to the current scope with a using declaration:
  1. // Make cout and endl available, but nothing else
  2. using std::cout;
  3. using std::endl;
  4.  
  5. cout << "Hello world!" << endl;
And explicit qualification of every name for every use:
  1. std::cout << "Hello world!" << std::endl;
It's best to never use the using directive unless you know for a fact that you won't have name clashes. That's usually not easily possible, and most people will suggest that you use explicit qualification all the time. The problem with that is explicit qualification is so verbose! Koenig lookup is a trick to shorten some of those names.

Here's a common example:
  1. vector<int> c;
  2.  
  3. // ...
  4.  
  5. std::copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, "\n"));
Koenig lookup says that if a function in a namespace takes an argument from the same namespace, the function need not be qualified because the compiler will look in that namespace for matching functions. So the following is legal C++:
  1. copy(c.begin(), c.end(), std::ostream_iterator<int>(std::cout, "\n"));
copy takes an ostream_iterator object as an argument. Because both ostream_iterator and copy are members of namespace std, Koenig lookup finds copy via ostream_iterator. A third of the namespace qualification has been removed from this line, and that is a big timesaver when it all adds up.
Quick reply to this message  
Join Date: May 2005
Posts: 82
Reputation: indianscorpion2 is an unknown quantity at this point 
Solved Threads: 1
indianscorpion2 indianscorpion2 is offline Offline
Junior Poster in Training

time saving tip for C programmers

 
0
  #16
Jun 23rd, 2005
suppose you guys are writing a program which uses a number of loops,
use a single variable for all the loop counters and declare the variable to be of register storage class. what happens is that the variable gets stored in the cpu registers and the loops get executed a lot faster.
the syntax is:
register int i;
hope this was helpful.
Quick reply to this message  
Join Date: Apr 2004
Posts: 4,362
Reputation: Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future 
Solved Threads: 242
Team Colleague
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline Offline
long time no c

Re: time saving tip for C programmers

 
0
  #17
Jun 23rd, 2005
Originally Posted by indianscorpion2
declare the variable to be of register storage class. what happens is that the variable gets stored in the cpu registers and the loops get executed a lot faster.
Rather ancient advice. Better advice is to improve the algorithm rather than micro-optimize.
http://www.eskimo.com/~scs/cclass/krnotes/sx7g.html
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Quick reply to this message  
Join Date: Apr 2004
Posts: 4,362
Reputation: Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future Dave Sinkula has a brilliant future 
Solved Threads: 242
Team Colleague
Dave Sinkula's Avatar
Dave Sinkula Dave Sinkula is offline Offline
long time no c

Re: C and C++ Timesaving Tips

 
0
  #18
Aug 23rd, 2005
Avoid Loop Control Using eof()

All over the 'net C++ programmers are taught to "read until end of file". This leads to the following (incorrect) idiom for loop control.
#include <iostream>
#include <fstream>

int main()
{
  std::ifstream file("file.txt");
  if ( file )
  {
     int i;
     while ( !file.eof() ) // bad!!
     {
        file >> i;
        std::cout << i << ' ';
     }
     std::cout << std:: endl;
  }
  return 0;
}
Run the above code with the following text file, "file.txt".
1 2 3 4 5 6 7 8 9 10
Your output will be like this.
1 2 3 4 5 6 7 8 9 10 10
Note the repeated 10.

What To Use Instead

Change your thinking to "while successfully reading input from a file" and know that the state of the stream -- indicating successful input or a failure -- is available from the input operation.
#include <iostream>
#include <fstream>

int main()
{
  std::ifstream file("file.txt");
  if ( file )
  {
     int i;
     while ( file >> i )
     {
        std::cout << i << ' ';
     }
     std::cout << std:: endl;
  }
  return 0;
}
The output is now correct.
1 2 3 4 5 6 7 8 9 10
Then, for amusement, change "file.txt" to this.
1 2 3 4 5 6 7 8 9 1A
Then run each of the above programs.

Another Example

A similar thing can be done when reading text.
#include <iostream>
#include <fstream>

int main()
{
  std::ifstream file("file.txt");
  if ( file )
  {
     char line[80];
     while ( file.getline(line, sizeof line) )
     {
        std::cout << line << '\n';
     }
  }
  return 0;
}
Copy this source into "file.txt" and it will print out this code.

Further Reading:
http://www.parashift.com/c++-faq-lit....html#faq-15.2
http://www.parashift.com/c++-faq-lit....html#faq-15.3
http://www.parashift.com/c++-faq-lit....html#faq-15.4
http://www.parashift.com/c++-faq-lit....html#faq-15.5
"One of the methods used by statists to destroy capitalism consists in establishing controls that tie a given industry hand and foot, making it unable to solve its problems, then declaring that freedom has failed and stronger controls are necessary." --Ayn Rand
Quick reply to this message  
Join Date: Oct 2004
Posts: 4,042
Reputation: vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice vegaseat is just really nice 
Solved Threads: 933
Moderator
vegaseat's Avatar
vegaseat vegaseat is offline Offline
DaniWeb's Hypocrite

Re: C and C++ Timesaving Tips

 
0
  #19
Aug 29th, 2005
Dave,
in your first example with
  1. while ( !file.eof() ) // bad!!
I could not get the extra 10
I am using Dev-C++ and Windows XP
May 'the Google' be with you!
Quick reply to this message  
Join Date: Sep 2004
Posts: 7,717
Reputation: Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute Narue has a reputation beyond repute 
Solved Threads: 733
Team Colleague
Narue's Avatar
Narue Narue is offline Offline
Code Goddess

Re: C and C++ Timesaving Tips

 
0
  #20
Aug 29th, 2005
>I could not get the extra 10
Put a newline at the end of the file.
I'm here to prove you wrong.
Quick reply to this message  
Closed Thread

This thread is more than three months old.
Perhaps start a new thread instead?
Message:



Similar Threads
Other Threads in the C++ Forum
Thread Tools Search this Thread



About Us | Contact Us | Advertise | DaniWeb | Acceptable Use Policy | RSS Feed

©2003 - 2009 DaniWeb® LLC