Help - Search - Members - Calendar
Full Version: C++ Help
Hydrogenaudio Forums > Hosted Forums > foobar2000 > Development - (fb2k)
kl33per
I'm new to C++ so cut me some slack.

I have some code here

CODE

char temp[32];

//cut out everything inbetween

sprintf(temp,"%d",st->wDayOfWeek);


I now want to test temp in an if statement, but can't seem to be able to do it. As I understand it, temp should be a number 0-6, but I can't get the if statement to work. Do I need to cast, and if so, how do I do that in C++.

Edit: As an appendum to this, how do you evaluate TAGZ in the SDK.
Aero
QUOTE(kl33per @ May 14 2005, 11:30 PM)
I have some code here

CODE

char temp[32];

//cut out everything inbetween

sprintf(temp,"%d",st->wDayOfWeek);


I now want to test temp in an if statement, but can't seem to be able to do it.  As I understand it, temp should be a number 0-6, but I can't get the if statement to work.  Do I need to cast, and if so, how do I do that in C++.
*


Is there a reason why you are converting the (presumably) int st->wDayOfWeek to a string? Strings are very hard to work with in C/C++...

Why not just access wDayOfWeek as an int?
CODE
if(st->wDayOfWeek >= 1 && st->wDayOfWeek <=5)
{
  // This is a week day
}
else
{
 // Everybody is working for the weekend...
}
kl33per
I just realised it would be better if I had it output numbers only (and not written days of the week) and then users could format it with TAGZ.

The problem is that some days have six letters (Sunday, Monday, Friday), some have seven (Tuesday) and some have eight (Wednesday, Thursday, Saturday).

However, your post has still be most helpful, and I wil take note. BTW, I had noticed reading through MSDN that strings are an absolute pain in the ass with C++. VB and Java are so much simpler (better not say that to loud smile.gif).

I also still need to know how to evaluate TAGZ.
kl33per
Another question.

CODE

static cfg_int

//removed

   cfg_seconds("seconds",0);

//removed

case (EN_CHANGE<<16)|IDC_SECONDS:
   cfg_seconds = uSendMessage(uGetDlgItem(wnd,IDC_IDC_SECONDS),EM_GETLINE,0,0);
   break;

I know it's wrong, and that EM_GETLINE writes to a buffer, but I'm not sure how to set it up properly.
kl33per
For reference, I solved the problem with this:

CODE
 
case (EN_CHANGE<<16)|IDC_SECONDS:
   BOOL result;
   if ( true )
   {
       unsigned temp_seconds = GetDlgItemInt(wnd, IDC_SECONDS, &result, FALSE);
       if ( result )
           cfg_seconds = temp_seconds;
   }
break;
Supernaut
Seeing as you find C strings hard to work with, you might want to try the string class (part of the Standard Template Library which is part of the C++ standard). The strings in it are much more like Pascal/Java strings: they auto-resize, you can concatenate them with '+' and do all sorts of other nifty things. #include <string> to use it.
kl33per
Thank you very much, concatenate strings was something I was trying to figure out how to do earlier.
kode54
There is a lighter string8 class, and even lighter string_basic class, both of which are in PFC and used extensively by foobar2000, parts of the SDK, and various components. You may want to consider if this will fill your needs before you pull in larger dependencies like the STL. I'm not sure if they support "blah" + "blah" + "blah", but they certainly support += "blah". Search around the SDK for useful examples.
kl33per
Yeah, I found string8 which is suitable for most/all my needs.
kl33per
I can't find basic_string, but anyway... I have another question. How do I compare two string8's. == doesn't seem to work.

What I really want to do is use a not operator.

CODE
string8 val1 = info.meta_get("LAST_PLAYED",0);
string8 val2 = info.meta_get("FIRST_PLAYED",0);

if ( val1 != val2 )
{
   //blah
}
kl33per
Solved above with:

CODE
 
if ( cfg_write_play_stamp == 1 )
   {
       if (info.meta_get_count_by_name("FIRST_PLAYED") > 0)
       {
           string8 val1 = info.meta_get("LAST_PLAYED",0);
           string8 val2 = info.meta_get("FIRST_PLAYED",0);
           if ( stricmp_utf8(val1,val2) )
           {
               if ( !val1.is_empty() )
                   info.meta_add("PLAY STAMP",val1);
           }
       }
   }
Otto42
Just a little input that might help... C-style strings 101. smile.gif

C-style strings like you were originally having problems with are not really "strings" as such. They're arrays of characters. By convention, the "string" is null-terminated, meaning that the last byte in it is a NULL, or '\0' if you prefer.

char temp[32];
This defines an array of 32 chars. If you were to do:
sprintf(temp,"test");
You'd get values like this:
temp[0] = 't';
temp[1] = 'e';
temp[2] = 's';
temp[3] = 't';
temp[4] = '\0';

For handling these style of strings, look into the "str*" functions.
strcat - Concatenates a couple of strings.
strcpy - Copies one string to another.
strcmp - Compares two strings.
And so on... There's variations on these, like stricmp which is case insensitive, and strncpy which copies only a number of characters and so on. There's a lot of them, and looking into some documentation would be a good idea.

Note that C-style strings are prone to buffer overflows, because there's no bounds checking. That temp variable is 31 characters long, plus a character for the NULL terminate. If you tried to put something in longer than that, it would overwrite the end of it and basically overwrite stuff on the stack. Meaning that if you use these, you need to be very careful and be sure that you don't do that. Usually this means more complicated code.

In C++, most people prefer to use an actual string class, which does it's own bounds checking, can resize as needed, and so forth. std::string is good for this sort of thing. Just #include <string> and then declare your variable like this:
string temp;

string is actually a basic_string in disguise. If you want to be able to handle stuff like Unicode and such, then it's worth the effort to look into other string classes designed with this stuff in mind.

Old C-Style strings still come in handy every once in a while for quick coding because they're actually pretty easy to use, and they're incredibly fast by comparison to most string classes. But in production level code, generally they should be avoided.
kl33per
Thanks Otto, that is unbelievably helpful.

So basically there are no strings (without including additional classes), just arrays of char's. Despite the fact that this was staring me right in the face (can't count the number of times I've seen char blah[32] smile.gif), my brain just didn't figure that out on it's own. It actually makes a lot of sense now that you've stated it plainly.

Edit: Some things are so backwards in C++, whilst others seem to be fairly progressive (compared to VB6/Java anyway). Quite an interesting (and absurd at times) language.
Otto42
QUOTE(kl33per @ May 16 2005, 07:33 AM)
Thanks Otto, that is unbelievably helpful.

So basically there are no strings (without including additional classes), just arrays of char's.  Despite the fact that this was staring me right in the face (can't count the number of times I've seen char blah[32] smile.gif), my brain just didn't figure that out on it's own.  It actually makes a lot of sense now that you've stated it plainly.

Edit: Some things are so backwards in C++, whilst others seem to be fairly progressive (compared to VB6/Java anyway).  Quite an interesting (and absurd at times) language.
*


Just a minor nitpick, but C++ does have real strings. That's what std::string is. The array of chars thing is a C thing, not a C++ thing. In other words, "char blah[32]" is C code, not C++ code.

C++ is actually quite non-absurd, if you stick to pure C++. But the fact is that you have all this original C stuff underlying it all, and when you mix the two of them, it seems more absurd than it really is. And you almost have to mix them to get anything useful done. wink.gif

Trying to learn C++ without knowing what's original C and what is added on by C++ could be somewhat difficult... Might start with C instead, and work up to C++. Or at least keep in mind that "classes" are entirely a C++ invention along with other things like templates and so forth.
kl33per
I see. Indeed I have a lot to learn. One day...

Edit: Have you looked at the D Programming Language. Very interesting stuff.
kl33per
Another question.

In tags, how do I specify a new line. For example say I had two pieces of information, A and B. A is currently store in a tag, and I want to store B on a new line in the same tag.


CODE

string8 A = info.meta_get("PLAY_STAMP",0);
string8 B = "blah2";
A += B;


Obviously I need to add some sort of UTF-8 Line Feed character between A and B. How do I do this?
kl33per
I tried using:
CODE
char val4[2] = "\n";
as the character in between, but that does not work.

Edit:
This works.
CODE
char val4[4] = "\r\n";
OCedHrt
Ahh..the joys of C++. Can't call myself an expert, only have a year or two of experience from class, but I'll try to help as well smile.gif
kalmark
QUOTE(kl33per @ May 17 2005, 03:56 AM)
I tried using:
CODE
char val4[2] = "\n";
as the character in between, but that does not work.

Edit:
This works.
CODE
char val4[4] = "\r\n";

*


IMHO \n and \r count as one character, so you don't need a doubled length array to contain them.

e.g.
CODE
char a = '\n';
char b = '\r';
kl33per
QUOTE(OCedHrt @ May 17 2005, 09:26 PM)
Ahh..the joys of C++. Can't call myself an expert, only have a year or two of experience from class, but I'll try to help as well smile.gif
*


Thanks. Until I started modifying foo_playcount, I had aboslutely no experience in C++. Now I still no basically nothing, but I'm learning. Have written lots of VB6 in the past (which was a bad idea, and I picked up a lot of bad habits). In the last year I've learnt the basics of Java, but haven't used it extensively (I haven't written any large apps anyway).
foosion
QUOTE(kalmark @ May 17 2005, 12:58 PM)
IMHO \n and \r count as one character, so you don't need a doubled length array to contain them.
*
That's two characters, so the char array needs to have 3 elements (for the terminating zero).

Going back to the code snipped that used string8, you could add a (DOS) linebreak to a string like this:
CODE
string8 A = info.meta_get("PLAY_STAMP",0);
A += "\r\n";
A += "blah";

kl33per
Thanks, will make the change.
kalmark
QUOTE(foosion @ May 17 2005, 03:26 PM)
That's two characters, so the char array needs to have 3 elements (for the terminating zero)
Yep, I know, I tried to clarify what I meant in the example smile.gif I was not really successful, right? rolleyes.gif
seanyseansean
QUOTE(kl33per @ May 16 2005, 02:33 PM)
Thanks Otto, that is unbelievably helpful.

So basically there are no strings (without including additional classes), just arrays of char's.  Despite the fact that this was staring me right in the face (can't count the number of times I've seen char blah[32] smile.gif), my brain just didn't figure that out on it's own.  It actually makes a lot of sense now that you've stated it plainly.

Edit: Some things are so backwards in C++, whilst others seem to be fairly progressive (compared to VB6/Java anyway).  Quite an interesting (and absurd at times) language.
*



I had the same problems with these strings. I had to interface C++ code with VB6 components with VB style strings, and as 'strings' is a term independent of implementation it gets a bit confusing. Thanks for adding clarity to this thread, Otto.

wilson
i'm sorry,,,i can't the class of string8, can everybaby tell me? thx!
Dibrom
One thing to keep in mind about C, especially when comparing it to high level languages (I consider a high level language to be something like ML, Oz, Haskell, Scheme, etc.), is that C really isn't a whole lot more than a slightly more convenient, portable "assembly".

I think a lot of what is confusing about C is that it's difficult to understand why most things are done the way that they are until you really start to understand memory management at a low level. Pure assembly is obviously the best help there, but it's even more difficult to learn than C considering the lack of easily accessible tutorials and documentation (have fun wading through the cpu reference manual to dig up the instruction list..).

At any rate, I highly suggest picking up a copy of C Programming Language. It's quite a small book that covers all of the important stuff and leaves out all of the unneccessary fluff. It's probably the best C book I've ever read, and the only one I've ever really ended up needing.

C++ is a different story, but trying to jump straight into that before having a really solid understanding of C (including an understanding of how you can "fake" a lot of the features you get in C++ in plain old C) is a recipe for frustration.
kl33per
Thanks Dibrom, will try and get a copy of that book.
kode54
<Random insight>

Your meta_get comparison would be a lot faster if you used const char * instead of string8. The current method would be allocating two new buffers and copying the strings before comparing them. I suppose this wouldn't be a problem if the info class used string8 and string8 had a copy constructor which could use reference counting, and even performing duplication where necessary. (For example, refcount and string both in buffer, and if something needs to modify string, internal or external call a unique() method which dupes the string and sets refcount to 1 on local copy.) That's getting a little too complicated, though.

</Random insight>
kl33per
I'm continually amazed at how some of the seemingly most basic things in C++ are made so complex. Programming languages shouldn't be (and as far as I can work out need not be) this complex. Anyway, onto my question...

How do I implement tabs in a dialog box. Sounds simple, I know, but damned if I can figure it out. I've looked at MSDN, but as usual it's a highly technical view of what to do. I've also looked at foo_history, which has helped a little, but the code spans several files, and most of it I can't get my head around.

Basically, I've set up my dialogs in the same manor as foo_history, with one main dialog page as the config page, and then seperate child dialog's for each tab. I looked at foosion's code, but it uses so many files, you've got prefs.cpp, prefs.h, the foosion helpers, and goodness knows what else. Seems overly complex to implement a tab. I'm looking for the really simple, no frills apporach here. Any help is appreciated.

@ Dibrom, I've orded that book you suggested. I anxiously await it's arival.
Otto42
I'm not real familiar with how, exactly, the foobar stuff works. But essentially you're asking about Property Sheets.

You basically create a class for each page you want to display. This class will derive from CPropertyPage. It'll hold all the controls and layout and such for the page itself. It'll have all the member variables in it to hold the data you get from these controls and so forth.

All these pages get held in a CPropertySheet. You instantiate a CPropertySheet object. Then you instantiate an object for each one of these CPropertyPage derived-classes. For each one of these you create, you add it to the PropertySheet via it's AddPage() function.

How you then get that property sheet to display in the foobar preferences, I do not know. Normally you'd tell it to DoModal() to display a dialog box, or you'd Create() it to do it modelessly. You can probably figure out how to do it by looking at how foo_history does it.

But in any case, that's the gist of it.
hunted
Although I havn't used tabs personally, just by looking at MSDN, you dont really need to use property sheets, although you can. I think thats making it more complex than regular tabs.
All you need to do is create the tab control.
Then wait for messages that the selection changed.
And then display the right page.
You said you read MSDN, were you looking at the example code, its pretty basic and links to all the important macros, messages, and structures.
In the example code:
DoCreateTabControl() creates the tab control and adds the tabs.
MainWindowProc() handles the most basic messages.
TCN_SELCHANGE is wParam of WM_NOTIFY which tells you that they changed the tab.

the important macros are:
TabCtrl_InsertItem()
TabCtrl_GetCurSel()
TabCtrl_AdjustRect()

I'm sure someone more familiar with tabs will be able to provide more info.
Otto42
Meh. Six of one, half dozen of the other. If you're already using MFC, property sheets seem simpler.
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Invision Power Board © 2001-2008 Invision Power Services, Inc.