|
Remember that strings are immutable
This is not true in standard C++. Did you think of C# or some pre-standard implementation of STL?
|
|
|
|
|
Cool Cow Orjan wrote: Did you think of C#
Yep, my brain can only handle one language at a time.
However, the code still works.
|
|
|
|
|
If you want to replace the character '<' in a string with, "<", it could be done quite simply in C++ like this:
void replace_html_delimiters(std::string& str)
{
std::string::size_type pos = str.find("<");
while (std::string::npos != pos)
{
str.replace(pos, 1, "<");
pos = str.find("<", pos + 4);
}
}
Or if you want to cover the closing '>' as well:
void replace_html_delimiters(std::string& str)
{
std::string::size_type pos = str.find_first_of("<>");
while (std::string::npos != pos)
{
if ('<' == str[pos])
str.replace(pos, 1, "<");
else
str.replace(pos, 1, ">");
pos = str.find_first_of("<>", pos + 4);
}
}
By the way, I assume that you had < in your code example, and that CodeProject converted it to < when you posted it? This can be avoided by escaping out the leading ampersand (& is also a reserved character in HTML, like < and > ) like this: &lt; .
Otherwise, your C code would simply replace the character '<' with the character '<', with lots of copying back and forth.
void replace_html_delimiters(char *msg)
{
for(i=0; ; i++)
{
if(msg[i]== NUL)
break; if(msg[i]=='<')
{
msg[i] = NUL; strcpy(z_buf,msg); strcat(z_buf,"<"); strcat(z_buf,msg+i+1); strcpy(msg,z_buf); }
}
}
And that could be rewritten very effectively like this:
void replace_html_delimiters(char *msg)
{
}
|
|
|
|
|
First, the original code should compile and work for any C++ compiler. Almost any C code should, as long as your function declarations contain the full parameter list (this was not mandatory in C, but is in C++). If the function doesn't work as intended in C++, then it didn't in C either!
If your intention is to refactor the code into something that more resembles C++ coding standard, here's a few pointers:
1. Do not use #define for constants. C++ introduced the const keyword for that purpose and AFAIK ANSI C as well. #define always introduces a risk, as it replaces text without concern for the context, and therefore might break your code in places that it was not meant to affect. It's even worse when #define s are used in headers, making the replacement global.
2. Do not use magic numbers. Magic numbers are numeric or string literals that are used within the code to define array boundaries, values passed to functions, or limits used for loops. It's almost always better to instead define a constant, using a name that explains its purpose or use. There are multiple advantages of doing this: First, if you ever need to change the value you only need to change it in one place, no matter how often you used it, and no matter whether others used it in places that you don't even know of; Second, the name of the constant explains what it is, saving people the effort to somehow divine it from the context or (nonexistent) comments; Third, constant names are often easier to remember than the literals they represent. And intelligent editors will even remember these names for you.
3. Use std::string instead of C-style 0-terminated strings. They are sometimes more awkward to use, but they're fast and generally more safe. They also manage their own memory, so you don't need to allocate an arbitrarily sized buffer yourself, nor do you need to care about its deallocation. Also there are already plenty of functions available in the STL, either as member functions of std::string , or as generic functions found in algorithm:: (unfortunately though, none of them exactly reciprokes your function)
4. Be careful when using index values for std::string , or in fact any of the containers of the STL. For one, many functions in the STL require iterators, not index values; most of the time index values - if provided for a container - can be used to read (or write) an element, but nothing else! Second, checking for the end (or start) of a range is often not easily possible with index values, as you have noticed yourself. The usual method for iterating oover the contents of an STL container, and that includes strings, is by using iterators.
5. Don't use break , nor multiple return statements in a function: they are just as bad as goto in that they obscure the program flow and make it unneccesarily hard to understand the code. The best way to replace a break is putting the condition into the loop header. If some of the code needs to be skipped, store the condition in a variable that is used both in the loop header and in an if statement that encapsulates the part of the loop that needs to be skipped. The important part is that the condition(s) that end a loop should always be visible in the header, so anyone trying to analyze the program flow can immediately see whether a loop will be invoked at all, and for how long. (you already rightfully asked why there is no end condition in the C-style for loop!)
6. If you need a function that works on a STL object (in this case std::string ), check for functions already in existance and learn how to use them. E. g. for std::string , check out http://www.cplusplus.com/reference/string/string/[^]
With all of the above (and more) in mind, your code should like something like this (not tested):
#include <string>
#include <iostream>
const std::string LESSER_THAN_SIGN = "<"; const std::string LESSER_THAN_HTML = "<"; const std::string GREATER_THAN_SIGN = ">"; const std::string GREATER_THAN_HTML = ">";
void replace_all(std::string& text, const std::string& from, const std::string& to) {
std::size_t textpos = 0; std::size_t replaced_length = from.length(); while ((textpos = string.find(from, textpos)) != std::string::npos) {
text.replace(textpos, replaced_length, to);
}
}
int main() {
std::string text("<b>some fat text</b>");
replace_all(text, LESSER_THAN_SIGN, LESSER_THAN_HTML);
replace_all(text, GREATER_THAN_SIGN, GREATER_THAN_HTML);
std::cout << text << std::endl;
return 0;
}
Note: I used the JavaDoc style for commenting the function. This style is also used by Doxygen, a tool that like JavaDoc can automatically extract a full function level HTML documentation from these type of formatted comments. Even if you don't use DoxyGen, it is generally a good idea to define *some* standard for commenting each function.
Sorry this turned out rather longer than intended, but I hope you will appreciate it anyway
|
|
|
|
|
Stefan_Lang wrote: Sorry this turned out rather longer than
Don't apologise, it's an excellent analysis of the issues, and solution.
|
|
|
|
|
Stefan_Lang wrote: Sorry this turned out rather longer than intended, but I hope you will appreciate it anyway
Only ever apologise to yourself, for the time lost writing an excellent post
|
|
|
|
|
Dear Friends
I am wirting an application for drawing a rectangle on the screen using opengl and mfc. So I implemented the OnPaint function, OnDraw function is also giving the same problem. It's drawing fine. I want to implement pan, zoom, and rotate functionalities. Now everytime the mouse moves I am calling Invalidate() or otherwise I can call Invalidate() in the ::OnDraw function. Pan, zoom and rotate everything is happening but its heavily flickering. I have serached a lot and tried all means like return 1 in the OnEraseBackground() functio for WM_ERASEBACKGROUND etc. But I am getting still flickering . Please help getting rid of this problem. Check the code snippet below.
void CRevolutionProjView::OnPaint()
{
CPaintDC dc(this); // device context for painting
// TODO: Add your message handler code here
CRect RectAff;
GetClientRect(RectAff);
glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ) ;
glClear ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
glPushMatrix( ) ;
glTranslatef(trans[0], trans[1], trans[2]);
glRotatef(rot[0], 1.0f, 0.0f, 0.0f);
glRotatef(rot[1], 0.0f, 1.0f, 0.0f);
drawcube();
glPopMatrix( ) ;
glFinish( ) ;
glFlush();
SwapBuffers(hDC);
Invalidate(false);
// Do not call CView::OnPaint() for painting messages
}
void CRevolutionProjView::OnMouseMove(UINT nFlags, CPoint point)
{
newP = point;
// TODO: Add your message handler code here and/or call default
int dx = oldP.x - newP.x;
int dy = newP.y - oldP.y;
switch(STATE)
{
case PAN:
{
trans[0] -= dx/100.0f;
trans[1] -= dy/100.0f;
// Invalidate();
}
break;
case ZOOM:
{
trans[2] -= (dx+dy) / 100.0f;
// Invalidate();
}
break;
case ROTATE:
{
rot[0] += (dy * 180.0f) / 500.0f;
rot[1] -= (dx * 180.0f) / 500.0f;
#define clamp(x) x = x > 360.0f ? x-360.0f : x < -360.0f ? x+=360.0f : x
clamp(rot[0]);
clamp(rot[1]);
// Invalidate();
}
break;
}
oldP = newP;
CView::OnMouseMove(nFlags, point);
}
|
|
|
|
|
|
I would recommend that you create an off screen bitmap, render the open GL image to that and then StretchBlt or equivalent to the display.
I recently developed a 2d/3d graphing system that supported 3d by openGL and it worked well using this method.
If you vote me down, my score will only get lower
|
|
|
|
|
Hi,
I thought I'd cracked this problem but it seems that I was wrong. Although I know now that the problem lies with the operating system.
I want to display a web page in a window. I realized that this is possible with the ShowHTMLDialog function, however it only works in windows XP not windows 7. There is something else though: I can get a web page to display when I run the program directly in visual studio but not when I run it as a stand-alone application(in windows 7). So I think the problem is that some required dlls are being loaded when I run it in visual studio but not as standalone.
It seems that the only dll i need for ShowHTMLDialog is mshtml.dll but I'm not sure if other dlls with different versions from windows XP are being used.
What's going on when I run the program from visual studio that is different from running the program on it's own ? How do I get ShowHTMLDialog to work in windows 7 ?
(I'm not using MFC)
thanks,
|
|
|
|
|
What kind of error are you getting? Not really sure what you mean when you say it only works on Windows XP, not Windows 7. You might be able to try using the dependancy walker application to find out what DLLs are needed by your application, thouhg.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
the error is that the program crashes on a call to ShowHTMLDialog(only on windows 7) and no dialog window appears.
thanks, I will check out the dependancy walker
|
|
|
|
|
Now that I checked here[^], I doubt that Dependancy Walker will help. You are going to have step through your code and find out which line of code is failing. My wild-ass guess would be that a call to GetProcAddress is probably not behaving as you expect it to.
Chris Meech
I am Canadian. [heard in a local bar]
In theory there is no difference between theory and practice. In practice there is. [Yogi Berra]
posting about Crystal Reports here is like discussing gay marriage on a catholic church’s website.[Nishant Sivakumar]
|
|
|
|
|
Ah, the problem is where I convert a char string to wide char string. I need to convert the url I want to display to a wide char string and if I leave that code out and just specify google as the url, the program works in windows 7.
I'm not sure what I'm doing wrong with the conversion ?
char url[MAX_PATH];
_getcwd(url, MAX_PATH);
std::string file = url;
file += "\\Help.html\0";
OLECHAR* oleChar = NULL;
oleChar = (OLECHAR*)calloc(file.length(), sizeof(OLECHAR));
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, file.c_str(), -1, oleChar, sizeof(OLECHAR)*file.length());
BSTR bstrURL = SysAllocString(oleChar);
|
|
|
|
|
hi,
how do i know index of an iterator of a map?
map<int, int>::iterator it = mymap.find(3);
i want to know index of 'it' in mymap???
Zo.Naderi-Iran
|
|
|
|
|
You can increment a counter in a loop.
But why do you need this.
std::map always works on the key and so you must not use the index to perform any operations on the map.
Here is something you could do -
map<int, string> num;
int j = 0;
for (auto i = num.begin(); i != num.end(); ++i, ++j)
{
if ((*i).first == 5)
cout << j << endl;
}
Don't know if there is any other way to do this.
|
|
|
|
|
maps are not arranged in a simple linear order (they are trees), so there is no 'index' for an item.
|
|
|
|
|
int a[33*1024];
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
HANDLE hReadThread = NULL;
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
_tprintf(_T("Fatal Error: MFC initialization failed\n"));
nRetCode = 1;
}
else
{
hReadThread = AfxBeginThread(ThreadWrite,0);
}
WaitForSingleObject(hReadThread,INFINITE);
return nRetCode;
}
UINT ThreadWrite(LPVOID lParam)
{
for(int i=0; i < 32*1024; i++)
{
a[i]=i;
cout<<"Write:" << a[i];
}
return 1;
}
Why in above program,
WaitForSingleObject() is not wating for thread comletion?
|
|
|
|
|
Because AfxBeginThread returns a pointer to a CWinThread object, not a thread handle (see "AfxBeginThread" at MSDN[^]).
You have to change from:
john5632 wrote: hReadThread = AfxBeginThread(ThreadWrite,0);
to (error checks left to the reader)
CWinThread * pWinThread = AfxBeginThread(ThreadWrite,0);
hReadThread = pWinThread->m_hThread;
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
|
You are welcome.
If the Lord God Almighty had consulted me before embarking upon the Creation, I would have recommended something simpler.
-- Alfonso the Wise, 13th Century King of Castile.
This is going on my arrogant assumptions. You may have a superb reason why I'm completely wrong.
-- Iain Clarke
[My articles]
|
|
|
|
|
Yep...
|
|
|
|
|
Can you tell me where I found the CHKBOOK sample project ? Because here [^] I found only documentation, not project source ... Thank you.
|
|
|
|
|
|
Sorry, I didn't see any CHKBOOK sample ...
|
|
|
|
|