Duoas 1,025 Postaholic Featured Poster

That was just an example function I created. I expected that you would take the code you needed from it and put it in your own function.

I don't think that TTextBox::Text takes a std::string, does it? You might have to say textBox1->Text = found.c_str(); Hope this helps.

zandiago commented: congrats on featured poster +6
Duoas 1,025 Postaholic Featured Poster

If all you want is teletype output (like you get on the console, without any fancy graphics or fonts or etc) you can open the PRN or LPT1 device:

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

int main()
  {
  ofstream printer( "prn" );

  if (!printer) 
    {
    cout << "fooey!\n";
    return 1;
    }

  printer << "Hello world!\n";

  printer.close();
  return 0;
  }

Most PC printers that I know of can handle simple TTY output of this kind. If you open in binary mode you can also send printer control codes (specific to your printer) to program it.

Have fun!

Alex Edwards commented: Great post, and sorry for giving you crap when I first joined. +1
scream2ice commented: thnx +1
Duoas 1,025 Postaholic Featured Poster

Probably not. LC3 only exists in textbooks and moreover, people who volunteer here don't want to do your homework for you.

Give it an honest effort and we will help as you go along.

Salem commented: Damn fine answer! +18
Duoas 1,025 Postaholic Featured Poster

A char is guaranteed to contain 8 bits, at least. (And unless you are playing with really old hardware, like ancient vaxen, a byte is also 8 bits.) But the compiler is not required to store individual chars in 8-bit entities.

So, yes, that's what I meant.

@zoner7
Don't modify cout. Just write a routine to do stuff for you.

I'm writing a Sudoku solver too... :)

The basic cell type can overload the shift operators for I/O:

struct cell_t
  {
  int value;
  // Whatever else I store in a single cell goes here
  };

std::istream& operator >> ( std::istream& ins, cell_t& cell )
  {
  // Get a cell. For example, if each cell is just one char, '1'..'9' and ' ':
  int c = ins.get();
  if (std::isdigit( c ) and (c != '0')) cell.value = c -'0';
  else                                  cell.value = -1;
  return ins;
  }

std::ostream& operator << ( std::ostream& outs, const cell_t& cell )
  {
  // This is the same as Ed's PrintValue() function,
  // with just a little extra error checking...
  if ((cell.value %10) == cell.value) outs << (char)(cell.value +'0');
  else                                outs << ' ';
  return outs;
  }

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Google "linked list".

I presume each node represents a single atom?

Duoas 1,025 Postaholic Featured Poster

You'll want to play with MASM32. It has everything you need.

Good luck!

Duoas 1,025 Postaholic Featured Poster

Actually it does have it backwards... foo = [B]this[/B]->foo; != [B]this[/B]->foo = foo; ?

Ancient Dragon commented: you are right, I should have seen that too +30
Duoas 1,025 Postaholic Featured Poster

Depending on how the data is packed.

If it is packed (MSB...LSB) ARGB then

int alpha = (color >> (3 * 8)) & 0xFF;
int red   = (color >> (2 * 8)) & 0xFF;
int green = (color >> (1 * 8)) & 0xFF;
int blue  = (color >> (0 * 8)) & 0xFF;

If it is packed in the Windows order: ABGR

int alpha = (color >> (3 * 8)) & 0xFF;
int blue  = (color >> (2 * 8)) & 0xFF;
int green = (color >> (1 * 8)) & 0xFF;
int red   = (color >> (0 * 8)) & 0xFF;

etc.

You can put these into a function for each component.

Or better yet, an ARGB_t class. You might find my response in this thread at cplusplus.com useful for some ideas. (It would be very simple to extend the RGB_t class to an ARGB_t or ABGR_t or whatever you need class.)

Hope this helps.

VernonDozier commented: Great link. +3
Duoas 1,025 Postaholic Featured Poster

There are only a couple that I'd recommend.

First, straight from esr himself:
http://web.cs.mun.ca/~rod/ncurses/ncurses.html

And another very good one, replete with great examples:
http://tldp.org/HOWTO/NCURSES-Programming-HOWTO/

PDCurses is really a port of NCurses for non-POSIX platforms like Windows and the Amiga and the like. There are a few differences but those generally stem from really unportable stuff where one or the other will explicitly say YRMV.

Have fun! (And be sure to post if you get lost. A few of us here know our way around ncurses pretty well.)

Ancient Dragon commented: nice links to curses lib and tutorials :) +29
Duoas 1,025 Postaholic Featured Poster

I think you are kind of close, but you need to be careful about a couple of things.

The first problem is that the variable lookahead is local to lexan(), so your compiler should be complaining about lines 11, 12, 14, 23, 27, etc.

The second problem is that you are testing conditions too many times. Remember, match( t ) will validate t and return the next "lookahead" or error.

This second problem comes from how match() returns... It is possible for it to not match an item and for that to be a valid mismatch. Since it always complains (with error()) if the match is not made, you have had to put extra code in AA() et.al.

Finally, you have mixed a couple of concepts, methinks. lexan() should be the function to call to check the language SS and return whether or not it matches.

To help, these are my suggestions:

  1. lexan() should call SS(), which should call AA(), do its own test against 'a', call BB(), and do its own test against 'b', and return success or failure.
  2. char lookahead should remain a local variable in lexan(), but it should also be passed as a reference argument to match(), SS(), AA(), and BB() (in addition to current arguments). For example: [B]int[/B] match( [B]char[/B] t, [B]char[/B]* thelookahead ); and called with match( 'a', &lookahead )
  3. match() should return either success or failure. If it succeeded, the lookahead variable should be modified …
Salem commented: Excellent effort, despite the poor state of the original post. +17
Duoas 1,025 Postaholic Featured Poster

That's because you are actually creating two different types of structure.

In C and C++, arrays are something of a mixed bag.

When you declare [B]int[/B] a[ 10 ][ 5 ]; What is actually allocated is [B]int[/B] a[ 10 * 5 ]; And when you access: a[ 4 ][ 3 ] what that translates to is: *(a + (4 * 10) + 3) In contrast, an array of pointers to arrays is an entirely different thing: [B]int[/B] *a[ 10 ] In C and C++ a pointer can be dereferenced as if it were an array, but whereas before only a calculated offset and a single dereference was needed to access an element, now two dereferences are needed: a[ 4 ][ 3 ] is the same as: *(a[ 4 ] + 3) which is the same as: *(*(a + 4) + 3) Whew.

So to allocate a contiguous memory space you need to multiply the dimensions to get the total amount of memory, then do the offset calculations yourself

int *a = new int[ 10 * 5 ]  // or int *a = new int[ 10 ][ 5 ]

int& elt( int *a, int rows, int cols, int row, int col )
  {
  if ((row >= rows) or (col >= cols)) throw 1;
  return *(a + (row * cols) + col);
  }

elt( a, 10, 5, 4, 3 ) = 42;
cout << elt( a, 10, 5, 4, 3 );

Hope this helps.

[edit] Too slow again...

jephthah commented: instructive +3
VernonDozier commented: Thank you for the helpful posts. +3
Duoas 1,025 Postaholic Featured Poster

Wow, I'm really surprised to see AD so boiled up over something like goto.

(I thought you were cool man.... *sniff* --- heh heh heh)

Actually, you'll notice that goto still exists in many modern languages. Why? Because it has its place. A rare one, but still useful.

All the fanaticism against it began as a backlash against poorly programmed code (often cases of "spaghetti code") and lack of structure.

Remember that underneath the pretty flowers all flow constructs are managed with gotos (or in the proper terminology, "jump" or "branch" opcodes). The purpose of higher-level constructs isn't to abolish the goto, but rather to provide a better abstraction as an end to better organized and more maintainable code, and to assist the programmer in managing closures/frames.

The problem with attacking the tool instead of the tooler (besides being "outside the box" --i.e. code-worded propaganda) is that the underlying problem is blissfully forgotten and remains undiagnosed by multitudes of programmers in their programming practices.

As a matter of interest, here is a 1996 study on coding practices as relates to the evils of goto:
http://citeseer.ist.psu.edu/148906.html
Notice that the study discovered that it doesn't take a goto to make really bad code, even spaghetti code.

Few people here have ever actually seen real spaghetti code, and therefore, predictably, lack the recondite profundity as to why it is wrong and to the depths of its evil. Anyone who has (and who doesn't …

tesuji commented: Very good essay +1
Duoas 1,025 Postaholic Featured Poster

Your loop encompasses both the menu and the selector, as:

do {
  display_menu();
  select_option();
while (!done);

So if the option is bad, the menu gets displayed again anyway.

What you'd probably like instead is something that catches itself. You can do it several ways, but another loop will probably do just fine.

do {
  display_menu();
  do {
    select_option();
  while (invalid_option);
while (!done)

Hope this helps.

Run.[it] commented: Thanks again mate! +1
Duoas 1,025 Postaholic Featured Poster

Yes, OK. Your routine should terminate when you hit one, not -1. (You've got it right for the last three clauses of your code -- the stuff handling the positive numbers.) The trick is what happens when things go negative.

It might help to visualize what is going on a couple of times.
The routine is (should be) defined to recurse as follows (what you have for positive numbers):

(mult a b) = (+ a (mult a (- b 1)))
(mult a 1) = a
(mult a 0) = 0

So for an example:

(mult 2 5)
= (+ 2 (mult 2 4))
= (+ 2 (+ 2 (mult 2 3)))
= (+ 2 (+ 2 (+ 2 (mult 2 2))))
= (+ 2 (+ 2 (+ 2 (+ 2 (mult 2 1)))))
= (+ 2 (+ 2 (+ 2 (+ 2 2))))
= (+ 2 (+ 2 (+ 2 4)))
= (+ 2 (+ 2 6))
= (+ 2 8)
= 10

And another:

(mult -2 5)
= (+ -2 (mult -2 4))
= (+ -2 (+ -2 (mult -2 3)))
= (+ -2 (+ -2 (+ -2 (mult -2 2))))
= (+ -2 (+ -2 (+ -2 (+ -2 (mult -2 1)))))
= (+ -2 (+ -2 (+ -2 (+ -2 -2))))
= (+ -2 (+ -2 (+ -2 -4)))
= (+ -2 (+ -2 -6))
= (+ -2 -8)
= -10

So far, so good. But what if b

Gagless commented: Great. Very insightful. +1
Duoas 1,025 Postaholic Featured Poster

You are correct. The process file table and the current working directory are not modified by exec(), so the new executable inherits it all.

Duoas 1,025 Postaholic Featured Poster

Of course, once you get the whole line, you'll want to parse it using a stringstream and getline() again...

#include <algorithm>
#include <iostream>
#include <sstream>
#include <string>

using namespace std;

char morse_decode( string letter )
  {
  ...
  }

bool is_multiple_spaces( char a, char b )
  {
  return (a == ' ') && (b == ' ');
  }

int main()
  {
  string line, letter, message;

  cout << "Please enter your message. Press ENTER twice to finish." << endl;

  while (getline( cin, line ))
    {
    if (line.empty()) break;
    stringstream letters( line );
    while (getline( letters, letter, ' ' ))
      if (letter.empty()) message += ' ';
      else message += morse_decode( letter );
    message += ' ';
    }

  // Remove extra spaces
  unique( message.begin(), message.end(), is_multiple_spaces );

  cout << "The decoded message is:\n"
       << message
       << endl;

  return 0;
  }

Hope this helps.

Nick Evan commented: Nice :) +5
Duoas 1,025 Postaholic Featured Poster

IMO, interfacing with the user is one of those things that needs to be absolutely bullet-proof.

There are two things to keep in mind here:

1. How does the user expect to interact with your program.
2. How does your program react to insane responses.

Answer 1: For console applications, users expect to have to press ENTER after every input. Just expect it.

Answer 2: Don't crash or do something regrettable.

For example, with just cin.get() (a simple solution for homework, etc), what if the user presses A, N, Y. (That is not a joke. It actually happens, and has had serious consequences!)

So, for this kind of thing, when you are writing production code I always advocate the ignore() method. There is an example of it in the first link VernonDozier gave you.

Keep in mind that if you have been using cin >> foo; up till then, you will have to first empty the input with an additional ignore()...

Hope this helps.

VernonDozier commented: Good post. +3
Duoas 1,025 Postaholic Featured Poster

Argh.

OK. You are parsing a standard CSV file, with a header record.

Handle it thus:

#include <algorithm>  // for min() and max()
#include <fstream>
#include <sstream>
#include <string>

ifstream csvfile( "foo.csv" );
if (!csvfile)
  {
  complain();
  return;
  }

string target_date = "07/01/1999";

string record;

// skip the header record
getline( csvfile, record );

// examine all remaining records
unsigned record_number = 0;
while (getline( csvfile, record ))
  {
  stringstream fields( record );
  string field;
  for (unsigned field_number = 0; getline( fields, field, ',' ); field_number++)
    switch (field_number)
      {
      case 0:
        if (field != target_date) goto l_next_record; // valid!
        break;

      case 1:  // we don't care what hour for avg, min, or max of anything
        break;

      case 2:
        // Convert the field to a number (complain if it isn't)
        int temperature;
        if (!(stringstream( field ) >> temperature))
          {
          complain();
          break;
          }
        // If this is the very first record, initialize our min and max
        if (record_number == 0)
          {
          min_temperature := temperature;
          max_temperature := temperature;
          }
        min_temperature := min( min_temperature, temperature );
        max_temperature := max( max_temperature, temperature );
        break;

      case ...
      }
  l_next_record:
  record_number++;
  }

csvfile.close();

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Hi!

The following is also a very illuminating document.
Incompatibilities Between ISO C and ISO C++

Salem commented: Another excellent link +17
hammerhead commented: Excellent link thanks +3
Duoas 1,025 Postaholic Featured Poster

Heh heh heh....

You're going to love this:

#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>

using namespace std;

int main()
  {
  string filename;
  cout << "Enter the numbers filename> ";
  getline( cin, filename );

  ifstream file( filename.c_str() );
  if (!file)
    {
    cout << "Invalid filename.\n";
    return EXIT_FAILURE;
    }

  istream_iterator<int> max_begin( file ), max_end;
  istream_iterator<int> min_begin( file ), min_end;

  int max = *max_element( max_begin, max_end );

  file.clear();
  file.seekg( 0 );

  int min = *min_element( min_begin, min_end );

  cout << "The largest number in the file is "  << max << endl;
  cout << "The smallest number in the file is " << min << endl;

  file.close();

  return EXIT_SUCCESS;
  }

Enjoy!

[edit] Oh yeah, here is my numbers file:

12
-7
108
43
Duoas 1,025 Postaholic Featured Poster

You are screwing-up your gcount() by using ignore(). Get the count first, then ignore.

Hope this helps.

Run.[it] commented: Your da man! Safe +1
Duoas 1,025 Postaholic Featured Poster

You should have gotten a runtime exception for trying it...

Anyway, Windows apps don't have consoles by default. At the beginning of your program you'll have to AllocConsole(); then... you'll have to hook the standard streams up to the console:
http://www.halcyon.com/~ast/dload/guicon.htm
(yoinks!)
Its easier than it looks.

Have fun.

VernonDozier commented: Good link. +2
Duoas 1,025 Postaholic Featured Poster

Recursion and iteration are two sides of the same coin.

The difference is, in C++, you have the potential of blowing your stack. So on Windows, if you have more than sizeof(Available RAM + Swap Space)/sizeof(Stack Frame) permutations, you'll crash your computer. Even if you don't get that high though... once you exceed RAM size your program will begin to slow considerably.

All that aside, recursion keeps state ("remembers" things) by passing and returning values.

As a simple example, the Fibonacci sequence is defined as:
F(0) = 0
F(1) = 1
F(n) = F(n-1) + F(n-2)

A simple iterative solution might look something like

unsigned long long i_fib( unsigned n )
  {
  switch (n)
    {
    case 0: return 0;
    case 1: return 1;
    default:
      unsigned long long f_of_n_minus_1 = 1;
      unsigned long long f_of_n_minus_2 = 0;
      unsigned long long f_of_n         = 1;
      for (; n > 1; n--)
        {
        f_of_n = f_of_n_minus_1 + f_of_n_minus_2;
        f_of_n_minus_2 = f_of_n_minus_1;
        f_of_n_minus_1 = f_of_n;
        }
      return f_of_n;
    }
  }

To make that recursive, we have to identify our state variables: F(n-1), F(n-2), F(n), and of course, n.
The current sum is dependent on the previous iterations, so that should be a return value, while everything else is dependent on 'n'.

So, that same routine in recursion would be

unsigned long long r_fib( unsigned n )
  {
  switch (n) 
    {
    case 0: return 0;
    case 1: return 1;
    default: return r_fib(n-1) + r_fib(n-2)
    } …
Duoas 1,025 Postaholic Featured Poster

Start here.

When you hit the wall post your code and we'll help further.

Duoas 1,025 Postaholic Featured Poster

Alright! :)

Sorry for the delay. There were a few more corner cases than I thought there would be when I started this. But anyway, here you go. Hope you find it useful.

The algorithm presumes that the dates in your file are more or less linearly distributed. If this is not the case by more than a standard deviation, open "datefile.cpp" and comment out the line #define LINEAR_DISTRIBUTION Sorry for the boilerplate, but companies get nervous without it. Basically it just says you can do anything you like with the files except claim anyone but I wrote the original versions or alter the boilerplate... (and excludes me from legal responsibility if someone manages to destroy something with it).

The file "a.cc" is what I used to test the datefile algorithm. You don't need it, but I've attached it anyway so you can play with it if you like. Its messy though...

Let me know if anything goes horribly wrong. ;)

So, here's a quick primer:

#include <iostream>
#include <fstream>

#include "datefile.hpp"

using namespace std;
using namespace datefile;

int main()
  {
  ifstream megafile( ... );

  time_t date = string_to_date( "4/28/1974" );
  streampos linepos = find_date( megafile, date );

  if (megafile)  // or (!megafile.eof())
    {
    string line;
    getline( megafile.seekg( linepos ), line );
    cout << "Found the line> " << line << endl;
    }
  else 
    {
    megafile.clear();
    cout << "No such date found.\n";
    }

  ...
  megafile.close();
  return 0;
  }

Enjoy! :)


Hmm. …

jephthah commented: very nice code +1
Duoas 1,025 Postaholic Featured Poster

The problem is exactly what it is saying.
For example, you have a procedure prototyped as: [B]void[/B] GetTemperatures ([B]int[/B] Temperatures[], [B]int[/B] NumTemperatures); ...which clearly states that it requires two arguments.

but in main() you don't specify any arguments: GetTemperatures (); You must specify the arguments: GetTemperatures( HourlyTemperaturs, NumTemperatures ); I think the problem is that you are confusing multiple variables with the same name as a single variable. For example:

int answer = 42;

void print( int answer )
  {
  cout << "The answer is " << answer << endl;
  }

In this example, there are two variables named 'answer'. The first is a global variable and it has the value 42. The second is a temporary variable local to print(). In other words, it exists inside the function but nowhere else. Since it has the same name as the global variable, the local variable takes precedence (meaning you cannot use the global variable inside the function).

Hope this helps.

PS. You could use the global if you give its full name: cout << [B]::answer[/B] << endl;

Metalsiege commented: Key to helping me solve my problem. Thanks! +1
Duoas 1,025 Postaholic Featured Poster

Link. Check out my post at the bottom.

(Sorry, I've got lazy fingers today.)

Ancient Dragon commented: Great solution -- I hadn't thought of that. :) +24
Duoas 1,025 Postaholic Featured Poster

"Better" is a subjective word. If you mean in terms of "easier to use complicated code with fewer errors and improved error handling" then OOP is better.

Objects encapsulate information. That is to say, they don't just define related information, but they provide ways to manipulate that information.

One point of note: classes actually make life just a little bit more complicated for the people writing the class. The reward is that classes make life a breeze for people using the class. The tradeoff, however, is slim, since you'd generally have to write all the stuff that gets put in the class anyway, and when in a class it is much more coherent and easy to read.

The Before Way
For example, a non-object oriented thing is an array:

int xs[] = { 2, 3, 5, 7, 11, 13, 17, 19 };

If you want to print this array you have to know something "magical" about it: its length. The magical thing is that, given the array, there is no way to determine its length.

(Now, before those of you in-the-know respond with length = sizeof( xs ) / sizeof( x[0] ) I'll remind you that that only works because the compiler knows how long xs is. That only works in specific cases... when you are executing the program you cannot depend on the compiler's help.)

Suppose, for example, we have a little function to print that array:

void print_ints( int xs[] …
VernonDozier commented: Good writeup +1
Duoas 1,025 Postaholic Featured Poster

Hmm, that's right. (Stupid grid controls are poorly designed... they give everyone and everything grief...)

You'll have to help it along. This is what I did. (I used a tStringGrid to test.)

Set DragMode to dmManual. (Sorry about that earlier.)
Set Options.goRangeSelect to FALSE.

procedure Form1.stringGrid1MouseMove(
  sender: tObject;
  shift:  tShiftState;
  x, y:   integer
  );
  begin
  // If we should be dragging, then start
  if ssLeft in shift then stringGrid1.beginDrag( TRUE )
  end;

I also used OnStartDrag to create a custom tDragObject (which you'll probably want to do also...). The source argument to OnDragOver and OnDragDrop is the object you create.

My custom object looked like this:

type
  TMyDragObject = class( TDragObject )
    // Tracks which cell we are dragging, so when we drop
    // it we can append its contents to the target cell's text.
  public
    sCol, sRow: integer;  // start col, row
    valid:      boolean;  // convenience
    constructor create( aCol, aRow: integer; aValid: boolean );
  end;

constructor TMyDragObject.create(
  aCol, aRow: integer;
  aValid:     boolean
  );
  begin
  inherited create;
  sCol  := aCol;
  sRow  := aRow;
  valid := aValid
  end;

And the way I used it:

procedure TForm1.StringGrid1DblClick( Sender: TObject );
  begin
  // Double-clicks just append an X to the cell's text.
  with stringgrid1 do
    cells[ col, row ] := cells[ col, row ] +'X';
  end;

procedure TForm1.StringGrid1DragDrop(
  Sender, Source: TObject;
  X,      Y:      Integer
  );
  var dCol, dRow: integer;
  begin
  // Drop the source object onto the cell under the mouse cursor.
  // Note that since I used 'OnDragOver' …
RoryGren commented: Very helpful! Thank you! +1
Duoas 1,025 Postaholic Featured Poster

The first problem this person had is that he did not comment his code very well. The second problem is that his comments don't match his code. The third (and most important) problem is that he did not write down what he was trying to do before doing anything.

For example, on lines 16..18 his comments say, basically, "get integer into $s0". However, what he does is stick the integer in $a0. The very next thing he does is clobber $a0 (and $v0) in order to print promptY, so the integer that the user entered is lost forever.

The commentary might better run like this:

.text

# variables
#  $s0 = X
#  $s1 = Y

main:
	# Ask user to "Enter a number for X: "
	li	$v0,	4
	la	$a0,	promptX
	syscall

	# Get X --> $s0
	li	$v0,	5
	syscall
	move	$s0,	$v0

	...

	# $v0 = exponential( $s0, $s1 )
	move	$a0,	$s0	# see note [1]
	move	$a1,	$s1
	jal	exponential

	# print the result
	move	$a0,	$v0
	li	$v0,	1
	syscall

	# terminate the program
	li	$v0,	10
	syscall

[1] Argument passing conventions
The registers $a0..$a3 are typically used as arguments to functions. The exponential() function takes two arguments, so the first argument is $a0 and the second argument is $a1.

We could design the function to take $s0 and $s1 as arguments, then we wouldn't have to move anything around before jal -ing to the function. However, I chose …

Duoas 1,025 Postaholic Featured Poster

If it is core-dumping you still need to potty-train it.

Google "linked lists" and read more to learn how to fix your problems. (They are all caused by an improperly-coded linked list.)

Also, your setHead() method is very dangerous: you should not have methods that let things outside your class mess around with its private data.

Hope this helps.

WaltP commented: Great imagery!! +11
Duoas 1,025 Postaholic Featured Poster

Between lines 11 and 12 put cin.ignore( numeric_limits<streamsize>::max(), '\n' ); The stream >> operator only reads what you ask it to, and leaves everything else behind in the input buffer. However, whenever dealing with user input you must expect that the user will press the ENTER key after everything you ask him to enter.

getline() reads everything except the ENTER key, stores it in a string, then reads and throws away the ENTER key.

cin >> anything, in contrast, only reads anything, and leaves everything else (including that pesky ENTER key) in the input stream. So the next time you call getline(), it does what it did before, reading '' and sticking it in to a string, then reads the ENTER key and throws it away.

So, after using >> you must explicitly read and throw away that ENTER key so that it isn't still there the next time you try to get input from the user.

Hope this helps.

Roebuc commented: Thank you for explaining it so clearly! +1
Duoas 1,025 Postaholic Featured Poster

The error you have has nothing to do with my code. undefined reference to 'winmain@16' means that you did not define a main function. Which means that you did not use the code I gave you in an application. Go to File -> New -> Windows Application to create a new project, write your forms, etc. and somewhere in there copy in the functions I gave you. Only then can you use them.

The second error is because of the first.

Duoas 1,025 Postaholic Featured Poster

None of the code I posted is a complete program. They are utility functions.

[EDIT] In other words, copy and paste them into your program and use them at the appropriate moment. For example, if you just want the console window to disappear, start your program and either FreeConsole or HideConsole.

Duoas 1,025 Postaholic Featured Poster

There are two basic ways.

First, you could simply FreeConsole to get rid of the console window, then AllocConsole to get a new one.

Better yet though, is to use ShowWindow:

#include <string>
#include <windows.h>

const char STR_CONSOLE_WINDOW_CLASS[] = "ConsoleWindowClass";

std::string GetConsoleTitle() {
  unsigned long length;
  std::string result( 1000, '\0' );
  length = GetConsoleTitle(
    const_cast<char *>( result.c_str() ),
    1000
    );
  result.resize( length );
  return result;
  }

void HideConsole() {
  HWND hConsole = FindWindow(
    STR_CONSOLE_WINDOW_CLASS,
    GetConsoleTitle().c_str()
    );
  ShowWindow( hConsole, SW_HIDE );
  }

void ShowConsole() {
  HWND hConsole = FindWindow(
    STR_CONSOLE_WINDOW_CLASS,
    GetConsoleTitle().c_str()
    );
  ShowWindow( hConsole, SW_SHOW );
  }

Well, that should do it... As usual, I just hacked this in so don't everyone complain too much if it needs a slight tweak to work.

You may want to use SetConsoleCtrlHandler() to keep the user from terminating your application when the console window is closed. A handler might look something like:

BOOL my_console_ctrl_event_handler( DWORD dwCtrlType ) {
  std::cout
    << "\n+-----------------------------------------------+"
    << "\n|  HEY YOU THERE! CLOSING ME ENDS THE PROGRAM!  |"
    << "\n+-----------------------------------------------+"
    << "\n"
    << "\nTo make this window disappear, select"
    << "\nFile -> Hide Console from the main window's menu."
    << std::endl;
  return dwCtrlType == CTRL_CLOSE_EVENT;
  }

(And if you use this message, don't forget to add a "Hide Console" command to the File menu.)

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Don't use void main() .
Always use [B]int[/B] main() .

In "List.h" the Traverse() method is (incorrectly) prototyped as void Traverse( DataType, int& ) . In "List.cpp" it is (correctly) defined as [B]bool[/B] Traverse( DataType, int& ) .

Please don't use leetspeak or other weenie talk. (Be kind to those for whom English is not their first language.)

Hope this helps.

SpS commented: :) +4
Duoas 1,025 Postaholic Featured Poster

So wait, did you get the "undeclared" error fixed (by typing isZero as) bool isZero( term t ) ?

Glad to have been of help.

orangejuice2005 commented: Thanks a lot Duoas! Good looking out +1
Duoas 1,025 Postaholic Featured Poster

Actually, your program has a few I/O errors that I'm sorry to say I didn't catch earlier. I'll list them all here for you though.

Polymain.cpp: line 15
Just as a personal stylistic preference, I'd add a single space after the prompt, as: cout<<"Enter selection> "; This isn't a bug, though. Just style. :)

1. Polymain.cpp: lines 44, 47
User input should generally be done on a line-by-line basis (that is, input an entire line as a string, then parse the string) but C++ lends itself to professors having you learn UI with the >> and << operators of the cin and cout streams. These operators do what they are supposed to do, but a one-sided education in their use produces some very bad and buggy I/O programs.

On the line indicated, you have the user input an integer. That's fine (unless the user inputs, say 'a'). I'll defer lecturing to the optional part at the end of my post and just fix egregious errors here.

After inputting the integer there remains a newline sitting in the input stream. The user had to press ENTER to send the number to the program, so we really do need to remove the newline before continuing. (That way the newline doesn't contaminate more input --which it does in your program, btw.) Best to avoid the possibility of error either way. Change line 44 to read:

cin>>choice;
	  cin.ignore( numeric_limits<streamsize>::max(), '\n' );

The same problem occurs on what …

John A commented: Good work. I'm too lazy to do that much correction. :) +13
Duoas 1,025 Postaholic Featured Poster

The loop belongs in main(), and each time through the loop you need to call output() once.

In the output() method there should not be any loops. I think the assignment would have been more clear had your professor named c1, c2, and c3 as unsigned char c[ 3 ]; So inside output() you can set c[ count ] = x; and count++; Then, if count > 2 you need to encrypt the c[0], c[1], and c[2] (or, as your professor has named them, c1, c2, and c3, and reset count to 0.

Hope this helps.

kylcrow commented: Extremely patient and helpful. Thanks again. +1
Duoas 1,025 Postaholic Featured Poster

Start small and work your way up. For example, you could start with just creating and displaying a polynomial. Then you could add a method to read a polynomial. Then add polynomials. Etc. Each step of the way test it out in main(). Once you are done, you can move the stuff into separate .h and .cpp files.

The introduction of a term class was brilliant! Good job!

I removed the initialize() method (it won't work and you don't need it).
The sort() method is not a constructor.
I've also renamed get_term() to number_of_terms(), as a more descriptive name.
Don't forget to end a struct or class type with a semicolon.

Also, indentation and formatting will help considerably when you read your code. For example:
[code=C++]

//------------------------------------------------
// The stuff that follows would go in your Poly.h
// file when you are done testing it

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

struct term
{
	int co;
	int expo;
};

class Polynomial
{
	friend istream& operator>> (istream& stream, Polynomial& poly);
	friend ostream& operator<< (ostream& stream, Polynomial& poly);

	public:

		// The list of terms in the polynomial
		// (not necessarily ordered)
		vector<term> poly;

		// default constructor
		Polynomial();
		
		// empties the polynomial of all terms
		void reset();

		// sort the terms from the highest to lowest exponent
		void sort();

		// add two polynomials
		Polynomial operator+( const Polynomial& p );

		// returns the number of terms in the polynomial
		int number_of_terms();
};

//------------------------------------------------
// The …
Dukane commented: excellent response +2
orangejuice2005 commented: Thnx for the continued support and patience! +1
Duoas 1,025 Postaholic Featured Poster

In C and C++ the only time it makes a difference is with the increment and decrement operators, which each come in two forms: postfix and prefix.

Here we have an integer: int a = 42; Let's play with it: cout << a << endl; prints 42 cout << ++a + 1 << endl; prints 44 cout << a << endl; prints 43
In this example, a was incremented before the expression was evaluated. (The entire cout statement.) This is prefix: the increment is done first. cout << a << endl; prints 43 cout << a++ + 1 << endl; prints 44 cout << a << endl; prints 44
In this example, a was incremented after the expression was evaluated. This is postfix: the increment is done last.

There is a caveat. For each distinct variable, you cannot use more than one increment or decrement operator in the same statement. Hence: cout << ++a++ << ++a << endl; BAD!
is likely to get you a random number.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

I haven't looked through the QStat sources (and I don't plan to), but if it really is just a plain-vanilla command-line application then you only need to spawn it as a subprocess, and re-route its standard input and output to your application.

Look through the docs for CreateProcess.

Hope this helps.

jonc commented: Thanks for your advice and URL for more info. Much appreciated :) +1
Duoas 1,025 Postaholic Featured Poster

LOTRJ, I just typed that in. THere are bound to be some small mistakes. You are expected to use it to get started in finding the information you need to do this yourself.

The function is sndPlaySound (with a lowercase S at the beginning).

And yes, the std::string needs to be passed as a const char *: hfound = FindResource( NULL, [B]resname.c_str()[/B], "WAVE" ); Hope this helps. Use the Google if you feel stuck, and if that fails come here. I'm not being rude or cruel --this is a skill you absolutely must possess in order to learn to program. (Just like with Blender, you expect people to try a few things before throwing questions at the human dictionaries...)

More often than not I test code that I post here, but I don't plan to build an entire application with resource file just to do something you can... Make sense?

(I am at the limit of my knowledge about using the windows sound subsystem.)

I recommend you find some good references on the net about the things you want to do.
Here's a start:

C++ stuff
simple and uncluttered: http://www.cppreference.com/
complete and detailed: http://www.cplusplus.com/

Windows Waveform Audio http://msdn2.microsoft.com/en-us/library/aa910189.aspx
Windows Multimedia Reference http://technet.microsoft.com/en-us/library/ms712699(VS.85).aspx

Hope this helps.


[EDIT] Ah, you must have found your answers.

Just include <windows.h>
I think that should get you everything you need.

zandiago commented: Congrats on your 1st star!!! Keep it up! +3
Duoas 1,025 Postaholic Featured Poster

No need to cuss at me... :-O

There is something wrong with your windows.h includes. The LoadResource function, according to Microsoft, looks like this: HGLOBAL LoadResource( HMODULE, HRSRC ); In my MinGW (GCC) winbase.h file (which is included by windows.h), that is properly listed as: WINBASEAPI HGLOBAL WINAPI LoadResource(HINSTANCE,HRSRC); Whatever library you are using that says LoadResource takes or returns pointers of any kind, or takes more or less than two arguments, is wrong.

Make sure you have the correct windows headers.

[EDIT] Woot! 1000th post!

WolfPack commented: Congrats on the 1000th post. You are indeed an asset to this forum. +7
Duoas 1,025 Postaholic Featured Poster

Well, I've just glanced over your code, so I'll run through the most obvious errors first, and give some useful suggestions, and see if that doesn't help.

1. main returns int.

2. You have not very well documented your code. In fact, it took me until I was reading through the aMpyC() and addTo() functions that I finally 'got it' that eArray is a bignum.

Also, your variable names need some work. I will not address that below, but poorly named variables are an indication of a nebulous understanding of what they do. This is what you are struggling with mostly at the moment-- making the structure match what you think it ought to be doing.

So, with that in mind, lets fix the very first part with some proper documentation.

// eArray
//
// The eArray class represents an unsigned
// integer of arbitrary precision. You can
// set it to a number, add a number to it,
// multiply it by a number, and print its value.
//
class eArray {
  ...
  };

3. You are forcibly using too much memory. Each element of data[] should represent only one digit of the number. (Yes it is possible to use all the bits in each element, but it is tricky and you are trying to do it the simple way anyway, so we'll stick with that.)

Also, you will likely save yourself some space if you use bytes instead of machine …

jaepi commented: very very very detailed and very very very helpful :D +2
Duoas 1,025 Postaholic Featured Poster

Vegaseat, you really ought to try to give people an idea instead of just writing code for them. People learn better when they can solve the problem themselves. A little direction --a nudge this way or that-- is all that is needed. (It is more satisfying both to the OP and to you who helped.)

Line 10: Never, ever, use input to get user input. That is just plain dangerous. It should read: celsius_list.append([B]raw_input[/B](prompt)) Hope this helps.

[EDIT] Just noticed (again) that you're a mod. I'm probably preaching to the choir. Sorry.

Duoas 1,025 Postaholic Featured Poster

Hey there. I just wanted to update my answer a little (I've looked it up to be sure).

It is actually a little easier than I thought it would be. Make your RC file

whizzing_fizzbang WAVE "whizzfizz.wav"
pop_rockets       WAVE "poprockets.wav"

etc.

Here's a little snippit of how to use it:

#include <string>
#include <windows.h>

...

void play_wav_resource( std::string resname, bool is_loop ) {
  HANDLE hfound, hsound;
  LPVOID data;

  hfound = FindResource( NULL, resname, "WAVE" );
  if (hfound != 0) {

    hsound = LoadResource( NULL, hfound );
    if (hsound != 0) {
      data = LockResource( hsound );

      if (data != NULL) SndPlaySound(
        (char *)data,
        SND_ASYNC | SND_MEMORY | (is_loop ? SND_LOOP : 0)
        );

      UnlockResource( hsound );
      }

    }
  FreeResource( hfound );
  }

void stop_wave_sound() {
  SndPlaySound( NULL, 0 );
  }

This code snippit is from this page on embedding resources (in Delphi). You can learn more stuff there. (The About.com pages have a lot of great stuff like this.)

Keep in mind that you don't actually have to free the resource until you are done with it. This routine does so because it uses the resource then it is done with it. Hence, the resource is re-loaded each time it is needed. If you plan to use the sound often, it would be better to load it once, then just use it as oft as you want. (You don't ever have to actually free it explicitly, since Windows will do that …

Duoas 1,025 Postaholic Featured Poster

It works just fine.

Make sure your RC file looks something like

MySound1 RCDATA "spiff.wav"
MySound2 RCDATA "bloink.wav"

etc.

Compile it to a resource file (*.res) using whatever program you have to do that (like windres.exe that comes with GNU stuff).

Inside your program, you'll need to use the windows API to access the resources.
First, get the resource with HRSRC MySound1_rsrc = FindResource( NULL, "MySound1", RT_RCDATA ); Then, load the resource with HANDLE MySound1_handle = LoadResource( NULL, MySound1_rsrc ); If either of these functions fail the return value is 0. You do not need to call FreeResource on the MySound1_handle at any time (but you can if you are sure you are done with it).
(For those of you who are paying attention, the returned handle is not global.)

Now you have a Windows handle you can pass to ReadFile.

Hope this helps.

Ancient Dragon commented: Excellent info! :) +21
Duoas 1,025 Postaholic Featured Poster

For option number two, google Resource Hacker. That'll do it.

Duoas 1,025 Postaholic Featured Poster

Don't worry about it.

I'm not sure exactly why the problem occurs either. But the type was being mangled incorrectly without the explicit cast.

I added a tellg() statement after the seekg() to see where the fp was, and I was getting some really large number, which showed me that it was not seeking from eof properly. So I checked the type of sizeof() against what the function wanted in order to find the error. I think that the problem is one of those "gotchas" from using templated objects.

Alas.


For the namespace problem, it sounds like you have already used something like using namespace fooey; or using namespace std; or one of the headers you imported did it for you, so if you try to say using namespace std; again it looks in the local namespace and says, basically, "std doesn't have any namespace called 'std'".

You can fix it by explicitly referring to the global namespace: stfile.seekg( -([B]::[/B]std::streamoff(sizeof(item))), [B]::[/B]ios::end ); or by (if you are using std) just stfile.seekg( -(streamoff(sizeof(item))), ios::end ); That could fix it. (Of course, your solution, by using an intermediate/temporary int works as well [obviously], because the compiler could properly promote the int type to streamoff.)


For the binary stuff, try running your program without the binary I/O and entering the number 10 in answer to either price and/or stock. You'll see that it doesn't write 40 bytes, but 41 or 42. This is …

Karkaroff commented: thanks! that clears things a bit +1