Notice: Any messages purporting to come from this site telling you that your password has expired, or that you need to "verify" your details, making threats, or asking for money, are
spam. We do not email users with any such messages. If you have lost your password you can obtain a new one by using the
password reset link.
Entire forum
➜ Programming
➜ General
➜ gethostname and other goodies
gethostname and other goodies
|
It is now over 60 days since the last post. This thread is closed.
Refresh page
Posted by
| Trask
Australia (23 posts) Bio
|
Date
| Wed 19 Aug 2009 04:21 PM (UTC) |
Message
| Hi all,
I wrote myself a little program, just to prove a concept to myself, which came back with very unexpected and varied results. Could someone take the time to explain these findings to me?
Test 0
#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
cout << "Computer Name : " << system("uname -n") << endl;
output:
MyComputerName
Computer Name : 0
Test 1
#include <iostream>
#include <string>
#include <stdlib.h>
#include <stdio.h>
using namespace std;
int main()
{
char hostName[128] = system("uname -n");
cout << "Computer Name : " << hostName << endl;
output:
test.cpp:12: error: array must be initialized with a brace-enclosed initializer
Why does this error occur everytime I try to initialize a variable with a function?
I also noticed somewhere whilst browsing the web for this problem, that #include <cstdlib> seems to be used instead of (stdio/stdlib).h Is this correct?
Test 2
#include <iostream>
#include <string>
using namespace std;
int main()
{
FILE *hostName;
hostName = popen("uname -n","r");
pclose(hostName);
cout << "Computer Name : " << hostName << endl;
output:
Computer Name : 0xbbd010
Test3
#include <iostream>
#include <string>
using namespace std;
int main()
{
char hostName[128];
cout << "Computer Name : " << gethostname(hostName,128) << endl;
output:
Computer Name : 0
And finally!
Test4
#include <iostream>
#include <string>
using namespace std;
int main()
{
char hostName[128];
gethostname(hostName, 128);
cout << "Computer Name : " << hostName << endl;
output:
Computer Name : MyComputerName
yay, it did what it was meant to do :)
The main concepts learnt seemed to be:
1) I can't initialise variables with functions
2) I can't call a function in the middle of a cout line and expect to get away with it.
Are these correct? And is there some reference that explains the functions in the common/standard C++ libraries? i.e. how do I find out what functions do what?
And now as it relates to TinyMud,
After all this testing, I added the following code:
globals.cpp
char hostName[128];
globals.h
extern char hostName[128];
comms.cpp
gethostname(hostName,128);
p* << "Welcome to TinyMud Server << VERSION << " running on " << hostName << "\n";
Is this the most efficient/correct way of implementing this?
And one final question: Is there a neater way of shutting down TinyMud, as opposed to killall tinymudserver ?
Sorry if this post is convoluted and lacking in logical progression, my mind is erratic at best.
Thanks heaps! | Top |
|
Posted by
| Twisol
USA (2,257 posts) Bio
|
Date
| Reply #1 on Wed 19 Aug 2009 04:34 PM (UTC) Amended on Wed 19 Aug 2009 04:35 PM (UTC) by Twisol
|
Message
|
|
To make your code more readable please use [code] tags as described here.
|
Anyways, on #1, that's because you defined an array. I can't explain it exactly (because I'm tired and also every so slightly rusty with C), but you're trying to assign the return result of system() to an array (and system() returns an int anyways, according to (1)). 0 in #0 is the status return code from the 'uname' program... if you've ever done much C, it's the 'return 0' you put at the end of main().
On #2, a FILE* is a file descriptor, not a string. I believe it's meant to be used as a handle to the process you started with popen().
On #3, if you couldn't tell, gethostname() returns an integer, but it does copy to the buffer. That's why in #4 it worked, because you copied to the buffer and then used the buffer rather than the functions return code.
(1) http://www.cplusplus.com/reference/clibrary/cstdlib/system/ |
'Soludra' on Achaea
Blog: http://jonathan.com/
GitHub: http://github.com/Twisol | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #2 on Wed 19 Aug 2009 07:49 PM (UTC) |
Message
| Twisol pretty much explained it.
Basically, I think you're running into extremely common frustrations with C/C++, namely that you can't just "do things" and have to jump through lots of hoops to do what seem like relatively simple tasks such as getting the output of a process. For example, yes, you can open a pipe to a process, but before you can use that output, you need to read out from the file until EOF, etc.
For all its benefits, C++ is most certainly not a terribly friendly language, and it doesn't make life easy. :-/
Some clarifications/elaborations on what Twisol said:
Quote: 1) I can't initialise variables with functions
You can, it's just that you weren't getting what you thought you were. The return values of the functions were not of the appropriate type. An integer is not an array of characters, for example.
Quote: 2) I can't call a function in the middle of a cout line and expect to get away with it.
You can, but the cout streaming will use the return values, whereas that function doesn't return the hostname -- it sets it into a buffer. (The reason is, basically, that it has to because of how C works -- it's a C library.) So you printed out the return value (which was 0) and the buffer was set, but you didn't print out the buffer. |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Nick Gammon
Australia (23,052 posts) Bio
Forum Administrator |
Date
| Reply #3 on Wed 19 Aug 2009 09:44 PM (UTC) |
Message
|
Quote:
And one final question: Is there a neater way of shutting down TinyMud, as opposed to killall tinymudserver ?
commandmap ["shut"] = DoShutdown; // shut MUD down
A word of caution here, gethostname is, I think, synchronous.
What that means briefly is that it looks up the host name whilst blocking your program. Say it has to go to a DNS server, and doesn't find one, or find one quickly, your program may seem to "hang" for a few seconds.
As for the other things, I agree with the other guys. You need to pay close attention to the defined return codes for functions. Many functions simply return success or failure (often success is zero, but certainly not always). If a value is also returned it may well be through an argument that is passed by reference, or is a pointer. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Trask
Australia (23 posts) Bio
|
Date
| Reply #4 on Thu 20 Aug 2009 03:36 AM (UTC) Amended on Thu 20 Aug 2009 03:45 AM (UTC) by Trask
|
Message
| Thanks very much for the replies guys,
Quote: A word of caution here, gethostname is, I think, synchronous.
What that means briefly is that it looks up the host name whilst blocking your program. Say it has to go to a DNS server, and doesn't find one, or find one quickly, your program may seem to "hang" for a few seconds.
Would this therefore be one of those instance where a script would be a better means of implementing this?
I got the idea from DoT mud, but I couldn't figure out how they implemented it in their code, bit too complex for me.
Such a simple little program has already taught me a lot about C/C++. I think it might be a good idea to have a poke through that /usr/include/ directory David pointed me to.
Cheers for the help, having people to ask questions of certainly makes the trials of a newbie coder a little easier... for the newbie at least :P
Thanks again | Top |
|
Posted by
| David Haley
USA (3,881 posts) Bio
|
Date
| Reply #5 on Thu 20 Aug 2009 04:49 AM (UTC) |
Message
| Glad that we can be of help :-) There's nothing wrong with being new, we were all there. People who are new but willing to learn and put in the effort to understand are usually extremely well-received, at least in my experience. It's the people who want others to write their code that tend to get the cold shoulder. ;)
Quote: Would this therefore be one of those instance where a script would be a better means of implementing this?
It depends on what you mean and what you want. If you want a small standalone program, then often scripting languages give you far more tools to "just do it" without the hoops that C++ puts you through. If you need this to happen inside a C++ application, it might or might not be easy to embed a scripting language interpreter. Lua is extremely easy to embed (when compared to other languages), but it doesn't have as many libraries for talking to the system in various ways.
The thing is, though, that you only need to write the fundamental code once to get some process's results. I can give you 100 to 1 odds that there is a library out there that takes a system command and returns a std::string or something similar with the results -- essentially abstracting away the whole process of opening the pipe, reading from it, etc.
Quote: I think it might be a good idea to have a poke through that /usr/include/ directory David pointed me to.
It might be worth mentioning that what you'll find in there is not necessarily intuitive, newbie-friendly or understandable. I find it rather opaque, to be honest, and find the man pages to be far more accessible. The problem with man pages is that you usually need to know what you're looking for in order to find it (catch 22!). |
David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone
http://david.the-haleys.org | Top |
|
Posted by
| Trask
Australia (23 posts) Bio
|
Date
| Reply #6 on Thu 20 Aug 2009 06:00 AM (UTC) |
Message
|
Quote: I can give you 100 to 1 odds that there is a library out there that takes a system command and returns a std::string or something similar with the results -- essentially abstracting away the whole process of opening the pipe, reading from it, etc.
I googled for this extensively before I posted my original question on the forums, and most of the results suggested uname and popen as options... Although it could have been the case that at some point, I was clearly staring at the solution and was simply to ignorant to realise it :)
I think this is going to be my greatest frustration in regards to coding, namely the catch 22 you mentioned. In order to find out information about a function, you already need to know about the function. Gah, why do the coding gods hate me so?!? :)
In reference to what I'm after as far as this system call, as I mentioned in my original post, It was a little bit of code to throw into my fledgling mud, so I could feel as though I had made progress :) If possible, can you look at the additions I made to my mud in the first post, and let me know if they are the most efficient means of doing this?
muchas gracious senors! | Top |
|
Posted by
| Nick Gammon
Australia (23,052 posts) Bio
Forum Administrator |
Date
| Reply #7 on Thu 20 Aug 2009 06:19 AM (UTC) |
Message
| See this post about an excellent book about the STL:
http://www.gammon.com.au/forum/bbshowpost.php?id=3666
However, you may have trouble finding that in Afghanistan. I had to order it from Amazon myself - I couldn't easily find it in Melbourne either. |
- Nick Gammon
www.gammon.com.au, www.mushclient.com | Top |
|
Posted by
| Trask
Australia (23 posts) Bio
|
Date
| Reply #8 on Thu 20 Aug 2009 06:47 AM (UTC) |
Message
| Thanks Nick,
David told me about that book in another thread. Ordering it from Amazon is definately the way to go for me, It'll take quite a while to get to me, it first goes to sydney, then gets routed to us here. As I mentioned to David, I'm reading Bruce Eckel's Thinking in CPP, and plan to order the Josuttis book as a progression.
Cheers! | Top |
|
The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).
To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.
28,160 views.
It is now over 60 days since the last post. This thread is closed.
Refresh page
top