Solved

Borland Database Engine date decoding errors

Posted on 1997-05-23
10
617 Views
Last Modified: 2012-06-21
Hi, I'm learning-on-the-go as I develop a database application for a small business.  I'm running into a lot of trouble reading numerical and date data from a dBase III file using the Borland Database Engine and IDAPI.

The function was returning wierd values, so as an error-check I encoded then immediately decoded a date.  What I get back is not what I put in.

Help, please!

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Theoretically, the messagebox should display "2/29/80" but it actually displays something like "901286/13/3248237"

Any ideas?
0
Comment
Question by:Klaxxon
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
10 Comments
 
LVL 4

Expert Comment

by:AVaulin
ID: 1163662
You use DbiDateEncode and DbiDateDecode not correctly. 1st parameter in DbiDateEncode and 2nd, 3rd and 4th parameters in DbiDateDecode are references. You must write:
DbiDateEncode( 2, 29, 80, dte );
DbiDateDecode( dte, mm, dd, yy );
I hope this will help. Good luck.
0
 

Author Comment

by:Klaxxon
ID: 1163663
Thanks for your answer, but it does not work.

My variables are declared as follows (as the online help file says they should be):

DBIDATE dte;
pUINT16 mm, dd;
pINT16 yy;

My code looks as you suggested:

DbiDateEncode (2, 29, 80, dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

But will not compile due to the following error:

Error:  superaje.c(583,34):Type mismatch in parameter 'pdateD' in call to 'DbiDateEncode'

I can get the code to compile as follows:

DbiDateEncode (2, 29, 80, &dte);
DbiDateDecode (dte, mm, dd, yy);
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);            

(I added a '&' to dte in DbiDateEncode), but it crashes with a "Thread Stopped" message saying there was an "access violation".

Obviously, my understanding of pointers is rudimentary, so if you could help further, it would be appreciated.
0
 
LVL 4

Expert Comment

by:AVaulin
ID: 1163664
Let's try this way:

long dte;
Word mm, dd;
short yy;

DbiDateEncode (2, 29, 80, dte);
sprintf (str, "%li", dte);
MessageBox (hDlg, str, "", MB_OK);
DbiDateDecode( dte, mm, dd, yy );
sprintf (str, "%hi/%hi/%hi", mm, dd, yy); // see h specifier
MessageBox (hDlg, str, "", MB_OK);

What both MessageBox says?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Klaxxon
ID: 1163665
Nope ... doesn't work.
I get a bunch of "type mismatch" messages because the types need to be DBIDATE, pUINT16, and pINT16.

I'm working in Borland C++ 32-bit with Borland Database Engine 32-bit.
0
 

Accepted Solution

by:
rlayton earned 100 total points
ID: 1163666
I believe DbiDateEncode requires 4 digits to calculate the correct date.  Try it, you'll like it!
0
 

Author Comment

by:Klaxxon
ID: 1163667
Thanks for the advise, unfortunately it didn't help.  For furthur clarification, here is the exact code I'm using, plus the exact results I get:

The variables are declared as follows:
DBIDATE dte;
pUINT16 mm, dd;
pINT16 yy;

This is the code:
/*  "Chk()" is simply an error-message printing function.  It's source can be found under "chk" in the bde32.hlp file  */

Chk (DbiDateEncode (4, 28, 96, &dte));
Chk (DbiDateDecode (dte, (pUINT16)&mm, (pUINT16)&dd, (pINT16)&yy));
sprintf (str, "%i/%i/%i", mm, dd, yy);
MessageBox (hDlg, str, "", MB_OK);

Here's the results with different dates:

when I encode:  5, 28, 1997
I get:  2064515077/28/133069
(at least the day works!)

encode:  5, 28, 97
get:  2064515077/28/131169

encode:  4, 28, 97
get:  2064515076/28/131169

encode:  4, 28, 96
get:  2064515076/28/131168

These results imply that I get simply subtract a particular value from each answer to get the right one.  This is the first time I actually did a trial-and-error check of the return values, and now it looks like they're always off by a consistant ammount.

I'd still like to have the function work properly, though.... I really bothers me to have to hack an answer out.

BTW, I ran the DbiGetDateFormat() function, and it returned the following:
DateFormat = 0
4 digit year = 0
Year biased = 1
date separator = '/'

The explanations of those are in the help file, but those values are as they should be.

As some additional background, I'm writing a program that reads in a dBase III .DBF file.  I was getting weird values when reading dates, so *that's* why I encoded then decoded a date... It's purpose is simply an error check.

Thanks for your help, I hope I've clarified a few things, and I hope you can assist me further...  My employer is getting anxious to see some results and this problem has been a major roadblock.
       - Klaxxon
0
 

Expert Comment

by:rlayton
ID: 1163668
Here is the exact code I use to encode/decode this stuff:

int Month, int Day, int Year;
DBIDATE Td;
 
DbiDateEncode(Month, Day, Year, &Td);
DbiDateDecode(Td, &Month, &Day, &Year);

This stuff is actually quite straight forward, and I haven't had any problems with it once I got it all setup and working correctly.  

The only other problem I can see is if the memory for the table buffer isn't allocated correctly.  Also, view the contents of the Td  ( the DBIDATE / double) variable after encoding each of the different trial dates, and see what relationship they have.  

I've never used the BDE with dBaseIII, but I've plenty of success using it with Paradox, MS SQL Server, and Sybase, which should basically be the same using it with any other DataBase

Anyway, Good luck!


PS. I have a DataBase/Table wrapper class I've written which encapsulates all this stuff, automating file opening, record access, etc...,  which really makes it much easier to manage (at least for me.)  If you're interested let me know,  I'd consider letting somebody else try it out!  However it may take you longer to get it set up than you have to waste.


0
 

Author Comment

by:Klaxxon
ID: 1163669
aaaallllllrrrriiiiiigggggghhhhhhtttttttt!!!!!

(you'll have to excuse me, but this problem has been really bothering me... and now it's FIXED!!!)  :o)

For some unknown reason, if the month, day, and year variables have not been assigned a value (it appears any value will do) before DbiDateDecode (dte, &mm, &dd, &yy); is called, then I get screwy answers.  All I did was assign mm = dd = yy = 1; at the top of the function, and now DbiDateDecode returns everything correctly!!  Wahoo!

I figured that out because in your code you fed DbiDateEncode preassigned values while I was trying to pass numbers directly to the function.  This led me to do a little playing around, and I figured it out.

Thank you *VERY* much.

.....Now, on with my program!

PS:  You *may* see a question posted here soon about reading regular numerical data (as opposed to strings) from a database.  But I'll see what I can do first.  Thanks a bunch.
0
 

Author Comment

by:Klaxxon
ID: 1163670
Yup.... I'm having problems with reading numerical data.  YaSee, this is the first time I've ever used BDE so I'm learning as I go.

Say a field contains an integer.  Do I just do the following?

int num;
DbiGetField (VarCur, FieldNum, RecBuff, (pBYTE)num, ...);

or do I use:
..., (pBYTE)&num, ...

or do I declare num as a string or perhaps a double?

If you could send me some sample source either as a comment to this question or to rogersa@superaje.com ,  I'd really appreciate it.

If you like, I can submit it as a 25 or 50 point question and then grade you.

Thanks in advance.
0
 

Expert Comment

by:rlayton
ID: 1163671
I'll give this one to you, just treat me well when the opportunity arises.

If the value you are retrieving is a double, then pass in a double, likewise with int, char*,etc...

Here is a snippet from my table class...

char * Table::GetField (UINT16 FieldNum, char *Src)
{
      BOOL Blank;

      strcpy(Action, "GetField");

      Status = DbiGetField (Cursor, FieldNum, DBRec, (pBYTE)Src, &Blank);

//Not always blank in SQL Server
      if(Blank)
      {
            switch(NumberType)
            {
                  case NINT:
                        memset(Src, 0, sizeof(int));
                        break;

                  case NDOUBLE:
                        memset(Src, 0, sizeof(double));
                        break;

                  case NLONG:
                        memset(Src, 0, sizeof(long));
                        break;

                  default:
                        strcpy(Src, "");

            }
      }


      if(Status)
            ErrorHandler();

      return Src;

}


double Table::GetField(UINT16 FieldNum, double &Number)
{
      NumberType = NDOUBLE;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


int Table::GetField(UINT16 FieldNum, int &Number)
{
      NumberType = NINT;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


long Table::GetField(UINT16 FieldNum, long &Number)
{
      NumberType = NLONG;

      GetField(FieldNum, (char *)&Number);

      return Number;
}


As you can see, I simply pass in the variable of the type I want to retrieve, which forces the correct function to be called, and the variable is also returned for ease of use!  Each function calls the top (top as in top of this listing) function, so you could look at that one for reference.  The Cursor and Record are both part of the class, so you'll need to pass those in as well.

Quick examples for use:

double Double;
int Integer;
char Str[MAX_SIZE];

wsprintf(Temp, "%d \t %lf", GetField(FieldNum, Integer), GetField(FieldNum, Double));
MessageBox(0, GetField(FieldNum, Str), Title, MB_OK);

etc...


Good Luck!
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

Title # Comments Views Activity
maze travler 6 66
Unable to start eclipse ? 17 163
What is sub-make ? 2 88
Indy 10 not Receiving UDP broadcast 3 43
What is C++ STL?: STL stands for Standard Template Library and is a part of standard C++ libraries. It contains many useful data structures (containers) and algorithms, which can spare you a lot of the time. Today we will look at the STL Vector. …
Introduction This article is a continuation of the C/C++ Visual Studio Express debugger series. Part 1 provided a quick start guide in using the debugger. Part 2 focused on additional topics in breakpoints. As your assignments become a little more …
The goal of the tutorial is to teach the user how to use functions in C++. The video will cover how to define functions, how to call functions and how to create functions prototypes. Microsoft Visual C++ 2010 Express will be used as a text editor an…
The viewer will learn how to use the return statement in functions in C++. The video will also teach the user how to pass data to a function and have the function return data back for further processing.

726 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question