nucleon 114 Posting Pro in Training

main must return int (not void).
You are missing a closing brace.
"five" is a strange name.
datum is spelled with a u.
See comments in program.

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

struct five {
	float column1, column2;
};

// Does not need to be a friend of five since five's data are public.
istream& operator >> (istream& ins, five& r) {
	ins >> r.column1 >> r.column2;
	return ins;
}

int main(){

	ifstream input( "data.txt" );
	if ( !input )
	{
		cerr << "Cannot open file\n";
		exit( -1 );
	}

	vector<five> data;
	five datum;

	// If you test for eof, THEN read (and don't test again right
	// after) you will add an extra element to the end of the vector.
	// So test for eof something like this.
	while ( input >> datum )
	{
		data.push_back (datum);
	}

	// This loop displays the data.
	// You can be modify it to sum the data instead.
	for( size_t i = 0; i < data.size(); ++i )
	{
		cout << data[i].column1 << ", " << data[i].column2 << endl;
	}
}
nucleon 114 Posting Pro in Training

When Knuth talks about random numbers he mentions a CD of random numbers called "Black and White Noise" which is a mixture of deterministically sampled rap music combined with white noise.

nucleon 114 Posting Pro in Training

> How would I set it as a Global variable

This question suggests that you may not be ready for WinAPI programming. You should master the programming language with console programs.

To make it global: First put HWND gHWndDlg; at the top of the program (say, just before the definition of keeprunning). Then under case WM_INITDIALOG: put the line gHWndDlg = hWndDlg; . Then in ThreadProc change all hWndDlg to gHWndDlg.

nucleon 114 Posting Pro in Training

ThreadTime does not have access to hWndDlg. You need to either make it global (DlgProc would set the global var in WM_INITDIALOG)or pass it as a parameter to ThreadTime.

nucleon 114 Posting Pro in Training

The FONT line is about the 7th line in gui.rc. Put the MENU line after that.

In that same file you can get rid of <afxres.h> if you replace IDC_STATIC with its value, -1. I believe most people do this.

In main.c, <string> should be <string.h>. If you didn't get an error, then you're compiling in C++ mode (probably with a .cpp filename). This is not necessarily a problem, but if you mean to be using C, you should compile in C mode (with a .c filename).

nucleon 114 Posting Pro in Training

Write it to a string with sprintf (or wsprintf):

sprintf( buf, "Random Number: %d", random_integer );
MessageBox( 0, buf, ... )
nucleon 114 Posting Pro in Training

You haven't associated the menu with the dialog. Add this line after the FONT line in the dialog definition: MENU IDR_MAIN_MENU

nucleon 114 Posting Pro in Training

So you're saying that this piece of code will send a jpg file the first time it executes but not the second time or after that? What's the value of bytes_sent when the error occurs? If it is -1, what is the value of errno?

Notes:

You should open binary files with the "b" attribute since this makes a difference on some systems. At a minimum, your program will be more portable.

You may as well just return the same number in exit() for the different errors. If you actually meant these errors to be tested by another program, then you would give them all symbolic names and put that in a header for the other program to use. The most common return value seems to be -1 (all bits set in 2's complement).

sizeof(char) is always 1 by definition since sizeof returns its result in multiples of char, so you don't have to multiply by sizeof(char) when allocating space for chars.

nucleon 114 Posting Pro in Training

There WAS a problem in reading in the data. I don't know if I did it or you, but the extra strtok (to get rid of the letters A, B, C in the data) needs to be inside the loop. So change the code as follows:

if( strcmp( pch, "MESH_FACE" ) == 0)
		{
			int i, f;
			f = atoi( strtok( NULL, delim ));
			for( i = 0; i < 3; ++i )
			{
				strtok( NULL, delim );
				curObj->facets[f][i] = atoi( strtok ( NULL, delim ));
			}
		}
jephthah commented: man, you really slugged this one out. truly a herculean effort. +8
nucleon 114 Posting Pro in Training

That's how it looks to me too. If you rotate the pyramid it will actually disappear at one point. I don't know if that's a related problem or if that's how it always worked. Test out rotating the pyramid. If it's not working the way it used to then it must be something with the opengl part of the program and not the data structure since the pyramid is hard-coded.

P.S., I figured out what was wrong with passing fullFile to initScene. Basically, it needs its own copy of fullFile because strtok leaves the nulls in the string. I was under the mistaken impression that strtok would remove the previous null before it scanned to place the next one, so that when all was said and done the string would be back to its initial state. (Which is stupid because I recall writing a program a few years ago that depended on the nulls being left in.)

nucleon 114 Posting Pro in Training

Turns out the data structure was okay after all (it only crashed because I had forgotten to allocate space for the scene in my test program).

But I found the problem. It had to do with passing fullFile to initScene, you know that problem. For some reason it just doesn't work, and you tried to change it back (to reading the file a second time) but forgot a couple of things. I only change perhaps 2 lines.

So I think it's working. A table shows up now!

nucleon 114 Posting Pro in Training

MF: We've got bigger fish to fry! But that's definitely a good idea.

caged_fire: I've created a opengl-free version to just read and print the data structure and I'm getting errors with it! I probably won't be able to take a good look at it until tomorrow, though. I'll get back to you.

nucleon 114 Posting Pro in Training

That is strange. I finally got it to run just now. There's a black-and-white checkerboard "floor", a blue "sky", and a box and a pyramid floating in the sky.

nucleon 114 Posting Pro in Training

Oops! Remove the ampersand from that one. So it should be: glVertex3fv(object->vertices[facet[i]]); Also, you might want to use atoi instead of atof in the line given below since you're reading an integer (the line is in loadScene): curObj->facets[f][i] = atof( strtok ( NULL, delim )); Let me know if it displays the scene or not.

nucleon 114 Posting Pro in Training

Try this. ;) But it's the essentially the same. Attach your project.c file if it's still not working.

void drawPolygon( Object *object, int iFacet )
{
	int i;
	int *facet = object->facets[iFacet];

	glBegin( GL_POLYGON );
	glColor3ub( 128, 64, 0 );

	for( i = 0; i < 3; ++i )
		glVertex3fv(&object->vertices[facet[i]]);

	glEnd();
}
nucleon 114 Posting Pro in Training

You define a buffer called found_key to hold each key as it is read. It has a length of MAX_KEYNAME_CHARLENGTH (defined, suspiciously, as 20).

If you are sure your keys will never be more than 19 characters long (leaving space for a terminating null), then this is okay, except for one thing: you are also reading values into this same variable as if they were keys! You need to skip the value of keys your not interested in so that you don't read them into found_key and possibly overrunning the buffer or even misinterpretting the value as a key.

Basically you'll have to skip values in exactly the way you do when you want to read them, except you won't be storing them.

nucleon 114 Posting Pro in Training

I believe this works.

void drawPolygon( Object *object, int iFacet )
{
	int i;
	int *facet = &object->facets[iFacet][0];

	glBegin( GL_POLYGON );
	glColor3ub( 128, 64, 0 );

	for( i = 0; i < 3; ++i )
		glVertex3fv(&object->vertices[facet[i]]);

	glEnd();
}
nucleon 114 Posting Pro in Training

Try this (yet another ampersand): glVertex3fv(&object->vertices[facet[i]]);

nucleon 114 Posting Pro in Training

Mostly it was missing ampersands (to take addresses instead of values). And I forgot to return the size from initScene. Try it now.

nucleon 114 Posting Pro in Training

I would've run it if I had any data! Actually, I just made some up and got it to run, but I'm not sure how to make it crash. Could you post a single-file (minimal), runnable (crashable, actually!) example with hardcoded data that makes the program crash?

nucleon 114 Posting Pro in Training

Yes, that's the right thing to do there. And I forgot to change the call to "shape" in display to a call to drawScene.

nucleon 114 Posting Pro in Training

tux> If your computer has more than a GB of RAM that wouldn't be a problem

But the OPs computer crashed with just a megabyte-sized array. :( So it's not about total space available, but about how much stack space is reserved (which of course can be increased with a compiler option).

nucleon 114 Posting Pro in Training

WH: What are your system specs and compiler?

nucleon 114 Posting Pro in Training

WH: You're saying that the code below does not crash on your system?

#include <iostream>
int main() {
    int matrix[512][512][512];
    matrix[0][0][0] = 1;
    std::cout << matrix[0][0][0] << '\n';
}

Assuming 32-bit ints, that's half a gigabyte! Removing the 3rd dimension works for me, but that's only a megabyte.

nucleon 114 Posting Pro in Training

It would be easier if I could run this thing, but I'm getting linker errors and cannot (easily) resolve them. Anyway, here's a rewrite of the data structure to enable loading mutiple scene files into a scene array. I've renamed a couple of functions, etc., as well. See if it runs and look through it carefully to understand the changes. Overall, it's simpler than before.

nucleon 114 Posting Pro in Training

The problem seems to be that you're incrementing i all over the place but only testing if it exceeds (or equals) buf_length at the top of the loop indexed by i.

There is also one possibility of an access before the beginning of the array, so I added a check for that.

I added parens to a condition.
You had: cond1 && cond2 || cond3 but meant: cond1 && (cond2 || cond3) I added an assert at a critical place, but you will need more tests to ensure that i does not go out-of-range. The rest is up to you.

const char * sf_extract_key( const char * buf, const char * find_this )
{
	int x, b, found_value_length, buf_length = 0;
	char found_key[MAX_KEYNAME_CHARLENGTH];
	char delim;
	char* found_value;

//!	while ( buf[buf_length] != '\0' ) buf_length++;
	buf_length = strlen( buf ); //! same thing!

	for ( int i=0; i < buf_length; i++ )
	{
		//! Added test to protect against buf[i-1] looking before buf[0]
		if ( buf[i] == '"' && (i == 0 || buf[i-1] != '\\'))
		{
			i++; // move past starting "

			//! Added parens around the or clause
			for ( b=0;
				  b<MAX_KEYNAME_CHARLENGTH &&
				  (buf[b+i] != '"' || buf[(b+i)-1] == '\\');
				  b++ )
				found_key[b] = buf[b+i];
			found_key[b] = '\0';

			if ( strcmp(find_this, found_key) == 0 )
			{

				i=b+i+1; // move past ending "

				//! This is just a debugging aid.
				assert(i < buf_length - 1);

				if ( buf[i] == ':' && buf[i+1] != '{' && …
nucleon 114 Posting Pro in Training

> correct me if I'm wrong, but this seems to be designed for ints.

No, it's for any type that has < defined (or you can pass in a comparison function).

The reason I mentioned lower_bound instead of simply find (not string's find but the algorithm find) is that your use of binary_search suggested you had a sorted array.

If your array is NOT sorted then you want find as it will work on a sorted or unsorted list; but it is less efficient than the binary search performed by lower_bound.

lower_bound is easy to use, as shown in the test code below.

// lower_bound returns an iterator to the greatest element not
// less than the search element. If the search element is greater
// than all elements, then one past the last element is returned
// (i.e., the end iterator).

#include <iostream>
#include <algorithm>

void test_lower_bound( std::string *searchIn,
                       size_t       searchInSize,
                       std::string  searchFor )
{
    std::string *it = std::lower_bound( searchIn,
                                        searchIn + searchInSize,
                                        searchFor );
    // We need to check not only that the returned itereator is
    // in range, but that the element it refers to actually is
    // equal to the one we were looking for.
    if( it - searchIn >= searchInSize || *it != searchFor )
        std::cout << searchFor << " not found: fits in at index "
                  << it - searchIn << '\n';
    else
        std::cout << searchFor << " found at index: "
                  << it - searchIn << '\n';
} …
nucleon 114 Posting Pro in Training

> I am seeing 2:00 pm listed as "2:00 pm", '\0' <repeats 17 times>

Is the size of the buffer 25? Those zeros are normal.

But in general, you can't use strncpy like that. It will not null-terminate the strings. To use it as a substring operator, you must do something like this:

strncpy(Hour, ConvertTime, 2);
Hour[2] = 0; /* Ensure null termination */

As a better strcpy, it's used something like this:

char dest [ DestSize ];
strncpy ( dest, src, DestSize - 1 );
dest [ DestSize - 1 ] = 0;
nucleon 114 Posting Pro in Training

You didn't post myMath.h.

nucleon 114 Posting Pro in Training

What exactly is the state of the program at the moment? Is it running properly, except for not being able to read in multiple files of objects?

BTW, you could have put all the files in ONE zip file. :)

nucleon 114 Posting Pro in Training

Can we see the function? Remember to use code tags.

nucleon 114 Posting Pro in Training

Such flat, lifeless code. Why? No code tags! ;)

You're reading over and over to the same part of the buffer (and zeroing it before every read). Move the zeroing (if necessary) outside the loop, and either move along the buffer (read into buffer+size) or do the file operations on a buffer by buffer basis, as below.

memset(buffer,0x0,BUFFER_SIZE); // init line
pFile = fopen ( "new.jpg" , "wb" );

for(;;)
{
  rc = read (sd, buffer, BUFFER_SIZE);
  if (rc <= 0) break;
  size += rc;
  fwrite (buffer, 1 , rc, pFile );
}

fclose (pFile);
printf("\n Total received response bytes: %d\n",size);
nucleon 114 Posting Pro in Training

IDC_EASTERN_TIME is (presumably) an integer control id. You need an HWND to pass to SetWindowText. If you have an hwnd to your dialog (or whatever) window, try this: SetWindowText ( GetDlgItem ( hwndDialog, IDC_EASTERN_TIME ), cETime ); Also, cETime has too-little space allocated to it. It should be at least 24; may as well make it 32.

nucleon 114 Posting Pro in Training

Is there no way to pass the object I want to load into the methods so that I don't have to create almost identical methods everytime I want a new shape though?

It is my understanding that object is a dynamically allocated array of objects. Do you mean you want to be able to load sets of objects from multiple files?

The countObjects method doesn't work if I use fullFile as a parameter, only if I pass 'char fileName[20]' as it was before.

That makes no sense to me.

Try zipping and attaching your code this time. :)

nucleon 114 Posting Pro in Training

You want to look at lower_bound. It has the same complexity as binary_search (and also needs a sorted list). But it returns an iterator.

nucleon 114 Posting Pro in Training

And, yes, the Float3 thing is a mistake. :)

nucleon 114 Posting Pro in Training

Change these two function signatures from this:

void loadShape(char filename[20], struct Object3D *object);
void countObjects(char fileName[20], struct Object3D *object);

to this:

void loadShape(char filename[20]);
void countObjects(char *fullFile);

Change the call to countObjects (in loadShape) from this: countObjects(fileName, object); to this: countObjects(fullFile); Change the call to loadShape (in main) frm this: loadShape("scene.ASE", object); to this: loadShape("scene.ASE");

nucleon 114 Posting Pro in Training

I see. Then REMOVE those ampersands I added to glVertex3fv's argument, and try changing this:

// A type to hold 3 floats
typedef struct Point3Df {
    float x, y, z;
} Point3Df;

to this:

// Point3Df is an array of 3 floats.
typedef float Point3Df[3];

And this:

if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
			object[nObj].vertices[v].x = atof(strtok (NULL, delim));
			object[nObj].vertices[v].y = atof(strtok (NULL, delim));
			object[nObj].vertices[v].z = atof(strtok (NULL, delim));
		}

to this:

typedef float Float3[3];

		if(strcmp(pch, "MESH_VERTEX") == NULL)
		{
			v = atoi(strtok (NULL, delim));
			printf("v=%d\n", v);
                        for (i = 0; i < 3; ++i)
				object[nObj].vertices[v][i] = atof(strtok (NULL, delim));
		}

Damn these spaces and tabs! ;)

nucleon 114 Posting Pro in Training

Try this. Note the ampersands.

void polygon(int a, int b, int c, int i)
{
	glBegin(GL_POLYGON);
		glColor3ub(128,64,0);
		glVertex3fv(&object[i].vertices[a]);
		glVertex3fv(&object[i].vertices[b]);
		glVertex3fv(&object[i].vertices[c]);
	glEnd();
}
nucleon 114 Posting Pro in Training

Here's a go at the new data structure and file-handling. Note that the new data structure is easier to use and initialize. I just hope it works. I've made object global (for now) since that is most consonant with the bulk of your design.

#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include "glut.h"
#include <GL\gl.h>
#include <GL\glu.h>

// A type to hold there ints
typedef struct ThreeInts {
    int a, b, c;
} ThreeInts;

// A type to hold a 3 floats
typedef struct Point3Df {
    float x, y, z;
} Point3Df;

// A type to hold the information for a single 3D object.
typedef struct Object3D {

    // Dynamically-allocated array of facets.
	ThreeInts *facets;
	int        nFacets; // Size of facets array.

    // Dynamically-allocated array of vertices.
	Point3Df  *vertices;
	int        nVertices; // Size of vertices array.

} Object3D;


// A global pointer to hold a dynamically-allocated array of objects.
Object3D *object
int numObjects;  // Size of object array.


GLfloat rquad;
GLfloat rShapeY = 0.0;
GLfloat rShapeX = 0.0;
GLfloat rShapeZ = 0.0;


GLfloat cubeVert[][3] = {
    {-1.0,-1.0,-1.0},{1.0,-1.0,-1.0},{1.0,1.0,-1.0},{-1.0,1.0,-1.0},
    {-1.0,-1.0,1.0},{1.0,-1.0,1.0},{1.0,1.0,1.0},{-1.0,1.0,1.0}};

GLfloat colors[][3] = {
    {0.0,0.0,0.0},{1.0,0.0,0.0},{1.0,1.0,0.0},{0.0,1.0,0.0},
    {0.0,0.0,1.0},{1.0,0.0,1.0},{1.0,1.0,1.0},{0.0,1.0,1.0}};


void display();
void adjustSize(GLsizei, GLsizei);
void animate();
//void mouse(int btn, int state, int x, int y);
void Keyboard(unsigned char key, int x, int y);
void SpecialKeys(int key, int x, int y);
void polygon(int a, int b, int c, int i);
void shape();
void DrawGround();
//void windCube();
//void cube(int a, int b, int c, int d);
void loadShapes(char filename[20]);
char *readFile(FILE *sceneFile);
void countObjects(char *fullFile);


int main(int …
nucleon 114 Posting Pro in Training

Please change your data structure and file-handling as I asked above and repost your code. I had asked you some questions, too.

nucleon 114 Posting Pro in Training

Basically you just say "start a new thread of execution here". It shares the same address space as your main (or original) line of execution, which can be handy. How about something like this:

#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/time.h>
#include <pthread.h>


void*
KeyboardThread (void *unused)
{
    printf ("In keyboard thread\nPress Enter...");
    getchar();
    printf ("Exiting keyboard thread\n:);
    return NULL; /* Or pthread_exit(NULL) */
}


pthread_t
StartKeyboardThread (void)
{
    pthread_t thread;
    if (pthread_create (&thread,        /* Thread id */
                        NULL,           /* Default attributes */
                        KeyboardThread, /* Thread start routine */
                        NULL)           /* Arg to start routine */
            != 0)
    {
        perror ("StartKeyboardThread");
        exit (-1);
    }
    return thread;
}


int
main (void)
{
    /* To start it */
    pthread_t thread = StartKeyboardThread();

    /* And when you want to kill it */
    pthread_cancel (thread);

    return 0;
}
JimD C++ Newb commented: Great idea and easy to understand +1
nucleon 114 Posting Pro in Training

I was forgetting that you've already written the server, so you must know about select (?). In the client, you can try using select the same way, adding STDIN_FILENO to the fds, but it is system dependent whether that will work. If it doesn't, there may be some other system dependent way to do it (like setting it up so a signal is sent every keystroke, interrupting the select).

Alternatively, the threaded solution is actually very clean. The "keyboard" thread reads keys, sending its buffer to the "main" thread (either when enter is pressed or even char by char) which communicates with the server.

nucleon 114 Posting Pro in Training

Just to check, are each of the following statements correct?
1. Each object is made up of an arbitrary number of facets.
2. Each facet is made up of three integers (used as indices into vertices)
3. vertices is a list of all the float-3D points used by all the facets.

If the above is true, then numCols never changes from 3 and in fact simply represents the fact that your points are 3D and your facets are triangles. This allows us to remove another level of indirection from both facets and vertices and replace it with a 3-element struct.

typedef struct Point3Df {
	float x, y, z;
} Point3Df;

typedef struct ThreeInts {
	int a, b, c;
} ThreeInts;

typedef struct Object3D {
	ThreeInts *facets;       // List of facets
	int        nFacets;
	Point3Df  *vertices;     // List of vertices
	int        nVertices;
} Object3D;

This structure is used like this:

Object3D  aCube;    // A single object
Object3D *objects;  // A list of objects
// As I understand it, you need a list of objects.

// Get first index of a facet
a = objects[objectNum].facets[facetNum].a;

// Retrieve the x coord of the point represented by that index.
x = objects[objectNum].vertices[a].x;

I have not yet looked through your code carefully (this time), but you MUST change the way you deal with the file. So at least make this change (as your posted code has no line-numbers (use code=c for line-numbers) you'll have to match up the text below …

nucleon 114 Posting Pro in Training

You do not need multi-threading for this task.

Your program proceeds in lockstep because your I/O calls are of the "blocking" type and you are calling them without knowing that they are "ready". If they are not ready, they'll wait until something is ready to return. This includes fgets, which waits until the Enter key is pressed to return (line-buffered input).

You have 4 I/O statements in the loop, a simplified version of which appears below (error handling removed):

for ( ; ; ) {

    gets ( msg );   /* IO_1 */
    if ( strcmp ( msg, "q" ) == 0 ) break;

    write ( ... );  /* IO_2 */

    read ( ... );   /* IO_3 */
    printf ( ... ); /* IO_4 */
  }

Instantly, the gets() blocks reading from the terminal, waiting for an Enter keypress. If the other client had sent us a message, we won't see it until we send our message. To fix that you must read the keyboard in a non-blocking manner and yet avoid active polling.

You avoid active polling with the select() function, which will block until one of a given set of file descriptors are "ready". Blocking is good because it means you're not looping and testing (active polling), which is worse than wasteful in a multitasking environment! select() allows you to block on a set of file descriptors, waiting until any one of them is ready. (I don't know how standardized select() is, but it should …

nucleon 114 Posting Pro in Training

vbapi is no longer supported. Your article actually says so, but not very clearly (just under the article title, to the left). Try this article instead.
This one might be even newer/better.

nucleon 114 Posting Pro in Training

I saw that no one had responded. The reason I had not responded was because I was "sick of trees". That can happen, you know. Maybe everyone else was sick of trees too. And it was a fair amount of code. And it was the weekend.

I'll take a look at the new stuff when you post it.

nucleon 114 Posting Pro in Training

> yeah, that was really abrasive

Nah, not really. I just had to get used to your style. The fact is that my avatar should be a foot in a mouth.

jephthah commented: mine too. without a doubt. +6
nucleon 114 Posting Pro in Training

You may not actually want to wait in real time. You would normally do that only for a realtime animation of the process.

It depends on what output you want. You seem to just want a line by line output of what happens after each input event. Each input event should probably have a time_delta to say whether it is for the current second (0) the next (1) or something further in the future. Each output line should start with the current_time, which would usually start at zero.

nucleon 114 Posting Pro in Training

jephthah is correct, in his abrasive way. :) As he himself might say, my "solution" (actually my code for your solution) is both half-assed and of the git-er-done variety.

It is better to search for some identifying string in whatever line it happens to be in, and strstr() is useful in that regard.