mcriscolo 47 Posting Whiz in Training

Hi,

A couple of things to look at:

1 - In your function "MStudent" - what are you doing with the return value from this? Hint - check out how you are calling it.
2 - In the function "CalcAvrg" - take a closer look at how you are accessing the items in the array. One dimension is for each student and the other is for each grade for a particular student.

-Mike

mcriscolo 47 Posting Whiz in Training

You can't declare an instance of a variable more than once. That's what's happening. Try this:

// Secondary.h
#ifndef SECONDARY_H
#define SECONDARY_H

#include <iostream>
using namespace std;
#include <string.h>
extern string HelloWorld;

void HelloEarth();

#endif

Change Main.cpp and Secondary.cpp to include "Secondary.h", remove the function declaration of "HelloEarth" from Main.h, and remove the include for Main.h in Secondary.cpp. This allows you to declare the variable once in Main.h, and reference it from other places.

Chuckleluck commented: Got straight to the point and showed me what was wrong with my code +2
mcriscolo 47 Posting Whiz in Training

Well, that's because you can only send one "piece" of data through when you start the drag. May be a bit of overkill, but can you do this in "button1_MouseDown":

button1.DoDragDrop(button1, DragDropEffects.Copy);

Then, in "button2_DragDrop":

Button oButton = (Button)(e.Data.GetData(typeof(Button)));

Now, you have a reference to button1, and all of the props within it.

mcriscolo 47 Posting Whiz in Training

Your deletion routine is not correct - you are leaving the pointer from the previous entry in the list dangling. Example: if you enter the values 3, 2, 1 in your list, you will have a list in order from head of 1 - 2 - 3.

When you go to remove the even numbers, you will start at 1 (head) and see that it doesn't need to be removed, so you move to 2. That should be removed. You set "step" to point to the 3, then remove the 2 - but the pointer from 1 - it's still pointing to where 2 was (it has an address in it, though it is invalid).

One way to do it is to have a "trailing" pointer (call it "prev") and set it to NULL. Each time you increment "step" WITHOUT deleting a node, you set "prev" equal to "step" BEFORE you increment "step". Then in the deletion logic, you set "prev->next" equal to "step->next", so the pointer from the previous node now points to the node after the one just deleted.

mcriscolo 47 Posting Whiz in Training

You can trap the "ClientSizeChanged" event on the RichTextBox. In both cases (when the scrollbar appears and disappears), this event will fire.

Momerath commented: My example came from your statement so you deserve credit +3
mcriscolo 47 Posting Whiz in Training

I'm not really sure why the code you have is not producing that. Further, perhaps if I knew what the program was trying to accomplish, I might be able to give more directed insight. So far, I've been trying to address the specifics of what you say is not working.

Is this for an assignment? Is this just an example but not part of your actual program?

Sometimes, trial and error is the best way. You muddle through things, gaining understanding of how the library functions work and how to construct the code to do what you want. What may not be fun is when you have to do all of that on a tight schedule.

mcriscolo 47 Posting Whiz in Training

Try this:

// Convert &lt; &gt; etc. to HTML
String sResult = HttpUtility.HtmlDecode(sData);
// Remove HTML tags delimited by <>
String result = Regex.Replace(sResult, @"<[^>]*>", String.Empty);

If you are using a .NET Forms app, you will have to specifically reference "System.web" in order to get your hands on "HttpUtility". "Regex" is in "System.Text.RegularExpressions".

mcriscolo 47 Posting Whiz in Training

Your seekg positioning is off. When you add records, you use:

fio.write((char*)(&t1), sizeof(t1));
    fio.write((char*)(&active), sizeof(active));

but when you look for records in your modify and delete, you use:

fio.seekg((number + 1) * sizeof(t1));

all well and good, but you are not accounting for the 1 byte boolean (active) that you write at the end of each record. Your seek code should look like:

fio.seekg((number + 1) * (sizeof(t1) + sizeof(active)));

You might consider moving the "active" flag inside your tool class - then your calculations work.

Some other things - the "tool" instance you pass into your getInput method is useless (other than to calculate the size of the tool object) - also the calculation is incorrect here, as well. You can use "sizeof(tool) + sizeof(boolean)".

Your "getInput" method - when you add a new record (when "modify" is false) - what happens when I add 2 records, and I type in a record number of "1" for both? It appears that I will overwrite the first record with the second. An add operation should seek to EOF and add there.

That should be enough to get you going.

mcriscolo 47 Posting Whiz in Training

Really? I ran this and I got 0x01. Here's the code (Eclipse Helios on Windows 7):

public class ArrayRefTest 
{
	public ArrayRefTest()
	{
		//Default Constructor
	}
	
	public static void main(String[] args)
	{
		ArrayRefTest a = new ArrayRefTest();
		a.foo();
	}
	
	public void ChangePrimitiveArray(byte bytes[])
	{
	    bytes[0] = 1;
	}

	public void foo()
	{
	    byte bytes[] = new byte[2];
	    bytes[0] = 4;
	    ChangePrimitiveArray(bytes);

	    System.out.printf("bytes[0]=0x%02x\n", bytes[0]);
	}
}

Check this out:

http://www.javacoffeebreak.com/faq/faq0066.html

VernonDozier commented: Thanks. +13
mcriscolo 47 Posting Whiz in Training

Are you checking the contents of the output file while the program is still running? Normally, when the file is closed (either explicitly, or when the object is disposed and the GC cleans it up), the buffers will be flushed.

If you want to check the status of your output file while the program is still running (e.g., you have a long-running process that's, say, writing a log file), then you will want to call "Flush" on the stream to push the data onto the disk.

A lot of things can affect when the data from a stream is actually written to the file (how long the process runs, how much data you are writing, etc.)

Does one program write more data than the other? A stream has a buffer, that, when it fills up, will be flushed to the disk. If one program is not writing a lot of stuff and you check it while still running, your file may be empty.

kvprajapati commented: Good point. +11
mcriscolo 47 Posting Whiz in Training

First, that semicolon on line 8 (between the end of your method implementation and the curly brace) is going to be a problem....

"blabla.date" is "const char *". So, one of 2 things: either cast the return value as (char *), so it will match the method prototype:

return (char *)blabla.date;

or, change the method prototype to return a type of "const char *":

class Bla{
private:
   char date[9];
public:
   const char* ReturnDate(const Bla& blabla);
};

const char* Bla::ReturnDate(const Bla& blabla){
   return blabla.date;
}
mcriscolo 47 Posting Whiz in Training

Knowing nothing more about your code that what you wrote, an extremely high-level solution could look like:

1) Convert your main() function to C# in a new C# Console Application project.
2) Create a new C++ "Class Library" project.
3) Copy all of your C++ code, minus the main() function, into the new project.
4) Attempt to build the C++ library.
5) In your C# project, set a reference to the new C++ Class Library.
6) Run the C# program and see what happens.

Again, that's extremely high-level, and discounts any possible non-portable constructs that may be in the C++ code that will have to be modified/rewritten to work with the CLI. It also assumes that the main() function in your current C++ program is relatively straightforward and can be converted to C# easily.

That's the way I'd start out, at least.

Good luck!

jonsca commented: Good suggestions. +6
pseudorandom21 commented: Helpful, and interesting post. +0
mcriscolo 47 Posting Whiz in Training

zachattack05,

To answer your last question first - no, security and tech support issues are never unfounded. Once you deliver an application to a user, you have to support it. And you will also have to make sure that only authorized users access the system.

I may have misunderstood part of your explanation of the app - you will be delivering the "server" app to your customers? I was under the impression that the server would remain with you (or your company) and the clients would access it over the network. Of course, if you are packaging up this solution, then the decision to include or not to include a full-blown database is a big one.

If I also understand part of the use case for the clients, you would want to be able to access the "server" directly from programs like Word or Excel? Hmm... If I had to do that, I'd open the can of worms with the database. While there is a lot of management that comes with it, I still maintain that it would be easier and take less time than trying to develop a wire protocol mimic of SQL Server or ODBC. You could always lock down the security in the database, and also issue the standard warning that if the customer monkeys with the database that you're not responsible, blah, blah (even though you and I both know you really are... But maybe you can beat some support $$$ out of …

mcriscolo 47 Posting Whiz in Training

Other than the details you gave in your post (so I don't know the *real* complexity of your app, or your budgetary constraints), might I suggest that you actually convert the data for your app to use a database? That is (and again, I'm not privy to the reasons why a custom format may be needed), developing a pseudo-ODBC driver or a server process that mimics the wire protocol of SQL Server (TDS, or Tabular Data Stream) seems like a whole lot of work. The time you spend developing, debugging, and then maintaining such a construct seems way more than what it would take to convert your data to use a database.

If the clients expect a database, then give 'em a database.

That being said, if a database just isn't going to work for you, there are some open source projects you may be able to look at to "borrow" some code - FreeTDS (though that's mainly for Unix/Linux programs that need to access a SQL Server database; and it's in C), unixODBC is an ODBC driver/manager developed in C.

Since you mentioned C# (probably running on Windows), there is a free edition of SQL Server 2008 (Express Edition) - it has some limitations, but it may be something you can try out.

Check this link out http://www.thefreecountry.com/sourcecode/database.shtml for a list of database projects where source may be available.

Good luck!

kvprajapati commented: Good suggestion! +11
mcriscolo 47 Posting Whiz in Training

Use the "CompareTo()" method of the string class. It compares two strings and returns an integer, thusly:

int iCmp = Text[i].CompareTo(Text[i+1]);
if (iCmp < 0)
{
    // Text[i] is "less than" Text[i+1]
}
else if (iCmp > 0)
{
    // Text[i] is "greater than" Text[i+1];
}
else
{
    // Strings are equal
}
mcriscolo 47 Posting Whiz in Training

If it's a Windows Forms app, yes, you can use the Timer object and set the "Interval" property to the desired value, in milliseconds, then call the "Start()" method to start the timer. It will fire the "Tick" method when the interval is reached. From there, you can call any method you like.

If you want to do it all in code, you can use the System.Threading.Timer object. Plenty of examples on the web of how to use that facility, but generally:

Timer myTimer;

// myTimerCallBack - method to call
// someData - blob of data that will get passed to the callback (can be null)
// timeBeforeFirstExec (in milliseconds)  - time before the first time the timer fires
// period (in milliseconds) - recurring interval to fire the timer
myTimer = new Timer(myTimerCallback, someData, timeBeforeFirstExec, period);

public void myTimerCallback(Object obj)
{
    // obj is the "someData" from the call, above
    // Do timer stuff
}

Hope this helps.

mcriscolo 47 Posting Whiz in Training

Good point, you can specify an IP address for the server manually (like was done in the example), or, you can use this syntax:

m_IpEndPointLocal = new IPEndPoint(IPAddress.Any, 5000);

This would cause the default adapter to be used. To your point, if your machine has more than one network adapter, then by specifying the IP address manually, you can "nail down" the socket to a specific adapter.

mcriscolo 47 Posting Whiz in Training

Yep, that's pretty much it.

mcriscolo 47 Posting Whiz in Training

Well, first, is this program the client or the server? To really run it with two processes, you'll want one program to be the client, and another to be the server.

The server program should execute the Bind, Listen and Accept; while the client program executes the Connect method to connect to the server program. You appear to be doing both in the same program. You can actually do that...

In the server program, you need a local Socket object to perform the Bind and Listen. You also perform the Accept (this is where the server "comes alive" when a remote client connects to it), and the return value from the Accept is *another* socket - the socket to the remote client that just connected. The original socket can then go back to the Listen and wait for another client to connect.

When you have the programs separated, execute the server program first, then execute the client. If coded correctly, the client will connect up and you will be able to pass data back and forth.

Client:

m_IpEndPointForeign = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);

m_SocketForeign = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
m_SocketForeign.Connect(m_IpEndPointForeign);

m_Stream = new NetworkStream(m_SocketForeign);

// Read & Write operations
m_Stream.Write(...);  // Implementation left to you...

m_Stream.Close();
m_SocketForeign.Shutdown(SocketShutdown.Both);
m_SocketForeign.Close();

Server:

m_IpEndPointLocal = new IPEndPoint(IPAddress.Parse("127.0.0.1"), 5000);

m_SocketLocal = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

m_SocketLocal.Bind(m_IpEndPointLocal);
m_SocketLocal.Listen(10);
Socket m_SocketClient = m_SocketLocal.Accept();

m_Stream = new NetworkStream(m_SocketClient);

// Read & Write operations
m_Stream.Read();   // Actual Read() implementation left to coder...

m_Stream.Close();
m_SocketClient.Shutdown(SocketShutdown.Both); …
mcriscolo 47 Posting Whiz in Training

In your case, you haven't done anything with the IPEndPoint instance, so it depends.

If you want to connect to a remote client (the rest of your code appears as such), you need to issue the "Connect" call from the socket, using the IPEndPoint instance:

m_socket.Connect(m_IpEndPoint);

right after line 3 in your post (of course, you will also put this into a try/catch block in case of exceptions). This will connect your program to the end point described by host IP "127.0.0.71", on port "5000" (which answers your question - in this case, it's a foreign - or remote - address).

Now, the IPEndPoint can refer to a local address and port, if you were to do something like this, after line 3 in your code:

m_socket.Bind(m_IpEndPoint);
m_socket.Listen(10);
Socket m_client = m_socket.Accept();

assuming your machine's IP address is "127.0.0.71", this code would set up a listen on port 5000 so other programs could establish a connection to this process (again, you will enclose this code in a try/catch block to grab any exceptions). You would have to change the rest of your code to use "m_client", as this will be the object pointing to the socket a remote client would actually be "attached" to, for you to perform your reads/writes.

mcriscolo 47 Posting Whiz in Training

A couple of things: first, you are mixing your class definition and method implementations together. You need to separate these into a header file for the class definition, and a code file for the method implementations. A short example (using your "booking" class):

New booking.h file:

#include <string>
using namespace std;
class booking
{
public:
booking(); /* constructor */
float calTicket(int numpass, string ctype);
};

New booking.cpp file:

#include "booking.h"

float booking::calTicket(int numpass, string ctype)
{
// Stuff the method is supposed to do...
}

Once you have that all separated, you should be a lot better off (code will be much more readable, too). Also, you don't need the "Friend" declarations. In your code, you just need to include the proper header, then just declare an instance of the class you want to use.

mcriscolo 47 Posting Whiz in Training

Glad I could help (though I'm confused about the error; I pasted that code directly from my project..)

As far as 3 text boxes are concerned, you'll have to manage them yourself. If you change the example to use textboxes instead of labels (assuming the text boxes are named "txtHour", "txtMinute", "txtSecond"), the code in the timer_Tick routine would look something like:

int iHour = Convert::ToInt32(txtHour->Text);
int iMinute = Convert::ToInt32(txtMinute->Text);
int iSecond = Convert::ToInt32(txtSecond->Text);
iSecond--;
if (iSecond == -1)
{[INDENT]iSecond = 59;
iMinute--;
if (iMinute == -1)
{[INDENT]iMinute = 59;
iHour--;
if (iHour == -1)
{[INDENT]// Ending condition - turn off the timer
iHour = 0;
iMinute = 0;
iSecond = 0;
timer1->Enabled = false;[/INDENT]
}[/INDENT]
}[/INDENT]}
txtHour->Text = iHour.ToString();
txtMinute->Text = iMinute.ToString();
txtSecond->Text = iSecond.ToString();

Note that once you start letting users input the values, you will have to edit/validate them to ensure they don't enter trash characters - in the above case, the "ToInt32" functions will dump if you hand them trash. Also, you'll want to make sure they enter valid values, such as limiting the minutes and seconds to a range of 0-59.

Let me know if you have any more questions.

Wiki_Tiki commented: Helped extremely well with making a timer. Explained code, gave understandable snippets. +1