Clockowl 56 Posting Whiz

Hmz. You want to split those classes up in files perhaps. Do you know how to do so? If you do, please do. It clears up the structure of your program a lot (and saves compiling time, yeey). But it's not necessary of course.

Oh, and normally people code classes like this..

class monkey {
  public:
  protected:
  private:
};

In that order, functions first, variables last. But again no biggy.

You seem to have an aweful lot of constructors:

Gun::Gun() 
{
        shotsFired = 0;
        hit = 0;
        miss = 0;
        hitPercent = 0.0;
        name = " ";
        ammo = 0;
}

Gun::Gun(int rounds) 
{
        if (rounds >= 0) {
                ammo = rounds;
        }
}

void Gun::Gun(int, double)
{
    cout << "Shots: " << shotsFired << endl;
    cout << "Hit %: " << hitPercent << endl;
}

And some double functions...

void Gun::shoot(int ammo, double hitPercent, int hit, int miss, int shotsFired)
{
    ammo--;
    shotsFired = hit + miss;
    hitPercent = hit / shotsFired;
    miss = shotsFired - hit;
}

void Gun::shoot(int, double, int, int, int)

My first suggestion is to clean the code up a bit, it'll make it a lot more readable and doesn't take very long.

Are you stuck on anything?

Clockowl 56 Posting Whiz

http://here/ didn't work for me Nucleon. ;)

Clockowl 56 Posting Whiz

Great, no problem. Good question-post. I take it for granted that you know why the program works like it does now?

Clockowl 56 Posting Whiz

A small addition:
Sometimes set functions do return something, and most of the time that's whether they succeeded or not.

Anyway, seeing the format, it's like this:

<name>, list(<subject>, <number>, <character>)

Make a function that separates those variables, so you can output them individually. If you can do that, then you can set them individually with those set functions handed to you.

Clockowl 56 Posting Whiz

So..

Read the sentences
For each sentence
  for each word
    add wordscore to sentencescore

for each sentence
   if setencescore > level, output sentence

Something like that perhaps? Go ahead, code something. It's okay to make mistakes.

Clockowl 56 Posting Whiz
while(!inFile.eof())
	{
        // use getline to read entire line  
        getline(inFile, s);
        cout << s << endl;
    }

That's wrong code. eof gets set when it has read eof, so and in that case getline() won't do a thing, so you'll output the last output twice (possibly).

Correct code:

while(getline(inFile, s)         // use getline to read entire line  
	{
        cout << s << endl;
    }

From there, again, use the set functions. You do know what your set functions do right? :D Some of the classes functions are empty though, either get rid of them or make them useful.

An example

Student someStudent;
someStudent.setName("Anne");
cout << someStudent.getName() << endl;
Clockowl 56 Posting Whiz
read sentences
add weights

? ;) Post a bit more information if you don't know how to do one of the two steps above and maybe even a bit of code?

Clockowl 56 Posting Whiz
void shoot(int ammo, double hitPercent, int hit, int miss, int shotsFired)

should be

void gun::shoot(int ammo, double hitPercent, int hit, int miss, int shotsFired)

Do you know what a static data member means in C++? It seems unlikely that every gun shares the same number of bullets. ;)

Clockowl 56 Posting Whiz

Nucleon: You didn't return anything from main and compared -1 and and unsigned int (size_t). Also, the code creates lots of strings with zero length, which is probably not wanted.

But yeah, C++ classes and functions are way better for this than C types and functions.

Anyway, here's the code the OP can hand in to his teacher (we didn't really answer his question though. xD)

#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;

int main() {
    ifstream ins ("Line.txt");
    string line;
    vector<string> fields;

    while (getline (ins, line)) {
        cout << line << '\n';

        int pos, lastPos = 0;
        while ((pos = line.find_first_of(":", lastPos)) != -1) {
            if((pos - lastPos) > 0)
                fields.push_back (line.substr (lastPos, pos - lastPos));
            lastPos = pos + 1;
        }

        for (int i = 0; i < fields.size(); ++i)
            cout << fields[i] << '\n';
        fields.clear();
    }

    return 0;
}
Clockowl 56 Posting Whiz
while(firstTry == true)
		{
			{
				cout << "It Is Your First Try, We Will Create My Array First:\n";
				updateArr(arr, size);
			}
			return firstTry = false; //Don't return here, hehe. 
		}

Should be something along the lines of..

if(firstTry == true)
		{
			cout << "It Is Your First Try, We Will Create My Array First:\n";
			updateArr(arr, size);
			firstTry = false;
		}
Clockowl 56 Posting Whiz

You're outputting a regular text file if I'm not mistaken. The Word Document format is closed and (therefore) hard to understand.

Tagging ".doc" on the end of your filename doesn't make it a Word Document.

Clockowl 56 Posting Whiz
#include <cstdio>
using namespace std;

void testing(const void *buf){
    puts((char*)buf);
}

int main() {
    char *x = "somebytes";
    testing(x);

    return 0;
}

That works here, does that small program also work for you?

Clockowl 56 Posting Whiz

Here's the correct version of your program to my best knowledge.

#include <iostream>
#include <fstream>
using namespace std;

static const unsigned int maxWords = 50;
static const unsigned int maxLineLen = 500;


int main() {
    ifstream ins;
    ins.open("Line.txt", ios::in);

    char *temp[maxWords];
    char line[maxLineLen];

    //while (!(eof || fail || bad))
    while (ins.good()) {
        //fetch a new part til newline
        ins.getline(line, maxLineLen);
        //show it
        cout << line << endl;

        //set the first word
        temp[0] = strtok(line, ":");

        //fill the elements, maximum of the array's size.
        for (unsigned int i = 1; i < maxWords; i++) {
            temp[i] = strtok(NULL, ":");
            //can't put this in for-condition, i gets incremented BEFORE condition check
            if(temp[i] == NULL) break;
        }

        //find until there are no more words, or no more elements for the words
        for (unsigned int i = 0; temp[i] != NULL && i < maxWords; i++) {
            cout << temp[i] << endl;
        }
    }

    return 0;
}
Clockowl 56 Posting Whiz

Sorry if this sounds harsh, but there are numerous problems with your code's logic. Is it guarranteed that there are a max of 7 tokens in your strings? And that the size of those is 99 chars max? And that all of the lines in your file don't contain whitespace? (istream << reads until the whitespace! ;) )

A bit more foolproof version of the program would look like this for instance:

int main(){
	ifstream ins;
	ins.open("Line.txt", ios::in);

	char *temp[7];
	char line[100];

	while(!ins.eof() && ins.good())
	{
		
		ins >> line;
		cout << line << endl;
		
		temp[0] = strtok(line, ":");
		for(int i = 1; temp[i] != NULL && i < 7; i++)
		{
			i++;
			temp[i] = strtok(NULL, ":");

		}
		cout << temp[0] << endl;
		//cout << temp[1] << endl;
		cout << temp[5] << endl;
		cout << temp[4] << endl;
	}
}
Clockowl 56 Posting Whiz

You can easily test that, just put some messages in the destructor and some in the program itself to see its place right? ;)

Clockowl 56 Posting Whiz

No, that's not the proper solution to this.

This is

#include <iostream>
#include <string>
using namespace std;

class car {
public:
    car (float speed) :
            speed(speed) {}

    car () :
            speed(0) {}

    void cruise(float speed) {
        this->speed = speed;
        getSpeed(true);
    }

    void brake(float power) {
        this->speed -= power*power/4;
        getSpeed(true);
    }

    float getSpeed(bool verbose = false) {
        if (verbose) {
            cout << "New speed: " << getSpeed() << endl;
        }
        return speed;
    }

private:
    float speed;
};

class racer : virtual public car {
public:
    void boost(float power) {
        cout << "BOOST! ";
        cruise(getSpeed() + power*power/3);
    }
};

class tank : virtual public car {
public:
    bool shoot(float aimTime) {
        cout << "Shot ";
        if (aimTime > 5.0) {
            cout << "hits!" << endl;
            return true; //hit!
        } else {
            cout << "misses!" << endl;
            return false; //miss!
        }
    }

};

class racetank : public racer, public tank {
public:
    bool boostShoot(float power, float aimTime) {
        boost(power*2);
        return shoot(aimTime*2);
    }
};

int main() {
    racetank mycar;
    mycar.cruise(50);
    mycar.boost(20);
    mycar.brake(5);
    mycar.boostShoot(35, 1.4);

    return 0;

    return 0;
}

This way, racetank only has one base object car, not two. Virtual Inheritance :D

Clockowl 56 Posting Whiz

Quoting myself:
I know the solution to this is to use virtual inheritance, but I was wondering why C++ works like it does.

The correct solution is to virtual inherit the class cars in race and tank class. This way, the compiler creates only one car inside of racetank, and 2 vtables to be able to still call the functions.

Basically, I was just wondering why GCC doesn't just pick one of the functions and give me a warning instead of 2 errors.

--Edit, a bit later:

So the compiler asks me what this pointer to give to the function, that of class a or b? It doesn't matter if one only uses class c, but when one degrades class c to class a, b or base, the data members may have different values then what was expected if the compiler chose instead of the programmer. Say function modifies int value, how would the programmer know what value it was modified, that of a or b? Therefore a name must be presented if one wants to call functions like this.

The "proper" solution, in most cases, is to go by virtual inheritance.

This was helpful research. Multiple Virtual Inheritance seems a nice and powerful tool, albeit a bit tricky.

Clockowl 56 Posting Whiz

Replying to myself yeey.

Let a class in memory be resembled by:

[classname]

Class inheritance in memory looks like this, according to wiki.

class a;
class b : a;

class a looks like this:
[a]

b looks like this:
[a]

So if we'd have a class base and c, we can create a diamond inheritance:

class base;
class a : base;
class b : base;
class c : a, b;

Their memory-pictures are like this:

base: [base]
a: [base][a]
b: [base]
c: [base][a][base][c]

c, more specific, looks like this:
[a::base][a][b::base][c]

So, naturally, a::base and b::base data members can differ, but a::base::func() must be the same as b::base::func() given that a and b don't overload and func() is not virtual right? How else can they be different?

Clockowl 56 Posting Whiz

From the reference:

"... The unicode field is only used when UNICODE translation is enabled with SDL_EnableUNICODE. ... "

I suppose you did that, but below there is code on how to translate that code back to ASCII.

Buuuuttt as he also notes, if you're not using unicode, don't enable it. Why not grab the .sym instead and convert that? Hope it helps anyway.

Clockowl 56 Posting Whiz

Maybe make sure that conversion is going alright?

Output (char) (event.key.keysym.unicode) or something.

ASCII chars in UTF-8 might be something like, {\x00\x<ASCII-code>}, in that case, you're appending \x00 ;). It's my best guess.

Clockowl 56 Posting Whiz

Hey guys,

I was wondering, with this code:

main.cpp

#include <iostream>
using namespace std;

class car {
public:
    car (float speed) :
            speed(speed) {}

    car () :
            speed(0) {}

    void cruise(float speed) {
        this->speed = speed;
        cout << "New speed: " << getSpeed() << endl;
    }

    void brake(float power) {
        this->speed -= power*power/4;
    }

    float getSpeed() {
        return speed;
    }

private:
    float speed;
};

class racer : public car {
public:
    void boost(float power) {
        cout << "BOOST! ";
        cruise(getSpeed() + power*power/3);
    }
};

class tank : public car {
public:
    bool shoot(float aimTime) {
        cout << "Shot ";
        if (aimTime > 5.0) {
            cout << "hits!" << endl;
            return true; //hit!
        } else {
            cout << "misses!" << endl;
            return false; //miss!
        }
    }

};

class racetank : public racer, public tank {
public:
    bool boostShoot(float power, float aimTime) {
        boost(power*2);
        return shoot(aimTime*2);
    }
};

int main() {
    racetank mycar;
    mycar.car::cruise(50);
    mycar.boost(20);
    mycar.car::brake(5);
    mycar.boostShoot(35, 1.4);

    return 0;
}

MinGW's GCC gives me these errors:

D:\MyDocs\Code\InheritThis\main.cpp||In function `int main()':|
D:\MyDocs\Code\InheritThis\main.cpp|62|error: `car' is an ambiguous base of `racetank'|
D:\MyDocs\Code\InheritThis\main.cpp|64|error: `car' is an ambiguous base of `racetank'|

How come the compiler still complains about ambiguity?

It knows the function is not overloaded (?)
It knows the function is not virtual.

Can't the compiler be sure that when I call the function like that, it's the same function?

Thanks in advance,

PS:
I know the solution to this is to use virtual inheritance, …

NicAx64 commented: hmm nice and smart bug , I think I find something new +1
Clockowl 56 Posting Whiz

You used defines in C++, most people look down on that for the reason that you can also use (static) const unsigned ints in your case. It has the benefit of type checking.

The array initialization is okay with the brackets, but if you make it a loop you won't have to update it manually each time. Maybe you can read up about memset().

The menu decision part now consists of if... if... It's more natural to make that a switch statement.

All of these tips won't have impact on the output of the program, but they are useful nonetheless.

Horribly off topic, what game is this? X in a row? Sudoku? The rest is looking good. :)

Clockowl 56 Posting Whiz

%d is just a format character for format strings used by print and scan functions. Check it out

In my code it's the window handle. A "window pointer" as it were, for Windows.

Clockowl 56 Posting Whiz

Ah, okay. Thanks for the explanation.

Clockowl 56 Posting Whiz

Thanks, it works, but...

That's where the guards (the #ifdef stuff) are for right? Not trying to be impolite, but why can't I include those headers with the guards in place?

Clockowl 56 Posting Whiz
newnode = new Node;
newnode = NULL;

Eerrrr? That's a bit of weird code. You're trying to derefence that pointer on the next line! ;)

Clockowl 56 Posting Whiz

'lo there folks,

MinGW's giving me 1 error I can't get rid of:

eventhandler.h|9|error: `element' has not been declared|
eventhandler.h|9|error: ISO C++ forbids declaration of `elem' with no type|

All code mentioned and I think needed:

eventhandler.h

#ifndef EVENTHANDLERH
#define EVENTHANDLERH

#include "element.h"

enum events {onClick, onHover};

typedef struct eventHandlerT {
    void(*func)(element *elem);
    events eventType;
} eventHandler;


#endif // EVENTHANDLERH

element.h

#ifndef ELEMETH
#define ELEMETH

#include "eventhandler.h"

class element {
    public:
    element();
    ~element();

    void processEvent(events event);

    vector<eventHandler> handlers;
    unsigned int ID;
    static unsigned int IDcount;
};


#endif // ELEMETH

Why is element not declared? I don't get that, the header is included right above it?

Any help is greatly appreciated,

Clockowl 56 Posting Whiz

The "numbers" are the size of the buffer, but you could've easily looked that one up on MSDN. "%d" means decimal. It's the format thingie for signed and unsigned decimal numbers I thought, might wanna check that.

Clockowl 56 Posting Whiz

You can probably get the state of a window by using an API, have you tried looking for it? I don't know any from the top of my head. If there isn't any, you could try and hide the window, and if the function ShowWindow() returns 0, it was already in the state you tried to set it in. I think. Better check on that though.

Clockowl 56 Posting Whiz

Ah yes, of course, thanks a bunch. I'll take a look at the ctor next time such a question pops into my mind.

Clockowl 56 Posting Whiz

Hey guys, I was wondering if the stringstream class copied the string to itself or just keeps a pointer.

Because if it copies I can free or clear the string without fearing for the data in stringstream.

EDIT:

Like this:

string stringz0r("Chickenz");
stringstream streamz0r(stringz0r);
//will this not affect the stringstream in any way?
stringz0r.clear();

Or, maybe a bit more complicated:

string *stringz0r = new string("Chickenz");
stringstream *streamz0r = new stringstream(*stringz0r);
//will this...
delete stringz0r;

Thanks in advance,
Nick

Clockowl 56 Posting Whiz

I thought a reference was basically a constant pointer, so that's why I thought I could replace any occurrence of "&" with "* const" and vice versa, but I was wrong. Coming from C I'm always wondering when to use references (they're strange and new and owell) and when just to stick with the somehow trusted concept of pointers...

Several minutes later

This article seems to explain the issue pretty well for me. References are pretty neat, but a bit hard to know when to use them and when not to. I'm sticking with "most of the time, use references" for now. When I don't want it to change the object itself I should just declare it a const.

Clockowl 56 Posting Whiz

Hey guys, I was wondering...

I always assumed that references were more or less constant "dereferenced" pointers.

With that in my mind I tried to do this:

#include <iostream>
#include <string>
using namespace std;

void outputIt(const string * const textz00rs){
    cout << *textz00rs << endl;
}

int main(){
    outputIt("window");
    return 0;
}

But that'll give me the error: cannot convert `const char*' to `const std::string*' for argument `1' to `void outputIt(const std::string*)' So I tried:

#include <iostream>
#include <string>
using namespace std;

void outputIt(const string &textz00rs){
    cout << textz00rs << endl;
}

int main(){
    outputIt("window");
    return 0;
}

And it works as planned! Where's the true difference between these two pieces of code? The compiler knows just as much in both cases, right?

Thanks in advance,
Nick

Clockowl 56 Posting Whiz

D'oh! I thought I'd already done tried that. Thanks. :)

Clockowl 56 Posting Whiz

Hey guys, I'm getting this kinda vague error:

Zeal\src\window.cpp|19|error: cannot declare member function `static unsigned int zeal::window::getWindowCount()' to have static linkage|

With the following code (only what I think is needed, if you need more please do ask)

window.h

namespace zeal {
class window : public element
{
    public:
    static unsigned int getWindowCount();

    private:
    static unsigned int windowCount;
};
}

window.cpp

unsigned int zeal::window::windowCount = 0;

namespace zeal {
    static unsigned int window::getWindowCount(){
        return windowCount;
    }
}

It's only called once from main, I want to call it like this:

main.cpp (one line only)

cout << "Nr of windows: " << window::getWindowCount() << endl;

Any help is much appreciated as usual,
Nick

Clockowl 56 Posting Whiz

You need to include a .lib, .dll or .a file from the library you are using I guess. What are you exactly doing/trying to do?

Clockowl 56 Posting Whiz

heh. Topic is going to hell but whatever.

I'm reading in XML data and have named my members and their attributes the same. So the XML element <element> has the attribute name. I read those attributes as strings, so that when I've read the attribute, I'll have 2 strings: one containing the attribute's name and one containing the value of that attribute:

"name" "10"

Then I want to change that variable to a integer and set the class member element::name to that integer (10). So, I compare the string to the element's member name (which is in this case "name") and if that's correct I set that member. :D

if(strAttrName == "name"){
    strAttrVal >> this->name;
}

because I don't want to write this 20 times, I created that macro:

#define setElementMember(x)\
            if(strAttrName == #x){\
                str >> this->x;\
            }

and I undefine it right after I don't need it anymore to make sure it doesn't get used anywhere else in the code.

Here's the final code:

//! Sets elements attrList AND the corresponding member variable.
    //! Current method does not allow setting of <char *> member variables due to the need for memory allocation. Necessary? (don't forget setName() )
    void element::setAttribute(const char *attrName, const char *value)
    {
        cout << "Setting " << attrName << " to " << value << endl;

        map<string, string>::iterator it = attrList.find(attrName);

        if(it != attrList.end())
        {
           attrList.erase(it);
           attrList[attrName] = value;
        }

        string strAttrName(attrName);
        string strValue(value);
        stringstream str(strValue);

        #define setElementMember(x)\
            if(strAttrName …
Clockowl 56 Posting Whiz

Here are two examples I created and use as a reference, maybe they are of help:

/* 
** Playing around with WinSockets
*/ 

#include <stdio.h>
#include <winsock.h>

int main (int argc, char **argv){
  WORD wsaVersion;
    wsaVersion = MAKEWORD(2,2);
  WSADATA wsaData;
  SOCKET sock1;
  int wsaerr;


  wsaerr = WSAStartup(wsaVersion, &wsaData);
  if (wsaerr != 0){
    printf("\nWinsock not found");
    return -1;
  }
    printf("Winsock found");

  sock1 = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  if (sock1 == INVALID_SOCKET){
    printf("Initializing socket failed: %ld\n", WSAGetLastError());
    WSACleanup();
    return -1;
  }
    printf("\nSocket() works");

  WSACleanup();
  return 0;
}
#include <stdio.h>
#include <winsock2.h>

int main(int argc, char **argv){
  WORD wsaVersion = MAKEWORD(2,2);
  WSADATA wsaData;
  int wsaerr;
  
  wsaerr = WSAStartup(wsaVersion, &wsaData);
  if (wsaerr){
    printf("WSAStartup failed, exiting.");
    return -1;
  }
  SOCKET somesock;
  somesock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
  
  if (somesock == INVALID_SOCKET){
    printf("Socket() failed, exiting.");
    WSACleanup();
    return -1;
  }
  
  struct sockaddr_in service;
  service.sin_family = AF_INET;
  service.sin_addr.s_addr = inet_addr("127.0.0.1");
  service.sin_port = htons(12344);
  if (bind(somesock, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR){
    printf("Bind() failed, exiting.");
    closesocket(somesock);
    WSACleanup();
    return -1;
  }

  closesocket(somesock);
  WSACleanup();
  return 0;
}

Here's are tiny server/client applications. I don't guarrantee they work or are the holy grail of winsock programming, but if they still work then they are good references. ;-)

basicServer.c

/*BasicServer.c*/

#include <stdio.h>
#include <winsock.h>
#include <string.h>

#define BUFFERSIZE 511

int main(int argc, char **argv){
  if (argc < 3){
    printf("Usage: %s <message to send to client> <ip to listen to>\n", argv[0]);
    return -1;
  }
  SOCKET sock, accepsock = SOCKET_ERROR;
  WSADATA wsaData;
  WORD wsaVersion = MAKEWORD(2,2);
  int sizeOf, wsaerr;

  struct sockaddr_in sockinfo, clientinfo;
  sockinfo.sin_family = …
Salem commented: Looks good. +26
Clockowl 56 Posting Whiz

First post!

Read the sticky at the top of the forum?

Clockowl 56 Posting Whiz

I changed it to #x and it works fine. Besides your needless ranting you haven't really said anything I asked for like an alternative.

And why would I make a "claim" about such a thing? I have class (element) with a private member (int name), is that weird or something?

Clockowl 56 Posting Whiz

That's one way to put it, how would I do that? I need to make a string at compile time you see: this->x; refers to a member with the name x.

For instance, element has a member name, so now I can say: setElementMember(name) And it'll set the member variable and compare with the correct string. I think the only way to do this is with macros, but I wasn't sure.

Clockowl 56 Posting Whiz

Small new unrelated question:

Do you guys think macros such as these are okay to use, or do you have an alternative or something?

#define setElementMember(x) {\
    if(attrName == "x"){\
        str >> this->x;\
    }\
}
Clockowl 56 Posting Whiz

EDIT: Removed the first paragraph, made no sense.

Major thanks for that streamstring thingy, ton of opportunities.

Edit: WHOA! Didn't refresh for an hour (due to telephone) then posted a reply, heh. Thanks for all the input, I think I can make something of that.

Clockowl 56 Posting Whiz

Hey guys,

Could I "teach" my compiler to do automatic type conversions for me?

So when I have this program:

#include <cstdio>
#include <string>
using std::string;

int main(){
    int x;
    string y = "1234567890";

    x = y;

    printf("y: %s == %d\n", y.c_str(), x);

    return 0;
}

It won't give me main.cpp|10|error: cannot convert `std::string' to `int' in assignment| But compile and do everything alright? I know C++ has this function somewhere since it can do a lot of conversions without having to use functions on the line itself (i.e. by simply casting), but I couldn't find details about it.

Thanks in advance,

Clockowl 56 Posting Whiz

Hey guys,

I'm stuck on some undefined references to glut and OpenGL, even when I linked my projects with the correct libraries. Well apparently they aren't correct...

I'm trying to compile this:

/* Copyright (c) Mark J. Kilgard, 1994. */

/* This program is freely distributable without licensing fees 
   and is provided without guarantee or warrantee expressed or 
   implied. This program is -not- in the public domain. */

#include <GL/glut.h>

GLfloat light_diffuse[] =
{1.0, 0.0, 0.0, 1.0};
GLfloat light_position[] =
{1.0, 1.0, 1.0, 0.0};
GLUquadricObj *qobj;

void
display(void)
{
  glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  glCallList(1);        /* render sphere display list */
  glutSwapBuffers();
}

void
gfxinit(void)
{
  qobj = gluNewQuadric();
  gluQuadricDrawStyle(qobj, GLU_FILL);
  glNewList(1, GL_COMPILE);  /* create sphere display list */
  gluSphere(qobj, /* radius */ 1.0, /* slices */ 20,
  /* stacks */ 20);
  glEndList();
  glLightfv(GL_LIGHT0, GL_DIFFUSE, light_diffuse);
  glLightfv(GL_LIGHT0, GL_POSITION, light_position);
  glEnable(GL_LIGHTING);
  glEnable(GL_LIGHT0);
  glEnable(GL_DEPTH_TEST);
  glMatrixMode(GL_PROJECTION);
  gluPerspective( /* field of view in degree */ 40.0,
  /* aspect ratio */ 1.0,
    /* Z near */ 1.0, /* Z far */ 10.0);
  glMatrixMode(GL_MODELVIEW);
  gluLookAt(0.0, 0.0, 5.0,  /* eye is at (0,0,5) */
    0.0, 0.0, 0.0,      /* center is at (0,0,0) */
    0.0, 1.0, 0.);      /* up is in positive Y direction */
  glTranslatef(0.0, 0.0, -1.0);
}

int
main(int argc, char **argv)
{
  glutInit(&argc, argv);
  glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
  glutCreateWindow("sphere");
  glutDisplayFunc(display);
  gfxinit();
  glutCreateWindow("a second window");
  glutDisplayFunc(display);
  gfxinit();
  glutMainLoop();
  return 0;             /* ANSI C requires main to return int. */
}

And added these options to the linker (according to code::blocks):
-lopengl32
-lglu32

Clockowl 56 Posting Whiz

That void* to char* isn't even giving me a warning with -Wall in GCC so I suspect that it's not necessary at all. This isn't C++.

Don't forget that void means (afaik) "lack of type", so you can just convert it to anything if you want to. No such thing as "can't convert from void to..." in C I think.

And you're first fix doesn't make sense. The fixes by Salem are correct.

Oh and final thanks to Salem and Aia because the optimization sped it up about.. 25 times. (with in GCC -O3, and that expensive optimizations mode). Yeah. That's sorta embarrassing, but I'm glad I followed your advice.

Clockowl 56 Posting Whiz

Ah yes, weird.. Weird.

I disagree with this:

"The string is a constant, so calling strlen() every time is only going to waste time, because it always returns the same result."

I'm expecting my compiler will do that for me, it seems like a very simple optimization to make, right?

The rest is right on the money, thanks a bunch.

Clockowl 56 Posting Whiz

Hey guys,

This program gives me a nice segfault (on line 27 and if it's removed on the realloc() below that) and I can't seem to figure out why. Any help is greatly appreciated.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

/*
  Parses parse_this for tokens using strtok() with seperators
  (but doesn't alter parse_this due to internal copy) and puts
  tokens into array_of_strings.

  array_of_string (out): should be a NULL pointer in the beginning.
  nr_of_strings (out)  : contains the number of strings
  parse_this (in)      : string to be parsed
  seperators (in)      : seperators to be passed to strtok()
*/

int cexplode(char ***array_of_strings, unsigned int *nr_of_strings, const char * const parse_this, const char * const seperators) {
    unsigned int loc_nr_of_strings = 0;
    unsigned int n = 0;
    unsigned int sepcnt = 0;

    for (sepcnt = 0; sepcnt < strlen(seperators); sepcnt++) {
        for (n = 0; n < strlen(parse_this); n++) {
            if (parse_this[n] == seperators[sepcnt]) loc_nr_of_strings++;
        }
        loc_nr_of_strings++;
    }
    printf("DEBUG: %p | %d\n", (*array_of_strings), loc_nr_of_strings);

    (*array_of_strings) = realloc((*array_of_strings), loc_nr_of_strings * sizeof(char*));
    memset((*array_of_strings), 0, loc_nr_of_strings * sizeof(char*));

    char *parse_this_copy = calloc(sizeof(char), strlen(parse_this) + 1);
    strcpy(parse_this_copy, parse_this);

    char *pch = strtok(parse_this_copy, seperators);

    n = 0; //string count
    while (pch != NULL) {
        //allocate, copy, print, next string
        (*array_of_strings)[n] = realloc((*array_of_strings)[n], strlen(pch) + 1);
        memset((*array_of_strings)[n], 0, strlen(pch) + 1);
        strcpy((*array_of_strings)[n], pch);
        n++;
        pch = strtok (NULL, seperators);
    }

    //loc_nr is for alloc. loc_nr can be > true nr. of strings, n is always true nr of strings.
    loc_nr_of_strings = n;
    (*nr_of_strings) = loc_nr_of_strings;

    return 0; …
Clockowl 56 Posting Whiz

Nah I just meant to say that if you're sure that you'll only use it on your system, why not use those compiler specific functions? I think it's overkill to make basically everything you create cross platform, but if you're coding for your job then you should I guess... I'm a hobby coder. :)

Clockowl 56 Posting Whiz

I'm more of a newb but feeling cocky as always:

Don't AVOID compiler specific functions, but be sure to find a cross-compiler way to do it as well, as in: find it, use it a couple of time, memorize it.

However, I think it's a definite plus if you also know compiler specific tweaks.