Anti-nuisance lawsuit warning: The purpose of these notes is to remind me, Zoegond, of stuff or to help me work stuff out. They may contain mistakes.

Quick

  • ($a, $b....) = unpack("A2A7...", $packed)
  • push( array, list )

Monday, October 31, 2011

Perl mkdir, make_path and mkpath

mkdir can only create directories in directories that already exist. So if you say

mkdir("c:\\season1\\unearthly\\ep1\\caps");

it will only work if directory c:\season1\unearthly\ep1 already exists.

File::Path::make_path() will create a directory and any necessary ancestor directories (must use mkpath() instead on Perl 5.10 and possibly other versions earlier than 5.14).

NB it's File::Path:: not File::Path-> - the latter will give you a misleading error "mkdir File::.: Invalid argument; The filename, directory name, or volume label syntax is incorrect" .

Wednesday, October 26, 2011

Perl and large integers

Trying to get a straight answer to the question 'What is the largest integer Perl can handle on Win32?' and failing, I decided to ask Perl, eventually ending up with the questions

perl -e "print 2**49+1"
perl -e "print -2**49-1"


and getting precise answers.

So on my 32-bit Windows the answer is "more than 2^49 and less than 2^50".

readdir

readdir returns bare file names without any path. Also there will be two results "." and ".." representing current and parent directories (unless the directory is the drive root, in which case on Win32 neither seems to be present, but since everyone throws both of them away it probably doesn't matter).

Monday, October 24, 2011

Combo box dropdown failure

A combo box won't drop down unless the vertical size you gave it includes enough space for (a) the edit box bit and (b) at least one row (?) of the drop-down bit.

So if you're using, say, a constant YHIGH for controls with one line of text, your combo box height should be in the region of YHIGH * number of lines to show in the drop down. Don't worry, it won't expand the edit box bit to take up all that space.

(Thanks to this post)

CreateProcess

Using CreateProcess opens two handles (one for a thread, one for a process) which are stored by Windows in the PROCESS_INFORMATION structure that you supplied with CreateProcess.

You should close both if the child process exits while your program is still running - but it also seems you can close them any time before this without causing your child process to exit. (Obviously then you can't communicate with the child). I'd want to do this if I'd started a process so that the user could interact with it.

Pointers to member functions

A pointer to a member function returning int, say, is not the same type as a pointer to a function returning int.

This buggers up any attempt to do anything simple like supplying a pointer to one of your class members where Windows expects a WNDPROC.

Don't think there is any easy way round this. This explains some more complicated ways round it.

Saturday, October 22, 2011

Perl system and synchronicity

system("calc");

runs the Calculator and waits till the user closes it.

system("cmd /c start calc");


runs the Calculator and continues with your script without waiting.

system("cmd /c start /wait calc");


has the same effect as system("calc").

Friday, October 21, 2011

AAD and AAM

You can use AAD and AAM (ASCII adjust for Division/Multiplication) to do quick decimal-binary conversions for numbers 0-99.

Suppose AX = 0506h (representing decimal digits 5 and 6 for the decimal number 56)

then AAD will set AX = 0038h (56d)

and then AAM will set AX = 0506h.

So AAD converts 2 digits in AX to binary in AL, and AAM converts binary in AL to 2 digits in AX.

(Once you've got your two digits you can easily turn them into ASCII characters by adding 30h to each byte and adjusting for the characters between '9' and 'A').

Tuesday, October 18, 2011

Endianness

I'm surprised I could have forgotten this but - if you have the following

mem: dw 0
mov ax,1
mov [mem],ax

the two bytes at /mem/ will be set to 01 00, not 00 01.

Saturday, October 15, 2011

Astronomy sky diagrams and photos often have a little key to indicate if they're erect views, inverted views or mirror views.

What used to puzzle me is that an erect view is indicated by

 N
E+

when that looks like it should mean a laterally reflected view, as E is on the 'wrong' side.

But then I realised that when you're looking up at the sky (which is the perspective that a sky photo has) you're looking OUT of the map, not INTO it. Consequently E and W are reversed.

Thursday, October 13, 2011

Giving up smoking

Preparation

(Before you start smoking...
1. Don't. If you think getting used to smoking, not being sick etc is hard, wait till you try getting used to not smoking.
2. Pick a brand that is a bit unusual and not available in all shops. Like B&H 100s.)


1. Pick a date to stop and stick to it. It should be a work day or a day on which you will have something to occupy you most of the time.
2. If you're going to use a nicotine replacement method, pick one and have at least a week's supply. Consider using two, like gum and an inhaler, in case like me you don't fancy chewing gum right after breakfast.
3. If you habitually smoke in the same places (chair, room etc) at home, choose a different, temporary place and stick to it.
4. If you usually buy cigarettes at the same shop, be prepared to stop going there. Find somewhere else to buy anything else that you get from there (lottery tickets have been my downfall).
5. Start keeping your cigarettes in a different room to where you usually smoke. The short walk before each smoke helps disrupt your habit.
6. Explain to smoking friends that you're going to stop. If they take offence, well, they aren't your friends.
7. Consider getting a prescription for Champix. It worked for me, it really took the edge off the initial cravings. And it didn't make me go mental (or more mental) as some websites suggest. Also, now that I know it works, if I do start smoking again, I can't use the excuse that stopping would be too hard, because Champix will always be there. If you follow this route, start the Champix 3 days before you stop smoking.

The day before - morning
1. Have your first cigarette of the day in a different place or at a different time. This will disrupt your expectations of getting one tomorrow morning.

The day before - before your last cigarette
1. Tomorrow you will have 4-5 minutes' spare time in the morning for each cigarette you usually smoke before going out. Set your alarm later to correspond (eg I used to have 3 fags in the morning, so I gave myself 10 minutes extra in bed).
2. Get a brush ready to clean up your smoking areas.
3. Dispose of all surplus cigarettes. I flush mine down the toilet. You don't want to find yourself going through the bins tomorrow.

The day before - after your last cigarette
1. Clean up all dropped ash from your smoking areas. If you can, move the chair or other furniture to make it difficult to sit there tomorrow.
2. Empty all ashtrays (into a non-flammable container!) Do it now. Don't leave them lying around as the smell will make you want to smoke tomorrow. Throw them out when they're empty, or put them at the back of a cupboard or the back of your car or somewhere where you won't see them for a few weeks.
3. Throw out all empty packets, cellophane etc.
4. Put any nicotine replacement supplies ready.
5. Go to bed.

The day
1. Change your starting routine - if you associate cigarettes with coffee, have orange juice instead etc.
2. Take any nicotine replacement supplies with you when you go out.
3. Don't go into your usual cigarette purchasing places.
4. Be prepared for temptation and be prepared to ignore it. Each one goes away after a few minutes. I get 20-30 spells of temptation on the first day. Remind yourself each time that, if you give in, you'll be disappointed in yourself in an hour's time; if you don't give in, you'll be pleased and proud of yourself in an hour's time.
5. Don't court temptation - don't stand around with people who smoke, don't watch them.
6. Use any nicotine replacement as directed. If it's an 'on-demand' method like gum or an inhaler, use it at regular intervals. DON'T let a need for nicotine build up, it will feel too much like you're hungry for a cigarette.
7. Completed the first day? Reward yourself with a treat. Something sweet, or a drink (unless you associate drinking with smoking). Well done!

Days 2-3
There will be fewer spells of temptation but they keep coming. Don't let up on the anti-temptation measures. Reward yourself again.

Days 4-5
These will be easier and there might be quite long periods of time where you don't think about smoking at all. Now don't start thinking 'Oh, that was easy. I can start again and then stop again.' You'll have to go through the first 3 days again if you do! If you don't, you will NEVER AGAIN have to do that. Keep up with the rewards too.

Subsequently...
If I get to day 6, I've done it. Your mileage may vary. Danger points for me are 2 weeks, a month, 2 months and 3 months. After 2 or 3 weeks you will feel less need for any nicotine replacements you've been using. Don't fret if it takes longer, ANY nicotine replacement is many times healthier than smoking. The nicotine receptors in your brain WILL eventually reset themselves and stop demanding nicotine.

(If you fail...
Each time you don't succeed increases your chance next time, because you've learnt more about the pitfalls. Set a new stopping date, ideally within a week)


After a month you can stop avoiding cigarette purchase locations if you feel confident. From here on it's just a matter of not starting agan.

Monday, October 10, 2011

Constructors, temporary objects and initialisation

With this setup (two constructors, a copy constructor and the destructor)

class A {
A() {...}
A(int i) {...}
A(const A &a) {...}
~A() {...}
};

{
A c = A(11);
}


results in one call to the int constructor and one call to the destructor, whereas

{
A d;
d = A(11);
}


results in one call to the no-argument constructor, then one call to the int constructor when the temporary object is created, then a call to the destructor when its statement is complete; finally another destructor call when d goes out of scope.

NB btw that although both these forms look like they have an assignment in them, because it's in a definition, an assignment is not actually performed (and any assignment operator is not called). This situation counts as an initialisation not an assignment.

Sunday, October 9, 2011

new and constructors

C++ is not C# - these two forms have different effects

{
A v = A(9);
A *w = new A(8);
}


The first one constructs a temporary A and assigns it to v. Constructor A(int) is called exactly once, and when v goes out of scope, ~A is called.

The second one allocates an A-sized piece of memory, constructs a temporary A, assigns it to that piece of memory, and sets w to point to it. Constructor A(int) is called exactly once, but when w goes out of scope, ~A is not called. The only destructor that would get called here is the one for type A*, and A* isn't a class so either there isn't one, or there is one that does nothing. Either way it isn't what you want.

Wednesday, October 5, 2011

Choice of language

Perl is my first choice of language for writing tools for my own use. But recently I've been using C++ more instead, because I get an executable which can be stored on the PATH and is therefore quicker to invoke than typing the path to Perl and the path to the scripts directory.

But... The last tool I needed was a program to rewrite a list of files in order so that their modification time order was the same as their name order. This took 12 hours' C++ development time - I had to write a Directory class, a string class and a Rewriter class as well as debug my memory allocation.

For comparison, I wrote the same thing in Perl and it took 2 hours. I still had to write a Rewriter class but of course the Perl version took much less time to create.

Now, assuming each invocation of the C++ version is 10 seconds faster to type, I've got to use the tool 3600 times to get back the extra development time I invested in the C++ version. Which I'm probably not going to do as I only need it for reordering image files so they come out right in gallery viewers.

Of course, the C++ version runs faster, but I don't need it to run faster. The sole gain was in the experience of writing C++, which I haven't done in earnest for about 15 years.

So the moral of the story is not just to consider development time, or execution time, but also how often you're going to use the program you're writing.

Tuesday, October 4, 2011

argv and argc

argc is the count of arguments including argv[0] (the executable name), so argv[argc] == 0.

C++ static member functions

If you're defining an out-of-class static member function, don't put static in the definition, or it won't compile. Just put it in the declaration.

class Thing {
public:
static int f(char *g);
};

int Thing::f(char *g) {
...
}

Monday, October 3, 2011

do while is not a loop

I've found that if you have a loop like this

$i = 0;
do {
print "$i ";
last if $i == 3;
++$i;
} while ($i != 10);

you will get the run-time error 'Can't "last" outside a loop block' when $i reaches 3.

Putting the 'last' in a proper if() {} block doesn't make any difference.

Apparently this occurs because do { } is just a grouping block, not a looping one, and the while here is the statement modifier while, not the control structure while. do { } is what you use if you want to put a statement modifier on a block of statements - { } alone just won't 'do'.

While that makes a sort of sense, a big red warning in Programming Perl would have helped. 'Do not use! Useful construct merely simulated!'

Additionally: what makes this really dangerous is that, if it occurs in a sub called from within a genuine while, the last will immediately jump out of the genuine loop (even if that loop's in a different scope) without any error or warning message. DO NOT USE.

C++ structs

There doesn't seem to be anything a class can do that a struct can't. The only official difference I can find is that struct members are public by default.

mingw maximum file name length

The maximum file name/path length with mingw appears to be FILENAME_MAX, not NAME_MAX.

Followers

Blog Archive