Quicken doesn’t like Amex QIF format

If you’re trying to import data into Quicken 98 (or compatible) having downloaded it from the American Express web site you’ll get some odd and undesirable results. There are two incompatibilities.

Firstly the date field (D) needs to have a two-digit year, whereas Amex adds the century.

Secondly, for reasons I haven’t quite figured out yet, the extra information M field sometimes results is a blank entry (other than the date).

You can fix this by editing the QIF file using an editor of your choice, but this gets tedious so here’s a simple program that will do it for you. It reads from stdin and writes to stdout so you’ll probably use it in a script or redirect it from and to a file. I compile it to “amexqif”. If there’s any interest I’ll tweak it to make it more friendly.

It’s hardly a complex program, the trick was figuring out what’s wrong in the first place.

#include <stdio.h>
#include <string.h>

char buf [200];

int main()
{
int lenread;
char *str;
        while ((str = fgets(buf, 200,stdin))) // (()) to placate idiot mode on CLANG
        {
                if ((lenread = strlen(str)) > 1)        // Something other than just the newline
                {
                        if (str[0] == 'M')
                                continue;       // Random stuff in M fields breaks Q98


                        if (str[0] == 'D' && lenread == 12)     // Years in dates must be two digit
                                strcpy (str+7, str+9);
                }
                printf("%s",str);
        }
}

Having a good argument

I’ve seen all sorts of stuff on forums about how to process command line argument in C or C++. What a load of fuss and bother. There’s a standard getopt() function in the ‘C’ library, similar to the shell programming command, but it’s not great.

The main problem with getopt() is that it produces its own error message. Although this saves you the trouble, it can be a bit user unfriendly for the user, especially when things get complex. For example, you might have mutually exclusive arguments and want to print out a suitable message. That said, it’ll work most of the time.

Here’s a page showing a good explanation for the GCC version, whcih is pretty standard.

Example of Getopt (The GNU C Library)

But rolling your own is not hard. Here’s a skeleton I use. It’s pretty self-explanatory. My rules allow single options (e.g. -a -b) or combined options (e.g. -ab), or any mixture. “–” ends options, meaning subsequent arguments are going to be a actual arguments.

Please generate and paste your ad code here. If left empty, the ad location will be highlighted on your blog pages with a reminder to enter your code. Mid-Post

If you want to pass something as an option, such as a filename, you can. -fmyfile or -f myfile are both handled in the example.

You can add code to detect a long option by adding “if (!strcmp(p,”longname”)) … just after the char c. But I don’t like long options.

#include <stdio.h>

void process(char *s)
{
    printf("Processing %s\n",s);
}

int main (int cnt, char **a)
{
    int i;
    for (i=1; i<cnt && a[i][0] == '-'; i++)
    {
        char *p = &a[i][1];
        char c;
        if (*p == '-')
        {
            i++;
            break;
        }
        while (c = *p)
            switch (*p++)
            {
            case 'a':
                printf("Option a\n");
                break;
                
            case 'b':
                printf("Option b\n");
                break;

            case 'f':
                if (!*p && i+1 < cnt)
                    printf("Value for f=%s\n", a[++i]);
                else
                {
                    printf("Value for f=%s\n", p);
                    while (*p)
                        p++;
                }
                break;
                
            default:
                printf("Bad switch %c\n",c);

            }
    }
    for (;i<cnt;i++)
        process(a[i]);
}

The above code assumes that options precede arguments. If you want to mix them the following code allows for complete anarchy – but you can end it using the “–” option, which will take any following flags as arguments. As a bonus it shows how to add a long argument.

#include <stdio.h>
#include <string.h>

void process(char *s)
{
    printf("Processing %s\n",s);
}

int main (int cnt, char **a)
{
    int i;
    int moreargs=1;

    for (i=1; i<cnt; i++)
    {
            if (moreargs && a[i][0] == '-')
            {
            char *p = &a[i][1];
            char c;
                if (*p == '-')
                {
                    moreargs = 0;
                    continue;
                }
                if (!strcmp(p,"long"))
                {
                    printf("Long argument\n");
                    i++;
                    continue;
                }

                while (c = *p)
                    switch (*p++)
                    {
                    case 'a':
                        printf("Option a\n");
                        break;

                    case 'b':
                        printf("Option b\n");
                        break;

                    case 'f':
                        if (!*p && i+1 < cnt)
                            printf("Value for f=%s\n", a[++i]);
                        else
                        {
                            printf("Value for f=%s\n", p);
                            while (*p)
                                p++;
                        }
                        break;

                        default:
                            printf("Bad switch %c\n",c);

            }
        }
    else
        process(a[i]);
    }
}