C++ Programming TipsHere are C++ programming tips. Update: 5/29/2020 Index
How can I tell 32 bit or 64 bit dll?Here is how, using dumpbin dumpbin /headers named.dll | findstr machine The result you get 14C machine (x86) (or machine (x64)) Can you list the version for runtime?VisualStudio C++ uses runtime libraries and in the past libraries have different versions depending on Visual Studio versions. Here is the list from https://matthew-brett.github.io/pydagogue/python_msvc.html. Microsoft finally get the act together so that you need to install only the latest redistributable for codes compiled under VS2015 or later. That is, C++ 2015, 2017, and 2019 can use the latest redistributable files. https://support.microsoft.com/en-us/help/2977003/the-latest-supported-visual-c-downloads.
Why I'm getting exception for CString?I compiled a MFC program written by someone else and I was getting exception under debug: File: minkernel\crts\ucrt\src\appcrt\convert\isctype.cpp Line: 36 Expression c >= =1 && c <= 255It turned out that crt source code lives in C:\Program Files\Windows Kits\10\Source\$(version)\ucrt. The relevant code is here extern "C" int __cdecl _chvalidator(int const c, int const mask) { _ASSERTE(c >= -1 && c <= 255); return _chvalidator_l(nullptr, c, mask); }This method is called when you use methods like isspace(int c). But the comment for the method says // The _chvalidator function is called by the character classification functions // in the debug CRT. This function tests the character argument to ensure that // it is not out of range. For performance reasons, this function is not used // in the retail CRT.The problem with this method is that French accented character has negative value less than -1. How can I trap floating point error?When a calculation generates NaN (=-1#IND) or Inf (=1.#INF), you normally don't get exception thrown. It is not an exception but signal. The way is to setup the CPU trap _controlfp or_control87. Unfortunately Microsoft help is not clear on how. Here is the link http://www.devx.com/cplus/Article/34993/1954. The article uses _controlfp. The article method works for VS2010 also. By the way, Microsoft .NET language cannot trap floating point error. You cannot PInvoke() this function (it generates StackOverflow exception). In C#, you use double.IsNaN(), double.IsInfinity(), double.IsPositiveInfinity(), double.IsNegativeInfinity() Another thing is to translate SEH Exception to C++ Exception so that you can do thestandard try/catch without using Microsoft _try/_catch. You do this by1. Enable C++ Exceptions as Yes with SEH Exception(/EHa) 2. Add the following class and function class SE_Exception { private: unsigned int nSE; public: SE_Exception() {} SE_Exception( unsigned int n ) : nSE( n ) {} unsigned int getSeNumber() { return nSE; } }; void SE_translator(unsigned int u, EXCEPTION_POINTERS *pExp) { throw SE_Exception(u); } 3. At the beginning of your program _clear87(); unsigned int DW = _control87(0,0); DW &= ~(_EM_INVALID | EM_ZERODIVIDE | EM_OVERFLOW | _EM_UNDERFLOW ); // setup trap new mask DW = _control87(DW, MCW_EM); // must use /EHa _set_se_translator(SE_translator); 4. Add try/catch(SE_Exception ex). How can I get general 2D slices using gslice out of a valarray?Standard C++ library provides valarray for numerical computation use.What I wanted was to get a 2D slice out of a valarray. In my case, I wanted to get a 2D slice of all six types, i.e. XY, YZ, ZX, YX, ZY, XZ out of a valarray whose data were stored in row major way. There is a class called gslice to be used for such a purpose. Unfortunately, I could not find anything on how to do this on books and web searches. Thus I started investigating and found the answer. The XY slice is the easiest, since you can use slice. This is described in various C++ books. Before describing how I did, I need to prepare.I wrote a simple templated class called Volume for this purpose. You need to include . template <typename T> class Volume { private: std::valarray<T> *pV_; // valarray to store data size_t width_, height_, depth_; public: Volume(size_t w, size_t h, size_t d); // no default ctor Volume(const T *p, size_t w, size_t h, size_t d); // w*h*d elements of type T volume Volume(const Volume &v); // copy ctor Volume& operator=(const Volume& v); // assignment operator virtual ~Volume() { if (pV_) delete pV_; } // right-handed // Z (go to back) // / // /______ X // | // | // | Y std::valarray<T> sliceXY(size_t k); // row x column y std::valarray<T> sliceYX(size_t k); // row y column x std::valarray<T> sliceYZ(size_t i); // row y column z std::valarray<T> sliceZY(size_t i); // row z column y std::valarray<T> sliceZX(size_t j); // row z column x std::valarray<T> sliceXZ(size_t j); // row x column z ... (omitted) }; Here is the way to store array data into the valarray: template <typename T> Volume<T>::Volume<T>(const T *p, size_t w, size_t h, size_t d) { width_ = w; height_ = h; depth_ = d; pV_ = new std::valarray<T>(width_*height_*depth_); std::copy(p, p+w*h*d, &(*pV_)[0]); } Now I can describe my method. Here is the way to get XY slice, which you can find in many C++ books. template <typename T> std::valarray<T> Volume<T>::sliceXY(size_t k) { size_t w = width_; size_t h = height_; return (*pV_)[std::slice( k*w*h, w*h, 1)]; }; What do you do if you want the ZY slice? If you don't use gslice, then the followingwould be the way (get operation) for (size_t j = 0; j < h; ++j) for (size_t k =0; k < d; ++k) v[j*d + k] = (*pV_)[k*w*h + j*w + i]; // get That is to get the value from calculated location. Whenever you have a getalgorithm, you can find a faster one by using send operation, since get needs both target (j*d+k) and src (k*w*h+j*w+i) address calculations and send needs to calculate only the target address. gslice is the send method. (Have you ever programmed Connection Machines CM2 and CM5 (massively parallel supercomputer) ? If so, you are really aware of this fact. I worked for Thinking Machines Corp from '89 to '94.) After experimenting, I found a way to do the slice in ZY direction, using gslice. template <typename T> std::valarray<T> Volume<T>::sliceZY(size_t i) { size_t w = width_; size_t h = height_; size_t d = depth_; size_t len[2]; len[0] = h; // Y len[1] = d; // Z size_t str[2]; str[0] = w; // Y str[1] = w*h; // Z std::valarray<size_t> lengths(len,2); std::valarray<size_t> strides(str,2); return (*pV_)[std::gslice(i, lengths, strides)]; } It is weird. You must first pick the second axis and then the first axis. My guess was that this was done in the fortran way of thinking, i.e. column-major. Once I have this knowledge, I can write any slice. For example, here is the ZX slice: template <typename T> std::valarray<T> Volume<T>::sliceZX(size_t j) { size_t w = width_; size_t h = height_; size_t d = depth_; size_t len[2]; len[0] = w; // X len[1] = d; // Z size_t str[2]; str[0] = 1; // X str[1] = w*h; // Z std::valarray<size_t> lengths(len,2); std::valarray<size_t> strides(str,2); return (*pV_)[std::gslice(j*w, lengths, strides)]; } If you don't use gslice, then you would have written this "get" way: for (size_t i =0; i < w; ++i) for (size_t k = 0; k < d; ++k) v[i*d + k] = (*pV_)[k*w*h + j*w + i]; Now you know how to write a 2D slice using gslice, even for XY slice. How can I compile <valarray> in my code? (MS Visual C++ specific)This seems to be a rather well-known fact. You won't realize you need the fixuntil you try. When you include <valarray> header file, then you may get the following errors. This happened on VC++ v.7 (.NET), not on VC++ v.6. error C2059:syntac error: 'function-style cast' error C2334:unexpected token(s) preceding ':'; skipping apparent function body error C2334:unexpected token(s) preceding ':'; skipping apparent function body error C2334:unexpected token(s) preceding ':'; skipping apparent function body error C2629:unexpected 'size_t ( 'error C2629:unexpected 'std:_Bool ( 'warning C4003:not enough actual parameters for macro 'min' ... This is due to the confusion with the macro 'min'. You must set the preprocessor macro: NOMINMAX in the project setting. What is the value of 'char c=0xFF; int ic = (int) c; '?Here is the C++ program. Can you tell the result? unsigned char b = 0xFF; int bi = (int) b; char c = 0xFF; int ci = (int) c; if (bi == ci) c out << "unsigned char and char gives the same answer" << endl; else cout << "unsigned char and char gives the different answer" << endl; The result depends on whether the default char type is signed or unsigned. ANSI C and C++ do not require a specific implementation of char type. Microsoft compiler has /J flag. If signed, then ci = -1.If char is unsigned, ci = 255.ANSI Standard (ANSI/ISO 9899-1990) says in 6.1.2.5 that the behavior is implementation-defined: the values are treated as either signed or nonnegative integers. How can I input a directory name with a space, i.e. Program Files, in a pathname?Windows directory name can have a space in it. The problem is that when youwrite a program which uses ShellExecute. You have to prepare the argumentlist in a text string. When you just do the follwing: args = "c:\\Program Files\\MyApp\\input.txt";is interpreted as two arguments, C:\Program and Files\\.... In order to avoidthis problem, you have to escape the entire string by enclosing with '\"': args = "\"c:\\Program Files\\MyApp\\input.txt\""; Recommended C++ booksI like books which have no intention of showing-off and are worth reading again and again. I think the following three books are of that category.
The following books are to enhance understanding of what you learned.
How can I do iostream format printing for double?I have been used to C-style printf() formatting so long. I needed a translation dictionary to use C++ way of doing things. Here are some examples. double d = 123.456789; printf("%12.4f\n", d); is equivalent to cout.setf(ios::fixed, ios::floatfield); // precision applies to digit cout.precision(4); // precision persists cout << setw(12) << d << endl; // set widthwhere precision() specifies number of digits after decimal points. Note that you could use cout.width(12);. However, width()applies only to the next stream operation. In order to emphasize this fact,I used the iomanipulator setw() by including <iomanip> headerfile. You can use manipulators in the following way (gcc 2.96 does notunderstand "fixed") to get the same result: cout << fixed << setprecision(4) << setw(12) << d << endl; Next one is the g-format example. double d = 123.456789; printf("%g\n", d); // is equivalent to cout.setf(ios::fmtflags(0), ios::floatfield); // default value cout.precision(6); // default value cout << d << endl; // where precision() specifies the entire digit including integer part. You can remember the io flags and reset it by using flags(): ios::fmtflags oldflags = cout.flags(); ... cout.flags(oldflags); I don't use the scientific notation often (ios::scientific). How can I print 0012 from int i=12?int i = 12; cout << setw(4) << setfill('0') << i << endl; How can I use stream to do the task of 'scanf'?C programmer uses "scanf" to do variable translation. For example, char buf[] = "Value 12 1.2345 1.2345"; char msg[128]; int val; double dval; float fval; sscanf(buf,"%s %d %lf %f", msg, &val, &dval, &fval); /* note that %lf for double */ is equivalent to stringstream st(buf); // using the same buf st >> mgs >> val >> dval >> fval; Why can't I use eof for reading stop signal?I happened to write the following "bad" code counter=0; while (!input.eof()) { input.getline(buf, sizeof(buf)); ... counter++; }; I found that it is always executed one more time than necessary. If you think carefully, you understand. The fact of life:the computer program cannot predict future. The stream does not know whether it is at the end of the file or not until it tries to read one more character. Thus, the better way is to write this way: counter=0; while (input.getline(buf, sizeof(buf))) { ... counter++; }; How can I use an instance of a function template be friend?Here is the situation.I have a template class of the following: template <typename T> class Volume { ... }; I like to have a friend operator==() for this class. How can I write such a case? template <typename T> class Volume { ... friend bool operator==<>(const Volume &p, const Volume &q); }; template <typename T> bool operator==(const Volume<T> &p, const Volume<T> &q) { // implementation } It is essential to have <> in the declaration. How can I get back the newed value?Sometimes you want to get back a newed resource from a function. (You are responsible for deleting this resource later.) Note that C/C++ calling convention is copied the variable in the argument. Thus the following will work: // caller part: Element *pElement; // allocate the pointer value storage getBackElement(&pElement); // gives the address of the storage (... use pElement) delete pElement; // callee part: void getBackElement(Element **ppElement) // get the address of storage { Element *pNew = new Element(); *ppElement = pNew; // ppElement = &pNew; does not work! // set the value at the storage address location } How can I clear stringstream?I wanted to use stringstream for both input and output andwant to use repeatedly. I need to clear stringstream.Here is how. stringstream mystream;mystream.str(std::string()); Updated 10/14/2009 |
Programming‎ > ‎