Journal Articles
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: Questions & Answers
Author: Administrator
Date: 03 October 1999 13:15:34 +01:00 or Sun, 03 October 1999 13:15:34 +01:00
Summary:
Body:
I have decided to change the organisation of this column. Each issue I will publish a number of questions that have been raised either directly with me or through newsgroups, email lists etc. and invite readers to give their best shot at answering the problem. Hopefully many of you will want to participate. I do not promise to print all responses but I will arrange that everything that does not embarrass the author will either be printed or displayed on our web site. I have no doubt that the process of understanding other people's problems is very instructive.
I will provide a column of this style for both C Vu and Overload (though the questions and answers will require more technical skill for the latter).
Here are a few to get you started. Note that some questions have first order simple answers (i.e. you cannot do that … but I have tried to select problems because they have more hidden beneath the surface.
Question 1:
What is the best way of converting from strings to enums? I would like a solution that ensures that when a new enum is added, a corresponding string must also be added to ensure consistency.
I have seen two ways to do this but each have their problems
-
ensures that all possible strings are checked but enumeration values must be sequential
-
enums don't need to be sequential but if an extra value is added the programmer must add an extra if statemen
enum MyEnum { eOne, eTwo, ..... eEnd, eStart=eOne, eInvalid=eEnd}; string MyEnumStrings[eEnd] = { "One", "Two", ....}; //Method 1 MyEnum StringToEnum(string TheString){ for (MyEnum e=eStart; e<eEnd ; e=MyEnum(e+1)) if (TheString == MyEnumStrings[e]) return e; return eInvalid; } //Method 2 MyEnum StringToEnum(string TheString){ if (TheString == MyEnumStrings[eOne]) return eOne; if (TheString == MyEnumStrings[eTwo]) return eTwo; //.... etc }
Question 2
How do I output a float with exactly 'n' decimal places in C++?
Question 3
I found the following code fragment for implementing unary minus:
class Complex { double re, im // ... public: // ... Complex operator-() const { return Complex(-re, -im); } // ... };
I don't understand what the const is doing in the middle. I thought const was for variables.
Question 4
I want to use a dynamically created m by n matrix, but it seems that no variable can handle new double[m][n] properly unless n is predefined. I was told that there's no way to use
new double[m][n]
where m and n are int variables. So what should I do?
Question 5
I have the following problem with my program wherein I am using STL vectors to store documents. I store each document in a vector with each element containing a line. (I am using gcc 2.8 under Solaris 2.6).
I have a calling code like:
main () { vector<string>* doc; Break(doc); return 0; }
My implementation of the Break method goes as follows:
void Break (const vector<string>* doc) { vector<string>::iterator i; char* line; for (i=doc->begin(); i != doc->end(); i++) { strcpy(line, (*i).c_str()); // copy to remove const of (*i).c_str() while (*line != '\0') { cout << *line << " "; ++line; } cout << endl; } }
In the above program, the for loop traverses only a portion of the vector elements (13 lines) and aborts with a "Segmentation fault (core dump)" error or at times with a "Bus error (Core dump)" error messages. When I replace the while loop with
cout << line << endl;
it works perfectly (sends all the elements of the vector to stdout). What is happening?
Question 6
I have a problem that I'm confused about: I want a function to return an array (ptr?) such that int a[4] = return_int(); This codes doesn't work.... B is where I want to set i[4] = g[4];
int g[4]; int main (int argv, char **argc) { g[0] = 1; g[1] = 2; g[2]=3; g[3]=4; test1(); return 0; } void test1() { int i[4]; i = return_int(); /* B */ } int *return_int() { /* return int*?? */ return g; /* not sure here */ }
Question 7
I recently had to extract the day, month and year values from a 32-bit number, which was defined as "the number of seconds elapsed since midnight (00:00:00), January 1, 1970, Universal Co-ordinated Time." The only way I could think to do it was via repeated subtraction, which worked OK but didn't feel right. I'm sure is there is a better way. I then had to do a similar thing with a 64-bit number, for which I didn't have a definition, but I did know that the value 0x42C9D10443A00000 represented 1 January 1800. Any ideas?
From: "billcartwright" <billcartwright@ouvip.com>
As I have a copy of MS Fortran Professional, which includes ISML libraries, and Visual C++ I experimented with calling the Fortran libraries from Visual C++ with some unexpected results, to me if not others. I believed that, if I declared an array as double a[2][3], I could then refer to it using 'a' as a pointer. This appears to agree with all references I can find and with the ISML article which defines 'a' as above then calls a transpose routine as follows:
DTRNRR(&nra, &nca, a, &lda, &nrb, &ncb, b, &ldb);
The C header file shows:
void _stdcall DTRNRR(long*, long*, double*, long*, long*, long*, double*, long*);
However in Visual C++ 6.0 I received the error message:
C2664: 'DTRNRR' : cannot convert parameter 3 from 'double [2][3]' to 'double *'
Following up on Error C2664 did not help me.
I then redefined 'a' as double *a and used a = &aMatrix[0][0]; to get a pointer for use in the routine this seems to work fine but does not line up with my previous understanding of pointers and arrays.
As a further check I tried:
for(p = aMatrix; p != aMatrix + 6; p++) cout << *p << " " << endl;
This gave the same error message until modified to:
for(p = &aMatrix[0][0]; p != &aMatrix[0][0] + 6; p++) cout << *p << " " << endl;
Checking that aMatrix and &aMatrix[0][0] are the same using:
cout << "a: " << a << "\n"; cout << "aMatrix: " << aMatrix << "\n"; cout << "&aMatrix[0][0]: " << &aMatrix[0][0] << "\n"; cout << endl;
on my machine gives:
a: 004350C0 aMatrix: 004350C0 &aMatrix[0][0]: 004350C0
i.e. the same result for a, aMatrix and &aMatrix[0][0].
Bill's problem is that he (along with many others) has not taken the type of the pointer into account. Having the same value is not the same as being the same thing ☺ Let me see if I can clarify.
If you simply use the name of an array in a context where a pointer is required you will get a pointer to the first element of the array. So if
char message[] = "Help";
the type of the address that results from using message is 'char*' and its value is the address (pointer constant) to the first byte of the array of five (do not forget the string terminator) chars created to store a modifiable copy of "Help"
This is as far as many programmers get. However the next element is that C and C++ only support one dimensional arrays. They fudge multi-dimensional arrays by having arrays of arrays… (or dynamically by having arrays of pointers, but that is another level of complexity). When you write:
int matrix[2][3];
you are declaring matrix to be an array of 2 <arrays of three int>. What is the first element of matrix? It is an array of three int. So the type of the pointer you get from using matrix is pointer to array of three int (and while we are on this subject, that inner array does generally not decay to a pointer to int - again a complication that I will leave for now, but it matters when you try to write functions that have a multi-dimensional parameter)
The type of matrix decays to *(int [3]). Now the prototype DTRNRR is possibly wrong because I think some of the pointers should be pointing to rows (arrays of double) , however all the programmer wanted was the values, type safety would be handled by careful programming. Making the calls work seems to be a matter of using casts with the utmost care. Again, I am going to side-step the issue because you have to work with the prototype provided but I suspect that the programmer of the library did not understand arrays in C as well as we might wish.
Now let me look at getting the start address of the array in the way in which you wanted it. What is the first element of matrix? matrix[0] which is an array of 3 ints. Subtler, when I write matrix[0] I name an array and we know that in correct context this decays to a pointer to the first element of the array. What is the first element of matrix[0]? It is the int found at matrix[0][0]. So the solution to your original problem was to use a[0] instead of a.
Sorry if this is still not clear, pointers give almost all of us headaches.
In general to get a pointer of the type of a single element of a multi-dimensional array you must provide for all the dimensions but the last one.
You could have written your for loop as:
for(p = aMatrix[0]; p != aMatrix[0]+ 6; ++p) cout << *p << " " << endl;
Notes:
More fields may be available via dynamicdata ..