Skip to main content
GameDev.net gamedev.net
🔒 Locked

Comparisons between pointer and integer?

Started by Samsonite Jan 8, 2007 at 1:22 PM 13 replies 5.7k views
Original Post
Samsonite
Samsonite
Hello, I am trying to develop a scripting system similiar to(if not a clone of)Sir Sapo's. Now, what I'm trying to do is read in these "tokens" which is the first character in the script. The problem is, I cannot make comparisons between a loaded in script and a single character: Part of cScript.cpp:

/*Process' the script and "parse it"*/
void cScript::Process()
{
     std::string script = rawScript;
     if(script[0] == "-") //if the script file starts with a - (this is where I get a comparison error
     {
          Persistent = true; //the script is persistent
     }
     else
     {
          Persistent = false;
     }
     int i = 1;
     while(script != ";") 
     {
           Command = script; //assign each character to the command
           ++i; //increment the iterator
     }
} 



and cScript.h

#ifndef CSCRIPT_H
#define CSCRIPT_H

class cScript
{
      public:
             bool LoadScript(std::string); //loads a script from file
             std::string getScript() const; //returns the current script
             void Execute() const; //execute the script
             void Process();
             std::string getCommand() const;
             cScript(std::string);
      private:
             std::string rawScript;
             std::string Command;
             std::string Param1;//both parameters are optional
             std::string Param2;
             bool Persistent(); //this is true if the script conditions should be checked each update
};

#endif



I have no idea why this shouldn't work, because neither the local "script" string nor the member variable "rawScript" is a pointer... Can anyone help? Thanks in advance! [smile] EDIT: All this-> code has also been removed since for a split second I thought that was it...
Hope I was helpful. And thank you if you were!
Zakwayda
Zakwayda
It looks like you're enclosing your character literals in double quotes; they should be in single quotes.
Samsonite
Samsonite
Thanks a bunch - no compile errors. However I cannot open the file or the file is not opened correctly. Any idea why?

bool cScript::LoadScript(std::string filepath){     std::ifstream file;     file.open( filepath.c_str() );     if( file.is_open() )     {         while( !file.eof() )         {                getline(file, rawScript);         }     }     else     {        file.close();         return false;     }      file.close();     return true;}


main.cpp
#include <iostream>#include <fstream>#include <string>#include "includes/cScript.h"int main(){    cScript* testScript = new cScript();    bool result = testScript->LoadScript("script.txt");    if(result != false)    {        testScript->Process();        std::string com = testScript->getCommand();        std::ofstream file("result.txt");        file << com << std::endl;        file.close();        std::cout << "Current command: " << com << std::endl;        std::cin.get();        return 0;    }    else    {        std::cout << result << std::endl;        std::cin.get();        return 1;    }}


Thanks a bunch!
Hope I was helpful. And thank you if you were!
Enigma
Enigma
What are you expecting to happen and what does happen?

Some random comments on your posted code:
/*Process' the script and "parse it"*/void cScript::Process(){     std::string script = rawScript;     // are you 100% certain script is not empty?     // assert(!script.empty()) here to be on the safe side     if(script[0] == "-") //if the script file starts with a - (this is where I get a comparison error     {          Persistent = true; //the script is persistent     }     else     {          Persistent = false;     }     int i = 1;     // again, you should assert that script actually contains a ';'     // to avoid reading off into the ether (assert(script.find(';') != std::string::npos);)     while(script != ";")      {           // is Command big enough to write into?           Command = script; //assign each character to the command           // i is an index, not an iterator           ++i; //increment the iterator     }     // you could replace the above loop with Command.assign(script, 0, script.find(';'));}// ----#ifndef CSCRIPT_H#define CSCRIPT_Hclass cScript{      public:             // pass strings by const reference, not value             bool LoadScript(std::string); //loads a script from file             std::string getScript() const; //returns the current script             void Execute() const; //execute the script             void Process();             std::string getCommand() const;             cScript(std::string);      private:             std::string rawScript;             std::string Command;             std::string Param1;//both parameters are optional             std::string Param2;             bool Persistent(); //this is true if the script conditions should be checked each update};#endif// ----// pass by const reference, not valuebool cScript::LoadScript(std::string filepath){     std::ifstream file;     file.open( filepath.c_str() );     if( file.is_open() )     {         while( !file.eof() )         {                // this is going to overwrite the same line over                // and over again                getline(file, rawScript);         }     }     else     {        // no need to explicitly close the file        // the ifstream destructor will take care        // of that - one of the advantages of RAII        file.close();         return false;     }      // as above     file.close();     return true;}// ----#include <iostream>#include <fstream>#include <string>#include "includes/cScript.h"int main(){    // why dynamically allocated?    cScript* testScript = new cScript();    bool result = testScript->LoadScript("script.txt");    if(result != false)    {        testScript->Process();        std::string com = testScript->getCommand();        std::ofstream file("result.txt");        file << com << std::endl;        file.close();        std::cout << "Current command: " << com << std::endl;        std::cin.get();        return 0;    }    else    {        std::cout << result << std::endl;        std::cin.get();        return 1;    }}

Σnigma
Samsonite
Samsonite
Thanks alot for your advice - I'll remember it [smile](changed the code aswell, just so you know it).

As to your question:

I'm expecting it to read a line(for now) from a file and then std::cout the text between '-' and ';' (in the script file) like so:

script.txt
-test;


and then in my program it outputs "test". Keep in mind that this is just a test program and not something I would use in a game(alot of my code is unescesary as you've noticed). None of the assertions failed(no error screen), and it still cannot read from the file(the if(file.is_open() ) code fails).
Hope I was helpful. And thank you if you were!
soggyfries
soggyfries
Are you positive that script.txt exist and is in the same directory as the executable? I tried the code and it loaded fine.
Programmer16
Programmer16
Like jyk said, you're comparing using double quotes instead of single quotes.

Switch to this:
void cScript::Process(){     std::string script = rawScript;     if(script[0] == '-') //if the script file starts with a - (this is where I get a comparison error     {          Persistent = true; //the script is persistent     }     else     {          Persistent = false;     }     int i = 1;     while(script != ';')      {           Command = script; //assign each character to the command           ++i; //increment the iterator     }} 


Using double quotes isn't a compiler error, it just doesn't work as you would expect it to (I believe since string literals are arrays, comparison with them uses memory comparison rather than data comparison.) Just read what Zahlman said below.

-edit-
Sorry, I just realized that this doesn't fix your loading problem, but it is a problem.

The only thing I can think of is that your script file isn't in the right place; your loading code looks fine to me.

[Edited by - Programmer16 on January 10, 2007 4:27:53 PM]
Zahlman
Zahlman
0) For the actual problem you report - where is the file relative to the application? Are you *sure*? Do you know where your IDE puts the .exe file?

1) More style considerations, with the code actually adjusted to implement them.

// cwhat's ca cscript, canyway?#ifndef SCRIPT_H#define SCRIPT_Hclass Script {  // I like to put the private section first, but that seems to be unusual.  // What that does is avoid the need for an explicit 'private:' label.  // Don't keep the raw script around; you don't need it.  // Oh, and RAII demands that you do all the setup work - that means load  // the file and process it - in the constructor, throwing an exception in  // case of error. That way, your object is always in a valid state.  // Because the file may contain multiple lines, I use a container like this  // to keep the lines separate:  std::vector<std::string> script_data;  // Don't keep parameters around. The name "parameter" should tip you off;  // these are values that should be passed to the execution function.  // By the way, in C++, things like "execute()" are commonly spelled   // "operator()". :) (That lets you "call" the object like a function.)    bool persistent; // you had this as a member function before, which isn't  // right if you're assigning to it.   public:  // pass strings by const reference, not value  Script(const std::string&);  // Don't provide accessors. The contents of the script should be meaningless  // to the rest of the program.  // To handle the optional parameters, I provide defaults:  void operator()(const std::string& = "",                  const std::string& = "") const;  // So that we don't require the accessor for testing, I will make  // the operator() "interpret" the script by dumping it to the file named  // in the first parameter.};#endif// ----Script::Script(const std::string& filepath) : persistent(false) {  // That initialization will be overridden if we find a '-'.  std::ifstream file(filepath.c_str());  if (!file.is_open()) {    throw std::runtime_error("can't open script file");  }  // Read each line from the file, and append up to the semicolon character  // on each line to the script buffer. As well, check for persistence on  // the first line.  bool checked_persistence = false;  std::string line;  while (std::getline(file, line)) { // A common file-reading idiom that avoids  // subtle problems with .eof().    // Ignore blank lines (even at the beginning of the script).    if (line.empty()) continue;    int begin = 0;    if (!checked_persistence) {      checked_persistence = true;      if (line[0] == '-') {        persistent = true;        // And we should probably remove that '-' from the script line:        begin = 1;      }    }    // make a temporary and add it to the vector:    script_data.push_back(std::string(line, begin, line.find(';')));    // Yes, that does handle the case where there is no ';'.  }}void Script::operator()(const std::string& filepath,                        const std::string& reserved) const {  ofstream output(filepath.c_str());  if (!file.is_open()) {    throw std::runtime_error("can't open output file");  }  // Behold the power of <algorithm>! (Oh, you'll need <iterator> too :\)  std::copy(script_data.begin(), script_data.end(),            ostream_iterator<std::string>(output, "\n"));}// ----#include <iostream>#include <fstream>#include <string>#include <exception>#include "includes/Script.h"int main() {  try {    Script test("script.txt");    // Using the script is now this easy - like it should be:    test("result.txt");    return 0;  } catch (std::runtime_error& ex) {    // script failed to load.    // We can use the exception to get a better error message than just "false":    std::cout << ex.what() << std::endl;    // Notice how I also handle an error in the *output* file now, yet the error    // handling gets unified.    return 1;  }  // Don't pause your programs artificially at the end.}
Zahlman
Zahlman
Quote:
Original post by Programmer16
Using double quotes isn't a compiler error


Yes, it is.

To get into more detail: the elements of a std::string are chars, as one might expect. However, 'char' is really an integral numeric type, in the same family as short, int and long. The idea of 'char's representing "letters" is really only a convention (and one that gets totally obliterated by the idea of Unicode), but it gets the job done most of the time (after all, *everything* is just bits, ultimately).

The 'char' type, for historical reasons, may behave as either signed or unsigned, and is always considered a distinct type from either 'signed char' or 'unsigned char' (even though it will be functionally identical to one of the two). In any event, it is "an integer" in the inclusive sense.

Meanwhile, a string literal is of type const char[(some number here, according to the length of the literal)]. However, for the purposes of comparisons (among many other things), arrays "decay" to pointers. Thus the operation the compiler sees is a comparison of "an integer" to "a pointer", and it complains (because you aren't supposed to think of pointers as numbers, even though they are machine addresses - because doing so is almost always dangerous and basically never useful).
Samsonite
Samsonite
Thanks to both for the reply, I'll check once I get home. Rate++ to all of you!
Hope I was helpful. And thank you if you were!
Samsonite
Samsonite
std::copy(script_data.begin(), script_data.end(), ostream_iterator<std::string>(output, "\n"));


This line causes an error: 49 `ostream_iterator' undeclared (first use this function)

Included all the headers, etc. Any ideas? [smile]
Also, the std::runtime_error code doesn't work either. Everything else is fine.
Hope I was helpful. And thank you if you were!
Zakwayda
Zakwayda
Quote:
Original post by Samsonite
*** Source Snippet Removed ***

This line causes an error: 49 `ostream_iterator' undeclared (first use this function)

Included all the headers, etc. Any ideas?
Looks like you're missing a std:: in front of ostream_iterator. (Also, the header is , just in case.)
Bonedry
Bonedry
And std::runtime_error can be found in the header stdexcept.
Programmer16
Programmer16
Quote:
Original post by Zahlman
Quote:
Original post by Programmer16
Using double quotes isn't a compiler error


Yes, it is.

To get into more detail: the elements of a std::string are chars, as one might expect. However, 'char' is really an integral numeric type, in the same family as short, int and long. The idea of 'char's representing "letters" is really only a convention (and one that gets totally obliterated by the idea of Unicode), but it gets the job done most of the time (after all, *everything* is just bits, ultimately).

The 'char' type, for historical reasons, may behave as either signed or unsigned, and is always considered a distinct type from either 'signed char' or 'unsigned char' (even though it will be functionally identical to one of the two). In any event, it is "an integer" in the inclusive sense.

Meanwhile, a string literal is of type const char[(some number here, according to the length of the literal)]. However, for the purposes of comparisons (among many other things), arrays "decay" to pointers. Thus the operation the compiler sees is a comparison of "an integer" to "a pointer", and it complains (because you aren't supposed to think of pointers as numbers, even though they are machine addresses - because doing so is almost always dangerous and basically never useful).


Err, yea. That's what I get for trying to think. Thanks for the correction!
Zahlman
Zahlman
Quote:
Original post by jyk
Quote:
Original post by Samsonite
*** Source Snippet Removed ***

This line causes an error: 49 `ostream_iterator' undeclared (first use this function)

Included all the headers, etc. Any ideas?
Looks like you're missing a std:: in front of ostream_iterator. (Also, the header is , just in case.)


Heh. I try to fully-qualify everything when I post on the forums (unless it's a full sample program with a using-declaration), but it's easy to forget without the compiler reminding me ^^;;

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.