Departments


We Have Mail


Dear Editor:

Please send me your Author Guidelines for C/C++ User's Journal. I have several ideas; however some are sure to melt away once I find out how much work is involved.

Also, on page 95 of the October 94 issue, it says "Some programmers may wish to reuse the file_pointer member as a validity flag, instead of using a separate member. Although reusing file_pointer may save a byte or two per object, I feel that having a separate state member keeps the code more readable and maintainable."

Okay, but you missed an important opportunity to demonstrate how C++ can give you the best of both worlds. Go ahead and internally use the file_pointer member as the state variable, but use the public interface is_valid() to hide this. If, in the future, other reasons for invalid objects come up, it's easy to add an explicit state member because the is_valid() calls are already used. To me, design trade-offs like this are exactly why C++ is more powerful/maintainable than C.

Thanks and keep up the good work,

Andy Krassowski
andyk@sclara.qms.com

You make a good point about class interface style. — pjp

Dear Mr. Plauger,

I have been reading CUJ for the last two years and I enjoy it and find it very useful. It will be very good if all the articles published under "Code Capsules" or "Standard C" and "Stepping Up to C++" are made available at one place. Especially "Code Capsules" is very interesting. It will be useful to have all the articles under "Code Capsules" in a book form or as a special issue of CUJ. Do you intend to publish some articles on object-oriented programming?

Yours faithfully,

J.P. Singh
Melbourne, VIC 3071
AUSTRALIA

Many, if not all, of my "Standard C/C++" columns are also to be found in two of my published books, The Standard C Library, and The Draft Standard C++ Library, both published by Prentice Hall. I have been nagging both Dan Saks and Chuck Allison for years to produce books based on their respective columns as well. Talented as they are, they are both naturally too busy to find much spare time for such pursuits. I keep hoping, nonetheless. R&D Publications also continues to explore ways to make the material in their magazines available in other useful forms. So you should keep hoping too.

We'll probably never do an article on object-oriented programming per se. At least, it won't be one of those preachy things telling you how to program properly, at last. We prefer to run more useful "how to" articles, written by practicing programmers, that cover such topics in passing. I persist in the belief that pragmatic examples of working code are a better teaching tool. — pjp

Hi,

I'm curious about a statement in Kenneth Pugh's article "Using C Libraries in C++" in the May 1994 issue of CUJ. There is a statement there to the effect that in C++ it is the responsibility of the called funtion to clean up the stack when returning.

I'm probably missing something, but I've been sitting here for a while now trying to figure out how it's possible to have variable argument lists if the called function pops the stack on return. Assuming that the called function is called from more than one calling function, how would the compiler know how many and what type of arguments to remove from the stack when generating the code for the called function? Does it generate a copy of the function compatible with every invocation?

Sorry if I'm missing something obvious.

Joe Halpin
jhalpin@netcom.com

Ken should probably have qualified his statement a bit. It was a longstanding practice with C compilers that the caller removed arguments from the stack. Hence, it didn't hurt if the caller supplied more arguments than the callee expected. The C Standard introduced function prototypes so that, in the presence of a prototype at least, the callee could know how to clean the stack. The C Standard also requires that a function with a fixed number of arguments be called with the proper number. Compilers can thus now tailor their calling sequences accordingly. But C still requires the caller to clean the stack in one contex — where the prototype declares that the function expects a varying number of arguments.

C++ is even more restrictive. Every function call must occur in the scope of a prototype. Hence, except for the case of a function explicitly declared to accepty a varying number of arguments, the callee can reliably clean the stack. I hope that added bit of precision helps clarify your understanding. — pjp

Hello Dr. Plauger:

As a new programmer I find your articles interesting and helpful. I do experience some difficulties which I continually learn from due to compiler differences.

In particular, the article "Extending the Windows File Manager" (Sept. 1994, pp. 37) by Trevor Harmon needed a bit of modification to compile and function properly using Borland V4.0. The compiler didn't like the EXPORTS section in the FMEXT.DEF file. All that is needed is to delete the EXPORTS section entirely and to add the _export keyword to the LibMain, WEP, ShowSelDlgProc, DriveInfoDlgProc, and FMExtensionProc functions in FMNEXT.C. Also, #pragma argsused can be used where apropriate to eliminate those pesky "variable not used" warnings.

The new functionality is very interesting and I thank you and Mr. Harmon for providing it.

Michael L. Rohwedder
(ML-Rohwedder@bgu.edu)

Thanks for the information. And welcome to the wonderful world of nonportable C extensions. — pjp

Dear editor,

I read the article "A Simple Soundex Program" in the September 94 issue and discussed it with an associate here. I mentioned the May 1991 article referenced in this article about Levenstein Distances. This was titled "Inexact Alphanumeric Comparisons" by Hans Zwakenberg.

I had read that article in 1991 and modified the algorithm some time ago to what I felt was a more efficient one. My version uses a single array and few other vairables as a sliding window instead of the double subscripted array in the origional code. My associate suggested that I send my example back to you, so here it is. [It's available on the monthly code disk. — pjp]

It consists of a PKZIP file (v2.04g) containing a source module for the LDIST code, a header file and two sample programs I wrote to test the functions. I wrote an additional list search function using the algorithm to return the top N matches (lowest L distances) from a list.

I work for MCI in the Data Services Division and searching address lists for names is an important part of what we do here. Because of this, these algorithms, both the L Distance and the Soundex, interest me. Thanks.

R. Bruce Roberts
System Development Engineer
MCI Data Services Division

Thank you. — pjp

Dear Editor:

Regarding the Sept '94 letter from Lee Shackelford in which he asked of OOP, "Why bother?" Lee raises a legitimate question that I don't feel is asked often enough in our zeal to try out exciting new technologies.

Don't get me wrong, I'm not anti-OOP. I see benefits to the technology and have applied OOP to my work. But sometimes we adopt complex, new technologies in one big gulp without proper planning and proper consideration of the effects on our development processes.

Haphazard introduction of new technologies can lead to disasters, as happened to Borland International. Borland committed its projects to use C++, causing huge delays in getting their products to market. These delays put Borland into deep financial trouble. [1] Perhaps Borland should have tried C++ on a pilot project first, then slowly introduced the technology to other projects.

The moral of this story isn't to stop trying new technologies, just be careful doing so. And don't forget to ask "Why bother?" again and again.

Mason Deaver
AT&T Network Control Center - West
Denver, CO 80205
mcdeaver@attmail.com

[1] Andrew Binstock, "Objectively Speaking," Viewpoint column, Unix Review, June 1994, pg. 7

Amen. — pjp

Dear Mr. Plauger,

Thank you very much for your illuminating review on the book "Software Internationalization and Localization" which appeared in the C Users Journal!

Our organization, VTT, participates in a European research project, called GLOSSASOFT. VTT is a Finnish acronym for Technical Reseach Center of Finland. It is a non-profit research organization with 2,600 employees. The partners in the GLOSSASOFT project, in addition to VTT, are Open University from U.K., NCSR Demokritos from Greece, Claris from Ireland, HP Hellas from Greece, and Bull from France. The aim of the project is to develop methods and guidelines for software internationalization and localization.

VTT's expertise is centered around software development and therefore our concern is very much in the same area which you outline in your review. It seems that many of the current books and articles on internationalization and localization are written by specialists of localization. Good knowledge of programming is needed, of course, when internationalization is concerned.

In addition to our thanks, I would like to ask your kind advice on the following subjects:

Best regards,

Timo Honkela
vtt.fi!Timo.Honkela

I have written several times in these pages about internationalization. See the March through May 1991 and the May through July 1993 issues. Much of that material is also available in my book, The Standard C Library. Also, The Journal of C Language Translation, edited by John Levine (johnl@iecc. cambridge.ma.us) frequently prints articles on this topic. And Rex Jaeschke, Chair of X3J11, has an article you may find interesting in the pipeline for publication in this magazine.

Ongoing standardization in the area of internationalization is unfortunately divided among several groups. Within ISO committee JTC1/SC22 are the working groups WG14 (C), WG15 (POSIX), WG20 (internationalization), and WG21 (C++). Then there's X/Open and CEN, in Europe. I have trouble keeping up myself. Good luck. — pjp

Dear Mr. Plauger,

I have a couple of new tricks that I have recently learned. Having a programmer's instinctive desire to see people write code the way I would, I thought I might share them.

The first involves numeric conversion constants. Most of us have encountered the everpresent definitions:

#define DEGREES_ TO_RADIANS M_PI/180.
#define RADIANS_TO_DEGREES 180./M_PI
I recently had reason to also deal with mils (6,400 to a circle), bams (0x10000 to a circle) and sectors (we break the circle into 256 sectors for processing). (For the curious, this was part of a radar simulation.) Rather than defining 20 different conversion constants, I merely defined 180 degrees in each of the five units as follows:

// 1/2 circle in various units
// Usage example:
// radval = degval * (RADIANS/DEGREES)
#define BAMS ((float)0x8000)
#define MILS         3200.0
#define DEGREES       180.0
#define SECTORS       128.0
#define RADIANS        M_PI
I could then easily and naturally perform any conversion by combining the necessary constants, much as I learned in college physics:

sectval = milval * (SECTORS/MILS);
radval = sectval * (RADIANS/SECTORS);
and so forth. This is extremely flexible, and suffers no loss of readability. The parentheses insure that a compiler with decent optimization will pre-compute the division at compile time, producing a single multiply. Without the parentheses, the expression may generate a multiply and a divide. I tested this with Borland C++ 4.0, and the parentheses do save a run-time divide there.

The second trick is a way around a difficult, but fairly common, coding problem. I'm sure we have all run into loops like the following:

fgets(string, MAXLEN, stdin);
while (string[0] == '\n')
{
puts("Entering a blank line won't cut it.\n");
fgets(string, MAXLEN, stdin);
}
The problem, of course, is the repetition of the fgets call. This duplication is undesirable. It's too easy to change one of the calls and miss the other (especially in more realistic examples).

One solution is to change this to the following:

for (fgets(string, MAXLEN, stdin);
    string[0] == '\n';
    fgets(string, MAXLEN, stdin))
    puts("Entering a blank line won't cut it.\n");
This really doesn't cure the problem, and it abuses the iterative intent of the for loop.

My favorite solution to this problem is:

while (fgets(string, MAXLEN, stdin),
      string[0] == '\n')
      puts("Entering a blank line won't cut it.\n");
This is an unconventional solution, but seems to me a very effective use of the comma operator. For cases like this, it may be one of the best solutions for a sticky problem. It is certainly better than:

while (fgets(string, MAXLEN, stdin)[0] == '\n')
     puts("Entering a blank line won't cut it.\n");
which will also work, but may be less welcome in a professional environment. Thanks for your time, and apologies to all the people who thought of these ideas before I did.

Brian Tagg

I like your use of manifest constants to handle multiple units. When it comes to fgets, however, I'm a bit more paranoid. I always check to see if it returns a null pointer. And I worry about whether it truncates a long line. Otherwise, I approve of your concern with developing a good and consistent programming style. — pjp

Dear Editor,

This is a response to Edward Bell's letter (CUJ, March 1995), in which he asks for a program to generate random English pronounceable proper names.

I assume that you want to randomly generate the characters that make up the names and not just pick names randomly from a list.

I've tried this a few times. The only solution I like so far is to use a list of sample names to tabulate some statistics before generating the random names. I use about a 3- or 4-dimensional array to store the occurrences of the current character based on the previous characters.

/* Something like ... */
c0 = getchar();
a[c2][c1][c0]++;
c2 = c1;
c1 = c0;
You probably want to set the previous characters to spaces between each name to eliminate correlation between names.

I'm usually willing to handle punctuation and case on my own, so I just make each dimension 27 elements, one for each letter of the alphabet, plus one more for spaces and everything else. Most of the elements will have a frequency of zero, so you should save memory if a sparse array is used. Three dimensions should give fairly pronounceable names; four dimensions will probably start duplicating real names regularly.

To generate the names, total the occurrences for each posibility for the current character based on the previous characters and then generate a random number less than the total, and then find the character.

/* Something like ... */
c2 = c1;
c1 = c0;
n = 0;
for (i = 0; i < dim_siz; i++) n +=
a[c2][c1][i];
r = rand() % n;
for (i = 0; i < dim_siz; i++) {
   if (r < a[c2][c1][i]) {
      c0 = i; /* "c0" is the next char. */
      break;
   }
   r -= a[c2][c1][i];
}
putchar(c0);
A potential problem is that the random names tend to vary more in length than real names. If this is a problem, you can vary the weight of the space character based on the current name length.

References: (Old) Cryptography books often have information about frequently-occurring character sequences. Data compression algorithms based on frequently-occurring character sequences might be a good source for efficient storage methods.

Sheldon

Thanks — pjp

Dear Mr. Plauger,

I have just completed a course in advanced C++ at the University of California Extension Division. In the last class, we discussed new features of C++ including namespaces. That discussion brought up the fact that when the directive form is used (i.e. "using namespace") all classes, variables and functions declared in that namespace will be put into the global scope. It seems that this could cause problems if there were already items with the same name in global scope.

Is it possible to do some sort of name mangling on the variables etc. in the namespace when the using namespace declaration is used so that these items retain their uniqueness and thus can be accessed by their symbolic name only? The items already existing at the global scope can then be accessed by using the scope resolution operator.

Also, when do the namespace items get removed from global scope? Is it delimited by a { } pair or something else?

Thanks,

Dave Goldstein
Pittsburgh, PA

I believe there are rules that favor items declared in the parent namespace over those imported via a using declaration, but you're still correct. Programmers will encounter conceptual problems when names collide. Sometimes they'll expect to get the imported name, sometimes they'll expect to get the native name, and sometimes they'll want a diagnostic. Since no commercial compilers exist that implement namespaces, to my knowledge, it's hard to do experiments to see what works and what doesn't.

As for your last question, like any other declaration, the names it introduces go out of scope at the end of the block containing the declaration.

Thanks for writing,

P.J. Plauger

Hi

We are New at Visual C++ and have a problem.

I need to create a modal dialog, that has no resource template, because I read the window's size and position from an ASCII file, as well as a fields definition — these fields are created dynamically.

When I am building the above-mentioned window, I already have another one which is modal. I need to disable the first one and then show the window I am putting up from the ASCII file.

For creating the window I used the CreateExt function, This window is derived from CWnd instead of CDialog.

Can you gimme a clue as to how to create this window?

I send you my regards.

Juan Carlos Flores
(jflores@macosa.com.ec)
MACOSA - NCR
Alpallana 289 y Almagro
Quito - Ecuador South America

Veronica Burbano
(vburbano@macosa.com.ec)
MACOSA - NCR
Alpallana 289 y Almagro
Quito - Ecuador South America

Any Windows gurus out there? — pjp