Wednesday, August 22, 2007

Programs I Want to Write

A Shell script compiler

A To Do / Project manager

A better (robust, complete, elegant) compiler language

A March Madness tournament picker

A GUI for script writing

Monday, August 06, 2007

Keeping Safe Online

(Reposted by permission from Slashdot)

There is a tendency to want the government to do something about every problem, and the hassle of online scumbaggery is no exception. Individuals (and their guardians) need to take responsibility for their own protection, and not expect either the government to protect them (which it cannot) or for faceless strangers to be kind to them, which a tiny but significant portion will not.

Each of these steps solves roughly half of the remaining problems not solved by the previous ones.

  1. A fool and his unarchived data are soon parted. If you want it, make an offline copy of it.
  2. Switch to Linux, a Mac, or Anything But Windows. Most of the following only apply if this one won't work for you.
  3. Switch to Mozilla Firefox.
  4. Buy and install a firewall box. These are very easy to set up, and will save you a ton of trouble.
  5. Buy and install a virus scanner.
  6. Download and install Lavasoft Ad-Aware or similar spyware detector, even if your virus scanner says it provides that protection.
  7. Don't open email with attachments you aren't expecting, or respond to spam with so much as a single click. You have been warned.
  8. Stay away from porn sites. They're bad for your computer.
  9. Stay away from online games except those you know to be crap-free.
  10. You don't know that any of them are crap-free.
  11. Don't download commercial music except from commercial vendors to whom you pay a fee. Yeah, sucks to be us. But you get what you deserve, and if you're trying to get something for nothing, you'll give something for nothing in return.

So what do you do if your kids download some game, P2P app, or other crapware-laden piece of stupidity? Take away the computer. What if you have several kids, and you don't know who did it? Enlist their aid and hold them all accountable. Tell them that if any of them downloads crapware and the guilty party won't come forward, they all do their homework at the library (for a week or month or whatever).

Saturday, August 04, 2007

A.Rod's Big Day


"The Yankees' Alex Rodriguez became the youngest player to reach 500 home runs on Saturday."

Now, I know it's not really ambiguous, since hitting 500 home runs over the course of a career is still fairly rare.

Just saying.

Oh, and congrats Alex. Maybe now you can get a decent contract and start making some real money.

Friday, August 03, 2007

Making Strings Out of Numbers in C

A while back I was writing a C program and found I needed to convert numbers (integers) into strings. The language has no built-in facility for this. While sprintf() can be used, it has some drawbacks. Sprintf() only works with binary, octal, or hexadecimal bases, and the calling function has to calculate how much space each number needs. In any case, it didn't fit the bill at the time.

So I wrote itoa.c, which does the job. The file also contains a test wrapper with a main() function which may be useful in its own right. It will convert a decimal number on the command line to its representation in any base from 2 to 62.

One feature you may like or dislike is itoa's use of malloc() to get space for the resulting string. Itoa figures out how much space to allocate, which makes for twice the work for it but may save a large hassle in the calling function. I think that's an example of robustness, since it works correctly for any base, but your mileage, etc.

How do I know it works correctly for any base from 2 to 62? By inductive proof. The length for a string whose value is less than its base is 1 plus a null char for C, so the length is 2. So suppose the algorithm works for some base k. Since the same work is being done* when actually filling in the string with ritoa(), we see that working for base k means it works for base k+1. The boundary at 62 also works, so the algorithm is correct.

As always with C, be sure to garbage collect with free() when you no longer need the string.


/*
* Itoa.c
* Copyright 2004, Heal Consulting
* Published under the General Public License. See it at http://gnu.org
*/
/*
A sleeker version is available at:
http://www.cs.princeton.edu/courses/archive/fall96/cs126/examples/itoa.c
*/

#include /* only needed for main, fprintf error*/

static char *ItoaDigits =
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";

/*
* ritoa
* recursive itoa
*/
long int
ritoa(long int val, long int topval, char *s, int base)
{
long int n = val / base;
if (n > 0)
topval = ritoa(n, topval, s+1, base);
else
*(s+1) = '\0';
*s = ItoaDigits[ topval % base ];
return(topval / base);
}

/*
* itoa
* - mallocs a string of the right length
* - calls ritoa to fill in the string for a given base
*/
char * itoa(long int val, int base)
{
int len;
char *s,*buf;
long int t = val;
for (len=2; t; t /= base) len++ ; /* quickie log_base */
/* printf("len; %d\n", len); */

if((buf = (char *) malloc(len)) == NULL)
{fprintf(stderr,"out of memory in itoa\n"); exit(1);}
s = buf;
if (val < 0)
{
*s++ = '-';
val = -val;
};
len = (int) ritoa(val, val, s, base);
return(buf);
}

/*
* The test program may actually be useful.
* Converts a decimal number (long int) to a base you supply.
*/
int
main(int argc, char *argv[])
{
long int num = 0;
char *s;
int base = 10;
int maxlen = strlen(ItoaDigits);

if (argc >2) { base = atoi(argv[2]); };
if (argc >1) { num = atol(argv[1]); };
if ((argc <= 1) || (base > maxlen ) || (base < 2))
{
printf("Usage:\n\n%s [number [base]]\n", argv[0]);
printf("where number is in decimal and 2 <= base <= %d\n", maxlen);
exit(1);
}
s = itoa(num, base);
puts(s);
return(0);
}


After I wrote it, I found a slightly sleeker (base 2 through 16 only) version from an old Princeton CS class*.


* No, I didn't go to Princeton. That's why I waved my hands in the proof.