Jump to content
xisto Community

herenvardo

Members
  • Content Count

    11
  • Joined

  • Last visited

About herenvardo

  • Rank
    Newbie [Level 1]
  1. I think this should be easy for someone experienced, but I have never done something similar, so I need a bit of guidance. I have a mini-site under a subdomain that entirelly relies on dynamic URIs. All pages have URIs in the form http://towo.dragon-tech.org/cat/main http://towo.dragon-tech.org/cat/main and so on. The index.php script takes care of retrieving the appropriate content from both the database and some include files, and everything is working fine. Only that these URIs look quite ugly on any visitor's browser, and I want to make them prettier. I have read that I can use RewriteRule on the .htaccess file to make them look like http://towo.dragon-tech.org/esp/news http://towo.dragon-tech.org/eng/main and so on; but my ability with regular expressions is null (the few attempts I have ever made to use regular expressions for anything have devolved into too deep recursions or something that didn't do what I wanted; on most cases both ). Also, I'm a bit worried because the examples I have found on the web use paths relative to the root "/", rather than absolute; but these should only be applied to the subdomain. In summary, I'd like to have URIs converted like this: http://towo.dragon-tech.org/cat/mainlanguagecode/sectionname => http://forums.xisto.com/no_longer_exists/=languagecode&section=sectionname http://towo.dragon-tech.org/cat/mainlanguagecode/sectionname?whatever => http://forums.xisto.com/no_longer_exists/=languagecode&section=sectionname&whatever and I need this to not mess up with URIs in the main domain or other subdomains of the site. Any help will be appreciated. BTW, sorry for the "auto-links", but I don't know how to disable them
  2. Let's see:Price: PHP is better than ASP. Here is no discussion. Free is cheaper than asp, no matter version nor anything.Power: PHP tends to be smarter than ASP. I'm not sure about that, butI've experience in both languages and I've found PHP lets me atac any need by its root and solve the problem quickly and efficiently. With ASP, you have to write very strange code if you attempt to do something complex.Ease: you've been saying that php is easier for those used to C/C++, and ASP is better if you are used to Visual Basic... since C & C++ are far better than ms' basic thing, this is a point for php.I've seen that some say something about Object Orientation... this is what I think: if you actually need Object Orientation, forget ASP and PHP and go Java.The secret of any good technic is to know wich tool applies to each task :)Greetings,Herenvardö
  3. Going deeper: more about types and memory Type conversion (cast) C++ allows us to convert from one type to another very easily. Simply put the type you want your data to become between brackets, before the data, like: (t)exprreturns a value of type 't' which is the conversion of the value given by 'expr'. This will always work when working with atomic types; but with more complex structures the compiler won't be always able to figure out how to perform the conversion. Check your compiler documentation to get more about this.Class constructors and destructors A class constructor is a method in a class that has the same name than the class and returns an object of such class. Since the return type and the method name are exactly the same, it's only typed once, the compiler will recognize the constructor and assume its name and type. Basic constructors (those that have no arguments) are mainly used for imprescindible inicializations. Also, constructors with a single argument are often used by the compiler to perform type conversions. Constructors are also called whenever we use the 'new' operator. A destructor looks almost exactly as a constructor, but it's preceeded by a tilde (~). Destructors are always called when using 'delete', and they must care about 'delete' everything the object kept on memory, to free it. dynamic memory: the old 'C' way From the times of C, there were some functions to manage memory that, due to compatibility reasons, are also available when working on C++. Let's begin with a problem, then i'll solve it using these functions to show you what they can do for your programs. I'll use a simple, old and classic example: we have this structure: typedef struct{char* name;int category; //Supose that we also have some categories enumeration somewhere} client;Now, we need a list of clients. We are told that it may get from empty to 500 elements. Then, we could do: client cl_list[500];yeah... we have a list, it holds 500 elements, even in the case there are no elements to hold. And if, for any case, the limit increases, we'll have to modify the source and recompile the program again...Suposing that the list already has 500 elements, we can do: int siz = 500; //we'll store here the array's sizeclient* cl_list = (client*)malloc(siz*sizeof(client));malloc gets a numeric argument, which is an amount of memory, and returns a pointer to void. The returned pointer points to the start of a region of memory of the asked size, that malloc has reserved for us. We only have to convert the pointer to the proper type, since malloc always uses void*, and we can work with this memory.ok... it's more weird that the previous way, to do the same... but it can get much more weird, by adding something like this: void rem_elem(int i){siz--;for (int j=i;i<siz;i++) //remember that a for without {} is one-line.cl_list[i] = cl_list[i+1];cl_list = (client*)realloc((void*)cl_list, siz*sizeof(client));}void add_elem(client cl){siz++;cl_list = (client*)realloc((void*)cl_list, siz*sizeof(client));cl_list[siz-1] = cl;}realloc is more weird than malloc, but it's also more useful. The parameter before the memory size is a pointer to a dynamic set of data (we've to make it void*). realloc is used to resize (and move when needed) dynamic data allocated with malloc. It also cares to copy all the old data to the new allocation, but note that if we are reducing the size, realloc will not copy what gets out; this is the reason we've 'upped' all elements from the removed one in rem_elem().And the last one is a question of stability and etics: simply remember to make a call like free(cl_list);once you end using this dynamically stored data. If you don't free memory you allocate, the system will believe that this memory is still being used, and will be unavailable until the system resets.Dynamic memory: the C++ new approach Since c++, we can do cl_list = new client[siz]; //instead of mallocdelete cl_list; //instead of freethe 'new' operator makes a lot of work. First of all, it saves us the pointer conversions and all size calculations. It also cares to call constructors when new objects are created, and allows us to provide arguments for the constructors.The worst part is that we haven't anything for realloc. we can, even so, use the realloc function; or we can make it the weird way, using only the C++ operators: aux = cl_list;cl_list = new client[siz];for (int i=0; i<siz; i++) cl_list[i]=aux[i];delete aux;Nonetheless, this code gets near to the one realloc actually uses, with some minor diferences.I feel deceived I'll come soon with the templates chapter, and I'll have to post some versions of the Tree implementation. If you wanna get profit of these tutorials, try to solve the exercise by yourself, before looking at the resolution. If you have come late, and the solution is already published, then stop reading here, look at the post about recursivity and OOP, and try to solve the exercise proposed at the end: figure out which features will make the tree more usable and implement them. PM me or post your proposals... don't be shy, 'cos almost everything is doable in C++ See you soon, Herenvardö
  4. I'm writting a large class hierarchy and want to put it on a dll. What must I do to be able to use the class definitions in the dll from a visual basic application?. I'm making the dll from Borland C++ Builder 6 Enterprise.Thanks,Herenvardö
  5. I'm experienced on HTML and php, but it's my first attempt to work with databases. I've made a small test.php file to try out my code before publishing it and find some problems. The calls to mysql_connect() and mysql_select_db() work ok, but i get this message when trying to output a small table: Warning: mysql_numrows(): supplied argument is not a valid MySQL result resource in /home/gdt/public_html/test.php on line 26 The relevant part of my code is as follows: 25: $ps_res = mysql_query("SELECT * FROM 'proj_status'");26: $ps_num = mysql_numrows($ps_res);I need the numrows value to have a break condition in the loop that outputs the data. Also, I've tried to avoid the numrows call, by putting a literal number of rows, taken by directly counting the rows from phpmyadmin: I avoided the error message, but the browser hangs when I try to run the script. Can somebody help me?? Thanks Herenvardo
  6. Depending on your needs, you might try joynic.com. You might find a better service (in fact, it would be very easy), but not a cheaper one because they offer domains for free. The only bad thing is that you cannot get the classical .com, .net or .org domains, you get your-domain.**.ttIn my case it was good enough: here at Catalunya (a region in Spain with our own government and language) we've been figthing to be able to have .cat domains... while this war goes on (and it seems it'll take very long), I was able to get a .ca.tt, which gets near and it's free. Even the ones at joynic put the 'ca' thinking on Canada, my visitors perfectly see it as a 'home-made' alternative for .cat :DHoping be useful,Herenvardö
  7. I've been using Google's e-mail service, gmail, and found it great. I don't want to make a post saying only this, so I'll make a comparation of its features against its competitor's ones. Space: MSN Hotmail, in its paid version, provides 2GB of storage. Gmail currently gives you 2,5GB. The fact is that this space is continuosly increasing, and you may check it at gmail's homepage. So, it is not only the biggest e-mail, it's also the only one that grows. Comparing to free services, the biggest one I've found is at spymac.com, which is 1GB. In this aspect, gmail beats competence. Pricings: Gmail is free. Such a price, by definition, is unbeatable. There are a lot of free e-mail services, but they can only tie, never win, to gmail, since they offer the same price: free. So, in pricing, gmail is tied with many sites at top. Advertising: I'll avoid comparing with paid systems, because they do not need advertising, only to free services. Hotmail's free e-mail main window takes about a half of the screen, since the other half is invaded by banners. Other systems are a bit discrete, but there is always at least a banner ad. In a gmail account, when you open a message it is scanned automatically for keywords; these keywords are used to select a set of text ads that are clearly separated in a column at the right, as done in Google's search results. No banners at all, and all ads are relevant, so Gmail beats again. Language: Currently, gmail is available at 29 different languages, and they are working on more. In most e-mail services, you have only english available. There are many that also allow the local language of the providers, so you'll normally have one or two languages to choose from. Another point for gmail. POP access: Of course, gmail provides you POP access, to download your mail through the software you prefer. But gmail goes beyond allowing, it helps you to configure your e-mail client step by step and even provides a tool that does it for you on the most used clients: Outlook (& Express), Eudora, etc. The nearest competition on this feature is the Outlook-Hotmail combo: since they are both from Microsoft, Outlook is able to access your Hotmail account giving only the username and password. Even so, gmail's tools are wider and better. Once again, gmail clearly beats. HTML mail: well, they are not the best here. Even gmail gives many options for html formatting, such as font, color & style, it's beaten by those services that allow you to write your own code. So, in this aspect it's good but not the best. Maybe only half point here? Anyhow, remember that gmail is still a beta, and it won't surprise me if in some weeks they improve that. Xtras: Gmail notifier allows you to monitor your mail from the system tray. Picassa makes managing and mailing image files a children game; you may convert among formats, resize to save space and bandwith, and many other features. So, features speak for themselves: gmail rocks! Also, I'd like to make some comments: Google's philosophy is to beat competence by making its products widely better. Even if they achieve this or not, there is no doubt they do their best. That forces the competition to improve a lot to keep the bussines going on, and in a medium and long term, it's a great benefit for users. Also, remember that gmail is still in a beta stage, which means that Google still do not consider it enough. Hoping be useful, Herenvardo PS: I've a lot of invitations for gmail. If you need an account, PM me telling why do you need it and I might send you one.
  8. The best place to start I've been moving through a lot of different hosting services for the last few years, so I can make a review based on comparations. Anyhow, everything I might say here is only a point of view. Maybe I'm mistaken, even I don't feel so. There is my opinion: - Hidden fees: Many 'free' services hide fees or otherwise try to get moeny directly from you. The most obvious case was a host that allowed me to apply for the service by putting their banner in top on my home page. After exactly one month of applying, I got an e-mail telling that the free service was being suspended due to 'bussines reasons', and giving me an 'offer' for the paid service (50 megs of storage, 250megs/month bandwidth at 17$/month, plus keeping the banner, no way server side scripting allowed). I replied that I was NOT interested, and in few than 24h I got a new e-mail asking for my credit card details... I had to threaten them, explaining that those e-mails, still stored on the server, were a proof of spam, to get them stop asking for my money. I visited their homepage and was able to create a new free account ( wasn't that service suspended??). I put a 'site under construction' index.html file to make it reallistic, and waited... Once again, after 30 days, I got the e-mail telling me that the free service was being suspended and so on (note: the offer was different: it was 20mb storage and 500mb bandwidth for the same pricing). I finnished it off by telling them that legal actions had been started... I've never got notice from them again. This is a clear example of what are hidden fees. Actually, this is the more blatant one I've known. There are too many services that use tricks and cheating like that to get your money. Until the moment, I've seen NO indices of such cheating on Xisto, and it doesn't seem I'm gonna see them. Overselling: That's a known practice to sell more than the server can provide. The host sells packages of 500mb, for example, and then, knowing that the clients will use an average of 200mb or so, they sell so much packages that they can only provide 250-300mb per client. I still can remember a case of this: I was granted a 50mb account; I had only used about 4-5mb and, trying to upload a new file (it was a small gif to be usset as list-bullet, smaller than 1kb) I got a strange error message telling that there was no space enough on the hard drive... Here at Xisto, I had an issue some days ago: cPanel reported that I was using 58/20mb of storage, and I even got a 'Criticall notice' from the system warning that; but even so I was able to keep on uploading my files. Now the issue is fixed, and I'm sure I'll be able to use my 20mb if I require them. Pricing: Nonetheless it is stated in the site, there is nothing free, and this applies to hosting. The fact is that here, at Xisto, we are provided an alternative payment method: we apport our knowledge and experience to these forums, and we are given hosting in exchange. Somebody may find it cheap, others will find it expensive, but it is a truth that there is no money involved in the deal. For those who aren't able to pay with moeny, Xisto means an alternative way to get hosting. Don't forget that you can also put the banner to avoid the need of keeping active, so you have two different options for financing your hosting without spending your money. Other services I've tried ask you to put a banner and, in somecases, the code they force you to use for the banner does weird things, from opening annoying pop-ups to infecting your visitors with spyware. When this is done, your page shows a lot more ads, so you are paying a higher price (even not in money, it's a price and it has a real value) than agreed with the company for your hosting. I've not tried the banner, because I'm glad to contribute in a comunity like this, but it doesn't seem to do strange things. So, in conclusion, I can say that Xisto is the best and most professional free web hosting service I've ever tried. I'm very glad of the service and attention provided, and cannot understand how people make posts like rodneylay's one. Going further, such a post is an unjustified attack, and here at Spain legal actions could be applicable in response for such an attack. He has not only bypassed the TOS, but he has said, summarizing, that Xisto doesn't comply with and agreement. This is a proof-less accusation for fraud. A proof-less accusation is known in my country as 'difamation' and it is considered a crime by our laws. I don't pretend to impulse you to start legal actions, nor anything like that, but I want rodneylay know how grave is his action. Hoping be useful, Herenvardö
  9. Beyond the basics: OOP and recursivity through an example I will first introduce the basics of recursivity, and then I’ll use a example (a binary integer tree implementation) to give the basics of OOP in C++ and show the potential of recursivity. Recursivity: This goes beyond C/C++: recursivity is a very powerful (but dangerous) tool in programming, no matter the language you’re using. The same way a function can call other functions from its body, it can also call itself; that’s recursivity. But if a function call itself, then this new call will also call the same function, and will go on calling itself indefinitely until we stop it. Almost everywhere where I’ve read about this topic, I’ve seen it explained through the same example, so I’ll keep the tradition. If you have some maths knowledge and know what a factorial is, you may skip this intro. The factorial of an integer number is defined as the product of all positive integers less or equal to the given number, so the factorial of 4 (represented as 4! in maths) would be 4*3*2*1 = 24, 7! would be 7*6*5*4*3*2*1= 5040 and so on. Let’s look closer to that example: 7! could also be 7*(6*5*4*3*2*1), so it’s actually 7*6!. Given an integer number x > 0, we can assure that x! = x*(x-1)!, so to calculate a factorial we have to calculate a factorial: this is recursivity. It’s also required to know that 0! is defined to be 1, so 1!=1*(1-1)!=1*0!=1*1=1, which is what we should expect from the first definition. Now, we are going to implement it. Since factorial is only defined for non-negative integers, it seems that the appropriate type for the argument will be unsigned int. For the return type, we might also use int, but I prefer to return a long so we can handle bigger values: an int gets overflowed if we try to get 9! or higher. The long wont overflow until 12!... hmm that’s a bit short… Maybe better if we sacrifice precision to get more range: I’ll use unsigned double as the return type, actually factorials are huge! So the function would be something like that: unsigned double factorial(unsigned int n) {[tab][/tab]return n*factorial(n-1);}Wait… it can’t be so easy… something is wrong here, can you find the problem? As I said above, the function will call itself infinite* times unless we stop it, and we’re doing nothing to stop it. *When computing, infinite does not exist; in this case, the function would call it until it overwhelms the system resources, then it’ll crash the system. But there is still another problem: whenever we make the call factorial(0), the function will attempt to do 0*factorial(0-1); but 0-1 is not storable as unsigned. Anyhow, we have a special definition for 0!: it’s 1. So, if we apply it on our code, we get: unsigned double factorial(unsigned int n) {[tab][/tab]if (n==0){ return 1;[tab][/tab]} else { return n*factorial(n-1);[tab][/tab]}}Ok, that’s better. Let’s see how does it works for a easy case: 4!factorial(4) (call #0) calls factorial(3) (call #1), factorial(3) calls factorial(2) (call #2), factorial(2) calls factorial(1) (call #3), factorial(1) calls factorial(0) (call #4), call #4 fulfils the ‘if’ condition, so it returns 1 and no further calls are made. Then call #3 has the value it needs so it can finish: it returns 1*1 = 1, Now call #2 may continue, and it returns 2*1 = 2, which is used in call #1 to return 3*2 = 6. With this value, call #0 can return 4*6 = 24, which is, of course, 4!. You might have noticed that each call keeps its own n. This is an important fact about recursivity: no matter if you call the same function or another one, each call has it’s own set of arguments and local variables. When we refer to n in the body of the function, we are referring to the n of the current call. Now, after this brief introduction to recursions, we can begin with the main topic of this post: the binary tree example. Tree: a recursive data type Trees are a set of structures that are a bit abstract and, maybe, difficult to understand, but they are very useful. A tree is made out of nodes; each node has exactly one parent node and may have zero, one or more child nodes. The only exception to this rule is the root, which has no parent. The nodes that have no children are called leafs. A great example of tree is a file system: there is a root and a lot of nodes (dirs and files). Files and empty directories would be leafs of these trees. The case of our example will be simpler. In fact, this is one of the simplest trees. It won’t hold dirs and files, but only integers. Also, it’s binary, which means that each node may have, at most, two children. Look at this example: 0 / \ 1 4 /\ / 2 3 5 In this case, the root is 0, and it has two children: 1 and 4. 1 has also two children: 2 and 3; 4 has only one: 5. 2, 3 and 5 have no children, so they are the leafs. Of course, a tree may hold repeated values, I’ve avoided them in the above example to make it clearer. A first way to make it, we can create a struct like this: struct tree_node {[tab][/tab]int value;[tab][/tab]tree_node * left_child;[tab][/tab]tree_node * right_child;}In fact, the strictly needed data is already in this struct, and we’ll even use it in the final version. But, if all data is already here, why should we complicate it more? Do we need something that is not data? Yes, we need functionality, and this is precisely what make classes different from structures: they allow us to implement functionality.Class declaration and definition syntax: To declare a class (that is, to make the compiler know that this class exists), we should use: class class_name;To define a class, we have to complicate it a bit: class class_name:base_class1, base_class2,... {[tab][/tab]private: //private members are defined here[tab][/tab]protected: //protected members are defined here[tab][/tab]public: //public members are defined here};Ok, let’s explain it. Base classes are used to inherit both data and functionality from a previously defined class. We won’t use inheritance in this example, so we’ll use something like this: class binIntTree {Note that if there are no base classes, the colon ‘:’ has to be removed.private, protected and public are C++ keywords that allow us to determine accessibility for each members. Private members will only be accessible from inside the class they are declared in; if we try to access them from elsewhere, the compiler will complain at us telling that such variable, method, function, etc does not exist. This allows us to protect the critical data from misuse, but also forces us to decide which data is critical. Public members are available from anywhere where the class is available. Protected members are a mid-point; they cannot be accessed from outside, but the subclasses may access them. Since we’re not going to use inheritance in this example, we may omit this section. Members of classes may be variables and/or functions, and we declare them exactly as usual, but inside the class. The shape of the tree Now that we now where and how to put our class members, the next step is to decide what do we put as class members. - A tree has to have a root. We may declare it as a tree_node, as we defined above. Since this node also has the references to the children, we do not need to define them further - It would be interesting to be able to calculate the dept of the tree. That means the maximum number of steps we can make from the root to any leaf, moving from a node to one of its children on each step. So, a tree that is only the root would have a dept of zero. - Another interesting value that can be taken from a tree is it’s size, defined as the number of nodes that form the tree. Even we could make the class more complex and functional; I think that this will be illustrative enough. Here is a look at the class, but functions are not yet defined, only declared: class binIntTree {[tab][/tab]private: tree_node * root; //These functions will be explained later: static int node_dept(tree_node* n); static int node_size(tree_node* n);[tab][/tab]public: int dept(); int size();};Note that the dept and size methods take no parameters. You may ask how will they be able to find the tree they have to work with. And if you may ask, I may answer . There is a keyword in C++, ‘this’, that is a pointer to the object from which we’ve called the function. The same way we used a dot to access members of structs, we do the same with classes; so if we do myTree.dept();the this pointer will point to myTree while inside this call.Incise: the -> operator. It’s very useful in C++ to require a member of something that we access trough a pointer. Instead of doing (*myPointer).member;, C++ provides us an alternate and clearer way to do that: myPointer->member;. These two notations are not exactly equivalent: the first one would create a copy of the item pointed and then access the member of the copy, while the -> will make the compiler apply a lot of pointer arithmetic to access directly the member of the object pointed. When using ‘this’ we should use this new operator, because an expression like *this leads to misbehaving code. Static members You might have noticed that there are two functions that use the static keyword. A function or variable declared as static is part of the class, but not of its objects. We may access it using the syntax class_name.static_member; but not through an object of the class. We can call them directly (without class_name.) if we do so from inside the class. In contrast to non-static members, there is only one copy or instance of them, instead of one for each object. Since these functions are not part of any object, the ‘this’ keyword cannot be used there: there is no object to point. This is the reason why these two functions take a parameter their public counterparts don’t. Why are these two functions static? They are going to work in a recursive way, so at each call they’ll need different parameters: they won’t be always the original object. Since I wanted to make them private, they had to be inside the class, but are not methods for the object, so they are static. Calculating the tree’s size The function size() will be very simple: int size(){[tab][/tab]return node_size(this->root);}Obviously, the work will be done in the node_size function. Let’s take a close look to what it must do. The size of a node is the addition of the size of each children plus one, to count also the current node. But we have to care about null child pointers: if a node has only one or no children, then we cannot even try to access to a child it has not: we would get an error. So, the function is something like this: int node_size(tree_node * n) {[tab][/tab]if (n->left_child == null) { if (n->right_child == null) { [tab][/tab] //Both children are null: it’s a leaf. [tab][/tab] return 1; } else { [tab][/tab] //Only right child [tab][/tab] return node_size(n->right_child) + 1; }[tab][/tab]} else { if (n->right_child == null) { [tab][/tab] //Only left child [tab][/tab] return node_size(n->left_child) + 1; } else { [tab][/tab] //Both children exist [tab][/tab] return 1 + node_size(n->left_child) + node_size(n->right_child); }[tab][/tab]}} Getting the tree’s deptOnce again, the public function only calls the recursive private function: int dept(){[tab][/tab]return node_dept(this->root);}Before entering on details of the node_dept function, I want to comment something related: we’ll need some way to get the maximum between two values. I’m sure that libraries include some function to do that, but in any case there is a function that can do the job: inline int max(int a, int b) {[tab][/tab]return (a>=b)?a:b;}Now, we can go on with deeps. The function is very similar to node_size, in fact it has the same structure. The first difference is that the simple case (leaf) has to return 0, and not 1. In the cases of only one child, it’s completely parallel; and in the case of both children, we take the maximum of their dept instead of adding them. So, here’s the function: int node_dept(tree_node * n) {[tab][/tab]if (n->left_child == null) { if (n->right_child == null) { [tab][/tab] //Both children are null: it’s a leaf. [tab][/tab] return 1; } else { [tab][/tab] //Only right child [tab][/tab] return node_dept(n->right_child) + 1; }[tab][/tab]} else { if (n->right_child == null) { [tab][/tab] //Only left child [tab][/tab] return node_dept(n->left_child) + 1; } else { [tab][/tab] //Both children exist [tab][/tab] return 1+max(node_dept(n->left_child), node_dept(n->right_child)); }[tab][/tab]}} So, putting all togetherYou may mount the class replacing the declarations in the ‘skeleton’ provided above by the definitions that we’ve made, for all four functions. If you want to use the max() function provided, you should also add it (if you put it inside the class, remember to make it static!). What we have now is a class that works: unless I’ve mistyped something, you should be able to compile it, create binIntTree variables and call their methods. Even so, since we’re not able to add or remove nothing from the Tree, it’s completely useless. As an exercise, I suggest you to try to add something to it. I’ll give you a more usable version of the class in short, but I’m almost sure that you’ll understand it better if you try to improve it by yourselves before viewing the final version (ok, is not final. When I publish the tutorial about class templates, we’ll make a n-ary ‘any-type’ tree). See you soon.
  10. microscopic^earthling: I'm almost sure that I'd get warned if I made a post like yours; even I try to take it simply as a joke, I feel a bit deceived seeing and admin laughing at users' issues. Killtacular: I've the same problem. When I accessed cpanel for the first time, it reported 55/20 mb I assumed that it was counting preinstalled scripts and all this stuff, so I didn't bothered; but this morning I received this mail: It has worried me a bit. I've just got the hosting, and I'm worried to lose it for such an issue. I hope that admins will take this problem seriously; even not with cash, we are somehow paying for the hosting service.
  11. First of all, I want to congratulate GM-University for that clear, simple approach to the C/C++ basics. I don't want to override your tutorial, but to expand it to not-so-basic subjects about this powerful language. Beyond the basics More about data types We already know that variables, functions and arguments have types. We also know the types char, int, float, double and void. But what makes of C and C++ powerful languages is that they are extensible, this is, we can extend the data types to fit our needs. The basic types we already know are part of the ones called ‘atomic types’, since these are the atoms, or minimal parts, of which other types can be made. But the set of atomic data types can’t be complete without speaking about the basic modifiers. A modifier is a keyword that is put just before the type when declaring something, and gives additional control over how and/or where will it be stored on memory and/or managed by the system. Some of the modifiers are considered ‘default’, so they are assumed by the compiler unless a contradictory modifier is given. short (default): This modifier indicates that the value will use the minimum space the compiler considers needed for such types. It has the advantage to save memory, but the disadvantage of having a reduced range of possible values. Example: a short int needs only 16 bits (2 bytes) in memory, but it would overflow if we try to store the value 100000 on it. long: opposite of short, it means that the value will use a larger amount of space on memory, so it can hold more values. Example: a long int could store the value 100000 on it, and even the value 1000000000, but it requires 32 bits. Note: long char is not defined in the C/C++ standards, but some compilers allow it for Unicode chars instead of ASCII. Another note: long float is strictly equivalent to double, and some compilers also allow long double for enhanced precision. signed (default): This tells that the value can hold both negative and positive values. This doesn’t affect the amount of possible values for the variable, but modifies which are these values. unsigned: Obviously, this means that no negatives will be used, so our range for non-negatives gets bigger. So now, our list of four data types has now increased to (in theory) 16: char = signed short char, unsigned (short) char, (signed) long char, unsigned long char, (signed) (short) int, unsigned (short) int, (signed) long int, unsigned long int, and so on with float and double. Of course, it has no sense something like unsigned void, or any other modifier with void, even some compilers allow it and simply treat it as a ‘normal’ void. In addition, in the same way modifiers have defaults, types also have a default: int. If there’s a modifier but no type, since the compiler knows that after all modifiers there should be a type, it will assume that this type is int; so these lines int x; short x; signed x; are completely equivalent. This omission is used so much when using long int’s that too many people believes that long is another type. At last, note that a variable cannot be signed and unsigned, nor short and long, at the same time. Trying to do that may either cause a compilation error or an unexpected behaviour on the program. With this, we have finished the atomic types. Pointers Pointers are one of the darkest parts of C/C++, many people has a lot of trouble learning them, but they are the source of most of the power of this language. A pointer is a variable by itself, but the value it holds is the address in memory of something else. We can do the basic actions (assign, addition, etc) with a pointer, and we can also operate with the value it points to. For example: int x; //x is an integerint* p; //p is a pointer to an integerp = &x; //p is assigned the address of xp = p + 1; //p points to the next integer it was pointing to.*p = *p + 1; //the value pointed by p increases by 1. p still points to this value.x = *p; //x is assigned the value pointed by p.int** q; //q points to a pointer that points to an int.int ************** r; /* r points to a pointer that points to another pointer and so on, until the last (14th) one points to an int. Personally, I thing that this case will have no use beyond tutorials, but it’s still an interesting example.*/ Operators related to pointers* pointer declaration: this is used to declare pointers (see details below) * un-reference: it can be read as ‘the variable pointed by’ & reference, address of: it returns the address in memory of a variable or something else. Pointers to things that are not variables will be commented, but not explained deeply; they can be very useful, but are beyond the aims of this document. Usual operators: =, +, -, etc: these operators work almost equal that when using ‘non-pointer’ variables. The details will be commented later. Pointer declaration A pointer must be of a type, such as pointer to int, pointer to char, pointer to unsigned long double, and so on. It can also point a complex type, which will be explained later, or to void, so it’ll be simply an address. Conversion among pointer types can be made the same way conversions among basic and/or complex types are made. To declare a pointer to a given type, the syntax is almost the same that declaring a variable of that type, but a pointer-declaration operator is put between the type and the name: int* pint;long double *pld;void* pv;Some compilers treat the * as part of the type, so we can declare multiple pointers like: int* p1, p2, p3;In other compilers, where the * is taken as part of the name, the line above would declare a pointer p1 and the int’s p2 and p3, we should use this: int *p1, *p2, *p3;If you’re not sure how your compiler will take it, the most safe option is to declare the pointers independently. Personally, I do it this way for being the most stable.Pointer arithmetic Pointers work normally with the assignment operator (=) and with comparison ones (==, !=, <, <=, >, >=). Operators + and – take in account the type attached to the pointer. It’s better explained through an example: int x; //this int is only used to have some value to put on the pointerint * p = &x; //p is pointing to xp = p + 2; //this is the important line in this exampleAfter running this code, p will point 4 bytes beyond x. The 2 is not added directly to the pointer value. The program adds to the pointer 2 times the size of an int. If the example had used float instead of int, p would be pointing 8 bytes beyond the position of x, cause a float uses 4 bytes.In the case of a void pointer, the ‘size’ that will be applied is not so clearly defined, and it will usually be the minimum addressable by the system. In the case of pointers to a pointer, it’ll also depend on the system, it’ll be the size of an address in that system. Pointer applications: arrays To avoid entering complex matters before its time, we’ll suppose in this section that we make use of memory without any need of management (Author’s note: NEVER assume such a thing when making a real program, unless it’s intended to crash). Let’s assume that we need a set of values of the same type. We could use this code: int a0, a1, a2, a3, a4, a5, a6, a7, a8, a9…It’s doable, but a bit ugly (Author’s note: it’s not ‘a bit ugly’, it’s HORRIBLE!!). It gets even worse when we try to do something with each value: something(a1);something(a2);something(a3);…So, imagine for a moment that all these values are stored together and in order in the memory. Then we can use a pointer to the first element: int* a = &a0;The code becomes a lot simpler: for (int i = 0, i < 10; i++)something (a + i); //remember the pointer arithmeticIt may not seem too much with only 10 elements, but when the sequence becomes larger, this code becomes clearly better.Nonetheless, this is a so frequent action that C/C++ provide an specialized notation to do this: int a[10]; /*declares the sequence of 10 int’s, indexed from 0 to 9. This declaration makes the compiler solve the memory management, so it’s very recommended.*/a is strictly equivalent to a + i. Even declaring the array (these sequences are called arrays) with this new form, it is still a pointer and can be treated so later in the code.It’s very important to remember that the indexes begin on zero: trying to get a[10] would give an “Array out of bounds” error. This happens because the first element is at the address a, so it’s a + 0. Going further, as a pointer can point to a pointer, we can make an array of pointers, or even an array of arrays; remember that arrays are pointers. We can also have an array of arrays of arrays of doubles, for example. These are called multidimensional arrays. 2D arrays are also called tables, and lines like the following are very frequent: int [31][12] daily_data; Care that 3D and further arrays are a bit dangerous. Something like this: double [100][100][100][100] x; is correct in theory, but it would use more than 760 mb of memory… my machine does not have so much , and if I had it, I’d use it for a more interesting thing than holding a 4D array of real numbers .Arrays application: strings If you have previously used another programming language, like Basic or Pascal, you might have noticed that there’s no ‘string’ type in C/C++. This happens because the machine cannot work directly with strings. Other languages add a lot of code to the program when compiling to make strings work, but C/C++ is intended to provide control instead of ease of use. It’s possible to manage strings in C/C++, but we cannot expect the compiler make all the work for us. When we use a literal string value, that is, a text between double quotes “”, the compiler makes room on memory to store it, one character after the other, and a NULL char marking the end (the null char is the ASCII code 0, and it can be scaped ‘\0’). Then, a pointer to the beginning of the string is returned, the same way 5 is returned if we do 2+3. So, a string in C/C++ is no more than a pointer to char. We have to care that these pointers do not hold the string, but point to it. Operators will treat them as the pointers they are: str1 == str2 would return true only if str1 and str2 point to the same string, but it might seem that it compares if the strings are equal. To solve this, a lot of functions are available in the standard library ready to work on strings. As example, I include here a possible implementation of one of these functions: int strcom(char * str1, char * str2) {// returns -1 if str1 is previous (alphabetically) to str2, 1 if it’s later and 0 if they are the same. This version (the simplest one) treats upper case as previous to any lower case.[tab][/tab]if (*str1 < *str2) return -1;[tab][/tab]if (*str1 > *str2) return 1;[tab][/tab]if (*str1 == *str2) { if (*str1 == ‘\0’) [tab][/tab]return 0; else [tab][/tab]return strcom(str1 + 1, str2 + 1);[tab][/tab]}} That works comparing char by char the strings. Only if the first char is the same, we need to check the second one, and so on, so we recursively call the function without the first char.The standard library includes a lot of interesting functions to work with strings, and almost every compiler includes non-standard tools that may be very useful; so I suggest you to take a look on your compiler’s documentation. Some products even provide a class (a user-made type) to work with strings, some of them also define operators. Discrete data: enumerations There are some data that are intended to hold values from a limited set of values. Example: we could use an integer, using values from 0 to 6 or from 1 to 7 to define a weekday: Monday, Tuesday, etc. We can use constants or even variables, with the names of weekdays that hold the value that should be used to represent each day, and we’d be able to use these names instead of numbers. Look at this code: int mon=1, tue=2, wed=3, thu=4, fri=5, sat=6, sun=0; int weekday = wed; This code works, and it can perfectly be used. Even, if you use constants (not available in classic C, only in C++), you avoid the risk of having one of the initial variables assigned a new value. But the language provides a better form to do that: //in c++ enum weekday {mon, tue, wed, thu, fri, sat, sun}; //in classic c typedef enum { mon, tue, wed, thu, fri, sat, sun} weekday; Then we have a new data type, named weekday, which can hold any of the values of the list, so we can do this: weekday x = mon; If we use the c++ declaration of the enum in c, then we have to declare the variable this way: enum weekday x = mon; So using the typedef saves us of having to use the enum keyword at each declaration. In c++, type-definition is automatic, but the old explicit notation is also valid for compatibility.The enums are very simple, so I’ll finish this section with another example: Let’s assume that we are programming a table game called parchis (it was widely played in Spain some years ago, I don’t know if it exists outside, and have not found a translation of its name anywhere), where each player has to move its pieces from its own start to the centre of the table, making a whole wheel and entering to centre through the path of its own colour. To identify each player, each start zone and each path to the centre, we could use the colours, defining them this way: enum colour {green=0, blue=1, red=2, yellow=3};char*[4] play_names;play_names[green] = “john”;play_names[red] = “peter”; And so on. Note that, since enums are actually integers, they can be used as arrays’ indexes. Also note that you can force the numeric values that will be used for each name; I strongly encourage to force them begin from zero if they’re going to be used as index, to avoid “array out of bounds” errors.Complex data: structures This can be briefly explained almost completely through an example, so I’ll do this way. Let’s assume that we have to manage data about up to 100 books. We need to store title, id and author. In Spain, each published book is given a unique ISBN code (once again, I don’t know if this also happens outside), which makes the job of id. We could do: char * titles[100];char * authors[100];char * ISBNs[100]; Being honest, there is no need, in this case, to get more complications: this way the job can be done efficiently enough; but there is a more clear way to do that: struct book {[tab][/tab]char * title;[tab][/tab]char * author;[tab][/tab]char * ISBN;}book library [100]; The idea is that we have 100 books, and each of them has its own title, author and ISBN. Then we can use this syntax to access each field: library [x].title = “The Lord of the Rings – The Return of the King”;library [x].author = “John Ronald Reuel Tolkien”; In a more general form, the syntax would be object.field. We can use this syntax to write in the fields, as in the example above, or to read them: char * My_author = library[x].author;if library[x].author = library[x].title then auto_bio = true; and so on. Note that the [x] is used because library is an array, it has nothing to do with structs. We can make arrays of structs, pointers to structs, fields of structs that are pointers or arrays, and any combination of these tools that makes sense to our needs. If something can be a variable, it can also be a field of a struct, so we can make something like this: struct library {[tab][/tab]book books [100];[tab][/tab]char * address;[tab][/tab]char * manager;} And then work with a big set of libraries: library lib_set[20];lib_set[11].books[73].title = “C++ tutorial: Beyond the basics”; As the structure gets more complex, syntax also does, but it works exactly the same. lib_set is an array, we take the 12th element (indexed as 11, remember!); then, since this element is an struct, we access it member books. That member is also an array of structs, so we select the element indexed as 73 and we take a field of it: title.To finish, I’d like to comment that structs are stored in memory in a compact, ordered way, so we can replace the object.member syntax by some pointer-arithmetic malabarisms. Anyhow, I prefer let the compiler do these insane tricks for me, so I use the habitual syntax. Also, care that this examples are C++. If you’re working on C, you should use typedef’s like we’ve done in enums. Object Oriented Programming: a first approach As many of you should know, C++ is an evolution from C. But it isn’t only the avoiding of typedef’s and the possibility to use constants. The great difference about these languages is Object Oriented Programming (OOP). In C++ we can create classes. A class is something like structs, but much more powerful and flexible. A class can contain not only data fields, but also functions, which are called methods. For example, we could create a class for Strings and put in it all these functions included in the libraries, as strcom. Then, we could do things like: strMyString.strcom(str2);strMyString.upperCase(); This makes C++ to approach natural language: the same way we are used to structures SUBJECT + VERB + COMPLEMENTS, now we have a syntax like subject.verb(complements).Beyond this syntax evolution, there are three characteristics that define OOP. Encapsulation Part of the members of a class may be needed only internally. For example, in the String class, we need a char array to be able to store the string, but there is no need, when using the class, to directly access the array: we’ll do it through the methods that do the required work. Also, if we make strange actions upon such data, we could get in trouble. For example, some versions of the string class use a variable to hold the length of a string, and each method able to modify this length also takes care to refresh it. If we, externally, modify the char array, the length won’t be updated, and it is a problem. To solve this, some parts of a class may be private, which means that they are only accessible from inside the class. This is called encapsulation. Hierarchy and Inheritance Let’s suppose that we need a car class and a cycle class. If we try to make them separately, it’s sure that we are going to have a lot of duplicated code, because both classes will have an engine, wheels, and many other common members. If we take a deeper look, we can summarize these similarities in the fact that both cars and cycles are vehicles. Then, it’d be interesting if we could create a generic class called vehicle, containing all common members for vehicles, and afterwards create the car and cycle classes, taking all these elements from vehicle and adding or redefining everything needed. And we can do that in C++ (it’s obvious: otherwise, why would I have explained that?). This is called inheritance. We would say that car inherits from vehicle; and the same for cycle. Going further, we could create the class vehicle, and then inherit from it the classes land_vehicle, water_vehicle, air_vehicle and even space_vehicle. Afterwards, we would inherit car and cycle from land_vehicle. We could also create ship inheriting from water_vehicle, plane from air_vehicle and spaceship from space_vehicle. And now comes the funniest part: which class would you inherit to create hovercraft? The first impression is that it is both a land and a water vehicle; but it’s correct that a class inherits from more than one parent class? Being honest, there are too few languages that allow multiple inheritances… and yes, C++ is one of these privileged. So we could perfectly inherit our hovercraft from both land_vehicle and water_vehicle. There may be some issues because the class vehicle would be inherited twice, once through land_vehicle and once again from water_vehicle, and it may cause the compiler to get confused if we try to work with the methods of vehicle directly. But, beyond the issues of inheriting the same class more than once, multiple inheritance is a very powerful tool. At last, I’d like to comment that the set of classes and inheritance relationships among them is called class hierarchy. Polymorphism Ok. Now I have a lot of cars, cycles, ships and even some hovercrafts and spaceships. I want to make money renting them; can I group all of them in an array? The issue is that they are of different types. Wait, aren’t they all vehicles? Then, simply put them all in a vehicle array. It’s so simple. I’ll explain it better: once we declare that car inherits from land_vehicle, the compiler knows that cars are a kind of land vehicles, so we can assign a car object to a land_vehicle variable. And this extends through all the hierarchy. There is no error in assigning a bat-mobile in a vehicle variable (assuming that bat-mobile is a car object). The only issue is that when in a vehicle variable, the object will only have the vehicle’s methods, because the compiler doesn’t know, when compiling, if this variable will hold a car, a ship or something else. This is called polymorphism, from the greek poly (many) and morphos (form), and means than an object can take many forms: the car can take the form of car, land_vehicle, or vehicle. To finish with this subject, it’s important to know that most class libraries have an Object class, from which all other class inherit directly or indirectly, so an Object variable can hold any object, no matter which kind of object it is. Coming soon Object Oriented Programming on C++. Everything you need to know. Advanced OOP on C++: Templates and operator overload. Advanced aspects on C/C++: Dynamic memory, programming techniques and tips.
  12. There is a way to do what you want with a bit of scripting, assuming you don't need too great security features. I'll assume some points before starting explanation: - You should already have a system on your site to track user identification: that is, you need a working 'login' box. - Even it can also be done using database technologies, i'll give you the easiest way to implement it. - I'll supose that your site has a server-side scripting technologie such as PHP, ASP or so. I'll also supose that you know the basics about each of them. Most server side scripting technologies feature file-in/out methods. We may use this methods and some handmade data files to avoid use of databases in simple aplications. The simplest way to implement a points system is to create a folder, named something like 'users' and put a ***.dat or ***.points (or something like that) file for each user do you have, where *** is the user-name/login-name/id or even the email address. Once done that, you'll need to do the following: - Write a function new_user(username) that creates a username.dat file with '0' as it's only content. - Write a function get_points(username) that reads the file username.dat and returns its content. - Write a function set_points(username, points) that sets the content of username.dat to 'points'. Once you have these functions, you have a 'kernel' for your point system. Then you need a interface, that depends mainly on the use and administration you'll gona apply to this system. For example, you may create a form called 'grant points' that, in adition to login data (to ensure that user is allowed to grant points) gets a username and an amount of points. Let's assume this example: <form name='addpointfrm' action='grantpoints.php'>Admin log: <input id='admin_log' type='textbox'><br>Admin password: <input id='admin_pwd' type='password'><br>Target user log:<input id='user' type='textbox'><br>Amount of points:<input id='points' type='textbox'><br><input id='send' type='submit'></form>Then your grantpoints.php should have a fragment like this: // ...set_points($username, get_points($username)+addpointfrm.points);// ...Please note that these are generic examples. Exact codification varies upon technology and even version used on a site. If you post some more details about in wich environment do you run your site and what do you pretend to do, then I'll be able to give you more 'final' code. Hoping be useful, Herenvardo, Freakiest among the freaks
×
×
  • Create New...

Important Information

Terms of Use | Privacy Policy | Guidelines | We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.