Journal Articles

CVu Journal Vol 11, #6 - Oct 1999 + Programming Topics
Browse in : All > Journals > CVu > 116 (22)
All > Topics > Programming (877)
Any of these categories - All of these categories

Note: when you create a new publication type, the articles module will automatically use the templates user-display-[publicationtype].xt and user-summary-[publicationtype].xt. If those templates do not exist when you try to preview or display a new article, you'll get this warning :-) Please place your own templates in themes/yourtheme/modules/articles . The templates will get the extension .xt there.

Title: The Journey

Author: Administrator

Date: 04 October 1999 13:15:34 +01:00 or Mon, 04 October 1999 13:15:34 +01:00

Summary: 

The Journey is a reduction of the postings to accu-general compiled every month. ACCU general provides an opportunity for members to discuss, share, educate and be educated.

Body: 

The Journey is a reduction of the postings to accu-general compiled every month. ACCU general provides an opportunity for members to discuss, share, educate and be educated. The monster thread of the month award goes to "How Language Design Affects Idioms" started by Sean Corfield. Since the intention was to produce material for an article by Sean, I won't be quoting from that path. Here are some of the other prime threads from June.

Detecting stream errors

This thread brought about the interesting issue of stream diagnostics, or rather the lack of them.

[Dave Rutlidge]

If I have code that looks like...

void foo() {
  ifstream ifs;
  ifs.open("bar");
  if (ifs.fail()) {
    clog << "I got an error";
  }

How do I find the reason why the open failed? I have spent hours looking at the documentation but could not find any official way of doing this. I also played and found that perror() will display the error message, but this is C not C++/streams. I could use strerror(). Is this the "official" way? Is there a better way?

[Sean Corfield]

We discussed this a while back on this list and the answer was "You can't".

[Klitos Kyriacou]

Now it seems that C++ ifstream also sets errno. However, this may be a result of the streams library using the C stdio library in its implementation (depending on who developed your C++ library). The standard doesn't require errno to be set when ifstream.open() fails. Having said that, I suspect the C standard doesn't say exactly when errno should be set either. So it sounds like pot luck whether errno gives you anything useful, whatever language you choose. Any comments?

How about the following way of obtaining an error message, if one is available:

{
  errno = 0;  // Reset to no error
  ifstream f(filename);
  if (f)
    process_file(f);
  else
    if (errno)  // Set by ifstream::ifstream(const char*)
      cout << "Failed to open file: " << strerror(errno) << endl;
    else
      cout << "Failed to open file." << endl;  // Unknown cause
}

[Bill Somerville]

I still think that errno should only be relied on immediately after a system call returns a failure status.

[Philip Hibbs]

A global variable like errno can never be thread-safe, so even checking it immediately might not work.

[Adrian Fagg]

Well, actually it can sometimes be, though you can't rely on it everywhere. Multithreaded libraries - so long as they're properly initialised - will work correctly. As far as I know this applies to errno.

[Sean Corfield]

You can check the flags in a stream to get some information but generally any particular errors are platform specific (permissions, existence etc.) so these have no place within a Standard. Not much help I'm afraid... The committee did discuss making more information available but there was no agreement on how to do this in a portable manner.

Code Analysis Tools

This conversation was started by Paul Rocca, who explained he had to convert Pascal to C. To make things a shade more complex, the Pascal code was in French. Having Y2K checked some French C recently, I know how surprised I was at the complexity added by not understanding variable names etc.

[Jon Jagger]

If I were you the first thing I'd do is rewrite the French-Pascal as English-Pascal. Then worry about converting it to C. Or whatever. One thing at a time. Evolution rather than revolution. Stable Intermediate Forms (as Kevlin would say)

[Nigel Thornton-Clark]

A few years ago I worked on a project to convert a large application written in C from OS9 to RSX11. The original application was written by a German company so all the comments and names were in German. For some strange reason there were actually two projects doing the same conversion for the same customer on different sites run in parallel. The first project manager decided to translate everything into English, port the code, and make some enhancements all at the same time. The second project manager ported the code first and then made the enhancements. At each stage he made sure that the code was stable before proceeding. The result was that the second project finished six months ahead of the first and was a pleasure to work on. We didn't get round to translating everything from German to English because by the time we'd finished we could understand the comments and we were familiar with the German naming conventions.

In addition, I would make sure I could compile and run the code in Pascal before even thinking about translating it or converting it. I would also treat any automatic conversion tools with a great deal of suspicion as, from what I can remember, p2c only works with fairly standard Pascal whereas the source may be written in TurboPascal which has a lot of non-standard extensions. One approach may be to convert the code module by module, using p2c, and to keep the C code in a library that can be linked to the remaining Pascal code. That way you have something that works at every stage.

Strings

Finally this month, we have some distilled wisdom on the subject of strings. The following comes from a couple of separate threads which show how the unwary can be caught out by the C++ Standard string, even if they have used old style strings (char * or the MFC CString). The names have been removed to protect the innocent, and answers may have been supplied by more than one person.

[Q - Strings and map]

I'm trying to use the STL map and I'm having some problems.

map<char*, char*> myMap;
char a[40];
char b[40];
do {
  myMap.insert(myMap.begin(), map<char*, char*>::value_pair(a, b));
} while( morevaluesfromdb() );

If I do this, it overwrites the values. I believe this is because its storing the address of a and b rather than the values. How do I use the map correctly?

[A]

Map stores values - the values being stored are pointers (char *) Your code stores pair<&a, &b> over and over. Instead of std::map< char *, char * >, use std::map< std::string, std::string >

[Q - Strings and default parameters]

I have a function like:

int GetThing
  (const string& stra, const string& strb = NULL);

If I do this:

string x = "EH101";
GetThing(x);

I get an access violation because of the NULL strb.

What am I doing wrong. Can I use default values of type string?

[A]

You are attempting to initialise a string with a null pointer. Try:

int GetThing(const string& stra, const string& strb = string());

I like to talk about the former (char * or char []) as a C string, and the latter (std::string) as a C++ string, in the hope that all those programmers who haven't caught up yet will soon stop using raw char arrays in C++.

Notes: 

More fields may be available via dynamicdata ..