Duoas 1,025 Postaholic Featured Poster
Duoas 1,025 Postaholic Featured Poster

It looks like you haven't updated one of your files properly.

execprocess.cpp

// execprocess.cpp

#include "execprocess.hpp"

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles,
  BOOL is_show_window
  ) {
  HANDLE              result = INVALID_HANDLE_VALUE;
  #ifdef UNICODE
  std::wstring        cmdline;
  #else
  std::string         cmdline;
  #endif
  STARTUPINFO         startup_information = {0};
  PROCESS_INFORMATION process_information = {0};

  startup_information.cb          = sizeof( STARTUPINFO );
  startup_information.dwFlags     = STARTF_USESHOWWINDOW;
  startup_information.wShowWindow = is_show_window ? SW_SHOW : SW_HIDE;  

  #ifdef UNICODE
  cmdline = std::wstring( 1, '\"' ) +arg0 +L"\" " +args;
  #else
  cmdline = std::string( 1, '\"' ) +arg0 +"\" " +args;
  #endif

  if (CreateProcess(
    arg0.c_str(),           // full path of program to execute
    #ifdef UNICODE
    const_cast<wchar_t*>(
    #else
    const_cast<char*>(
    #endif
          cmdline.c_str()), // complete command line
    NULL,                   // no process attribute handle inheritance
    NULL,                   // no thread attribute handle inheritance
    is_inherit_handles,     // such as stdin, etc.
    NORMAL_PRIORITY_CLASS,  // 
    NULL,                   // use the parent's environment
    NULL,                   // use the parent's current working directory
    &startup_information,   // (all defaults)
    &process_information    // resulting process info
    ))
    result = process_information.hProcess;

  CloseHandle( process_information.hThread );
  return result;
  }

// end execprocess.cpp

execprocess.hpp

// execprocess.hpp

#ifndef EXECPROCESS_HPP
#define EXECPROCESS_HPP

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

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles = TRUE,
  BOOL is_show_window     = TRUE
  );

#endif

// end execprocess.hpp

In your program:

#include <windows.h>
#include "execprocess.hpp"

...

HANDLE child_pid = ExecProcess( "fooey.exe", "/a quux", TRUE, FALSE );
if (child_pid != INVALID_HANDLE_VALUE)
  WaitForSingleObject( child_pid, INFINITE ); …
Duoas 1,025 Postaholic Featured Poster

Recursion gets people because it is something new --which translates to forgetting all the stuff you already know.

In order to determine the maximum number in a list, you need three things:
1. the list
2. the current maximum value
3. something to compare each element of the list with the current maximum

If I were to do it iteratively, I'd write something like

int max_in_list( int a[], int size )
  {
  int max = a[ 0 ];
  for (int n = 1; n < size; n++)
    if (a[ n ] > max) max = a[ n ];
  return max;
  }

(This presumes that a[] contains at least one element.)

To make it recursive, you have to do the same kind of thing. Or in other words, you have to remember the same information across every function call that you remember each time you go through the loop:
1. the current index into the array
2. the number of elements in the array
3. the current maximum value
And each time the function returns it should give the new information that we get out of the loop:
1. the new maximum value

You are very close. Just watch your fenceposts (for an n-element array, elements are numbered 0..n-1). And don't forget to calculate the new current maximum value (current max vs anArray[n-1]).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You can push and pop it.

1. Call function first time. Answer is in EAX.
2. Push EAX.
3. Call function second time. Answer is in EAX.
4. Pop EBX (or register of your choice).

Answer to first function call is in EBX.
Answer to second function call is in EAX.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Oh, by "in the background" you meant that you don't want to see it running...

You'll have to fill out the STARTUPINFO structure with the proper information. Make the following adjustments to the cpp file:

HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles,
  BOOL is_show_window
  ) {
  //same stuff as before
  ...
  STARTUPINFO startup_information = {0};
  ...
  startup_information.cb          = sizeof( STARTUPINFO );
  startup_information.dwFlags     = STARTF_USESHOWWINDOW;
  startup_information.wShowWindow = is_show_window ? SW_SHOW : SW_HIDE;
  ...
  //same stuff as before
  }

and to the header file:

...
HANDLE ExecProcess(
  #ifdef UNICODE
  const std::wstring& arg0,
  const std::wstring& args,
  #else
  const std::string& arg0,
  const std::string& args,
  #endif
  BOOL is_inherit_handles = TRUE,
  BOOL is_show_window     = TRUE
  );
...

Now when you call it, do it as:

HANDLE my_childs_handle = ExecProcess( "fooey", "", TRUE, FALSE );

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

So did you get it working? :S

Duoas 1,025 Postaholic Featured Poster

You'll have to split the condition.

for (int n = 0; n < 8; n++)
  {
  if ((n != row) and (board[row][column] == board[n][column]))
    return false;
  if ((n != column) and (board[row][column] == board[row][n]))
    return false;
  }
return true;

Be sure to keep that last line out of the loop. You only want to return true once you have verified against all possibilities.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

As this thread is more than two years old, I don't think the OP is too interested in the answer anymore...
:X

Duoas 1,025 Postaholic Featured Poster

> hen i remove the line 22 then i get the answer 1 when input 90

That's because on line 21 you assign the answer to x instead of ans. I'd get rid of x too...

Duoas 1,025 Postaholic Featured Poster

Heh heh heh...

My brain got so big because I studied the theory of computation... :-O

You can make your brain bigger by picking up a couple of texts on the same. ;)

Then questions like this will be obvious to you too :yawn:

:)

Duoas 1,025 Postaholic Featured Poster

You know, all those little stars make my head spin. Basically what Salem wants you to do is:

1. Allocate space for all the pointers.
2. Allocate all the space for your ints all at once, in one continuous block of memory.
3. Go through an point all your pointers at the proper spots within that space.

Heh...

Duoas 1,025 Postaholic Featured Poster

No, but they can be used to roll your own by polling them in a loop.

Like AD said though, you are trying to do something a little unlikely...

Duoas 1,025 Postaholic Featured Poster

That's because on line 22 you abnormally terminate the program. Don't do that.

Duoas 1,025 Postaholic Featured Poster

On Windows, check out QueryPerformanceCounter() and QueryPerformanceFrequency().

Duoas 1,025 Postaholic Featured Poster

This page on Wikipedia (MIPS Architecture: Assembly Language) is an excellent resource to begin with.

Another useful resource is the Programmed Introduction to MIPS Assembly Language. It has a couple chapters on Floating Point Data replete with important points and simple examples.

You can also search the forum for additional help. Example.

Hope this helps.

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

All you need is an array or vector of items, say 't_top_score', which you read from file, modify, then write back to file.

struct t_top_score
  {
  string name;
  int score;

  friend ostream& operator << ( ostream& outs, const t_top_score& top_score );
  friend istream& operator >> ( istream& ins, t_top_score& top_score );
  };

ostream& operator << ( ostream& outs, const t_top_score& top_score )
  {
  outs << top_score.name << ' ' << top_score.score << endl;
  return outs;
  }

etc.

vector<t_top_score> top_scores( 5 );

for (int i = 0; i < top_scores.size(); i++)
  cout << top_scores[ i ];

etc.

Good luck.

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

Numbers and strings are two different kinds of thing.

You'll need to convert between them. Use strtol() or strtoul() to turn your string into a number (long or unsigned long respectively).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Casting won't change the type of thing found found in the array. It will only make the program look at it as if it were a different type -- which in this case is not the correct type.

You can either fix the original function to take the correct type, or you can fix the thing you are passing to it to be the correct type.

BTW, I presume it is a typo at the end of line 6 to i++ instead of j++ Hope this helps.

Duoas 1,025 Postaholic Featured Poster

That's actually what I had in mind.

Put the stuff in post 5 (with the UNICODE additions) into its own cpp file.
Then make a same-named hpp file to match it:

#ifndef EXECPROCESS_HPP
#define EXECPROCESS_HPP

#include <windows.h>

#ifdef UNICODE
HANDLE ExecProcess(
  const std::wstring& arg0,
  const std::wstring& args,
  BOOL is_inherit_handles = TRUE
  );
#else
HANDLE ExecProcess(
  const std::string& arg0,
  const std::string& args,
  BOOL is_inherit_handles = TRUE
  );
#endif

#endif

Then, #include "execprocess.hpp" in your program's code, and compile and link both cpp files. Using GCC it would be:

g++ myprog.cpp createprocess.cpp

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You've created a 2D array of (char*) (pointers to char), but you have not pointed them anywhere. Hence they are dangling pointers, and will cause your program to crash.

If you want a 1D array of strings (where a string is an array of char): char names[ NUM_NAMES ][ MAX_NAME_LENGTH ]; If you want a 2D array of strings: char names[ NUM_NAME_ROWS ][ NUM_NAME_COLS ][ MAX_NAME_LENGTH ]; But, if you want a 1D or 2D array of pointers to strings (arrays of char), then: char *names[ NUM_NAMES ]; char *names[ NUM_NAME_ROWS ][ NUM_NAME_COLS ]; Before you can use them (the pointers), you must allocate memory for them:

for (unsigned n = 0; n < NUM_NAMES; n++)
  names[ n ] := new char[ MAX_NAME_LENGTH ];

etc. You must, of course, release the memory when you are done with it.

Print with: cout << names[ 2 ]; (3rd elt of 1D array) cout << names[ 2 ][ 3 ]; (3rd row, 4th column of 2D array)
etc.

[edit] Nearly forgot:
Access individual characters: names[ 2 ][ 0 ] = 'A'; (1D: 1st char of 3rd name := 'A') names[ 2 ][ 3 ][ 0 ] = 'A'; (2D: 1st char of 3rd,4th name := 'A')

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Don't take it as a release to use goto with wild abandon. :-O :S

Escaping deeply nested loops is one of the few places where it is considered "responsible gotoing".

Notice how even my silly, broken example of breaking out of a nested while/switch drew debate. Ed made good points against it, too.

But, other than that, glad you found it useful.

Just remember, readable, understandable, well organized code is the key. That only comes from an organized brain. Or, if you are like me where your brain shorts out on you at the least convenient times, well-organized notes.
:X

Duoas 1,025 Postaholic Featured Poster

The problem is that an array declared as: [B]int[/B] a[ 42 ][ 17 ]; is not the same as [B]int[/B] *a[ 42 ]; The first is a 2D array of 714 (42 x 17) ints.
The second is a 1D array of 42 pointers to int.

The c_function() is looking for something like the second, but you are trying to give it something like the first.

[edit] It is a vagary of the C language that lets you treat pointers like arrays, so however you define it, you can reference a specific int as: a[ 10 ][ 4 ] For the first type, it is just a simple multiplication and one dereference to index the element: *(a + (10 * 42) + 4) For the second type, it is two dereferences: *(*(a + 10) + 4) Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You've got the right idea, except that you can't name your constructor or destructor something different than the name of the class.

TFP.h
either

class ToonFillPrint
  {
  public:
    ToonFillPrint();   // constructor
    ~ToonFillPrint();  // destructor
  };

or

class TFP
  {
  public:
    TFP();   // constructor
    ~TFP();  // destructor
  };

TFP.cpp
to match what is above, either

ToonFillPrint::ToonFillPrint()
  {
  // construct me here
  }

or

TFP::TFP()
  {
  // construct me here
  }

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Or if you are feeling particularly C++ish, do it thus:

#include <sstream>
#include <string>

...

string catnum( const string& str, int num )
  {
  stringstream ss;
  ss << str << num;
  return ss.str();
  }

...

string rama1 = catnum( "rama", 1 );
string rama12 = catnum( rama1, 2 );

cout << "rama1  = \"" << rama1 << "\"\n"
     << "rama12 = \"" << rama12 << "\"\n";

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

In reality, almost all hardware does both I and O with the system.

The difference is in how the device is integrated into the system. A keyboard is typically (and AFAIK, always) treated as an input device, so programs that interact with it through the keyboard device driver can only use it to gather input.

Another important attribute is the kind of data handled by the device. While everything boils down to bytes, the meaning of those bytes differs depending on the device. For a keyboard, numbers mean key presses and releases, which are translated to letters, etc, that your program can read from the device driver. For a monitor, the data represents color information.

So, like Ed said, if your monitor can recognize touch, the system will typically have two device drivers attached to the monitor: one for color display (like all monitors), and another that looks like a mouse driver to the application, but which is in reality translating touch information into the mouse data.


What your book is probably getting at is that C++ doesn't really care where the input comes from. Most terminals have a keyboard attached to them for us humans to play with. But that is not necessary, nor is it required by the C++ standard. That's why things like redirection work.
For example, the following program counts the number of lines input before ENTER is pressed twice:

#include <iostream>
#include <string>
using namespace std;
int …
Duoas 1,025 Postaholic Featured Poster

And one is not prime.

Duoas 1,025 Postaholic Featured Poster

The suggestion offered you does exactly what you want.

int i = 3;
string s = "pineapple";

cout << s << i;

produces

pineapple3

Duoas 1,025 Postaholic Featured Poster

> And maintenance tasks are usually given to entry level programmers in the working world.
Hmm... good point.
My thought was just that this kind of routine ought not to need any maintenance because it is a small, do-one-thing kind of function. If other things are wanted, the correct way to add them is to overload using another function that calls the first, or simply replace it.

> If it were a simple break, you would have been able to use a break statement instead of a goto.
You can't break out of a loop from inside a switch. But you can break a loop:

while (quux)
  {
  if (baz) break;
  }

And you can break a switch:

switch (foo)
  {
  case bar: break;
  }

And break is just a goto anyway...

> Edward isn't smart enough to...
Oh come on, you're a super genius.
Fall-through is a basic property of C and C++ switch statements. Any rookie programmer who can't handle that isn't qualified for the job.
But, that doesn't change reality I guess... so good point anyway... :angry:

> What a fantastic place for a comment, don't you think.
It was commented elsewhere. (Don't duplicate commentary.) Sorry. :$

I think Ed and I are troubling over peanuts. :) Like I said, it is always possible to avoid using goto. Useful examples come so rarely it just happened to be what I had on hand.

Duoas 1,025 Postaholic Featured Poster

In the most platform-neutral way, use system().

For Windows, you can also use CreateProcess() or the ExecProgram() macro.

To save things to the desktop, you first have to know where it is. Use
SHGetSpecialFolderlocation

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

So Ed prefers flaggy code to do something that is straight-forward?

Not only has she introduced additional logic to accomplish a simple break, she has overloaded the readability of the code by splitting the reader's interests between the action of the switch and the effort to escape, thereby obfuscating the relationship between the if and the switch, which is the most important consideration in the algorithm.

Further, she has added unnecessary verbiage, should that flagginess be required by one's suit.

std::string get_line(std::istream& file)
{
  std::string result;
  bool done = false;

  while (!done)
    switch (int c = file.get()) {
      case '\r':   if (file.peek() == '\n')
      case '\n':     file.get();
      case EOF:    done = true;
                   break;
      default:     result += char( c );
    }

  return result;
}

Readability and the prominence of structural relationships are paramount here.


[edit] Oh, and by the way. I don't care if "everyone" can read it. Programming requires a certain level of competence that comes from experience and time served. Those finishing a 12-week beginner's course need not apply.

The code is easy enough to trace to unroll:

while (true)
  switch (int c = file.get())
    {
    case '\r':
      if (file.peek() == '\n')
        file.get();
      return result;

    case '\n':
      file.get();
      return result;

    case EOF:
      return result;

    default:
      result += char( c );
    }

[edit] Oh, also, I'm aware that it reads two '\n'. That was part of the application.

Duoas 1,025 Postaholic Featured Poster

There are numerous types of memory.

There is external memory (stuff stored elsewhere like on disk or over a network or the like). Everything else I'll say here relates to internal memory: memory your computer has direct access to.

There is RAM -- Random Access Memory, which is accessed via an address. RAM is typically designed to be pretty quick to access so that programs will run quickly. However, there is still a significant performance hit to accessing it, because it is accessed through the computers data bus (the memory is stored on one or more chips that attach to your motherboard).

To help speed things along, there is a special kind of memory called the Register File, which is basically a certain number of memory locations that are directly accessible by the CPU (they are part of the same chip as the CPU). Accessing them is lightning fast and suggests their use for certain operations, like additions and comparisons.

Individual "registers" often have special functionalities attached to them. For example, on MIPS systems register 0 ($0) always has the value 0 (zero). You can assign to it but its value never changes. This is very handy because zero is such a useful number when computing.

Another example is on Intel 80x86 processors. The [E]CX register is hardwired for counting through loops. Its special integration into the hardware for such tasks make it very efficient and fast for looping/repetitive operations.

Because these special memory …

Duoas 1,025 Postaholic Featured Poster

University level (350 or above) or Preparatory/High School?

If the latter, you can probably gather some information from the syntactical analysis.

For example, the following two are equivalent:

if (foo) bar();
else baz();

if (!foo) baz();
else bar();

If the former, you'll have to study what I mentioned, or talk with your professor for more direction.

Duoas 1,025 Postaholic Featured Poster

Good job!

BTW, what compiler are you using? I had to pull out my old TP4 to compile it...

Duoas 1,025 Postaholic Featured Poster

Is this homework or workwork?

What is the application?

Semantics is a pretty broad field. In a very small domain, you can track semantics, but if the programs are very disparate in design then you are going to have a pretty tough time.

I suggest you look into lexical analysis. You'll need to build up some carefully constructed trees and apply some pretty sophisticated transformations on them in order to compare them.

Yoinks.

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

@shankhs
You've got the right idea (for one way of doing it).

You might as well give the last argument a default value: bool rec(string a,string b,int i=0) You also need to watch your termination condition. If a and b have different lengths you may get an access violation.

[edit] I was going to give a nice, simple recursive version, but then I realized that this is Gagless's homework, so I'll just give him something to think about.

Recursive functions must always have a termination condition for every possible branch. Your current function doesn't (it leaves one branch open).

Since (as way already noted) all char[] strings must end with '\0', you can use that as a EOS signal, but explicitly passing a size count is fine also. Also remember, you don't want to compare elements in the same string, you want to compare elements in one string with those in another string at the same indices.

There is no rule that says that you have to traverse the strings in a forward direction. It is fine to go backwards. So, given that a string must end with '\0', and the argument values giving the lengths of the strings, you can immediately write the following conditions:

sizeA != sizeB --> strings not equal (they have different sizes)
ArrayA[ sizeA ] != ArrayB[ sizeB ] --> strings not equal

Now you must add one more condition to check to see if the …

Duoas 1,025 Postaholic Featured Poster

I'm sorry, but I've already given you the answer without actually writing code. You'll have to think about it yourself now...

Good luck.

Duoas 1,025 Postaholic Featured Poster

Yes, my example assumes you are using ANSI strings, not Unicode. You'll have to change the types appropriately:
std::string --> std::wstring
const_cast<char*>(...) --> const_cast<wchar_t*>(...)

If it makes a difference, you can wrap the appropriate code in #ifdefs for UNICODE

#ifdef UNICODE
const std::wstring& arg0,
const std::wstring& args,
#else
const std::string& arg0,
const std::string& args,
#endif

etc.

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

Forget the 4 digits thing. You are trying to skip a step. (Though you may not realize it...)

Just take a single digit at a time. For binary, it should be a zero or a one.

i, n, foo: integer;
...
result := 0;
for i := 1 to length( s ) do
  begin
  // validate digit is a binary digit
  if not (s[i] in ['0','1'])
    then complain_that_its_not_a_binary_number;
  // convert that digit into a number
  val( s[i], n, foo );
  // power up and add
  result := result * 2;
  result := result + n;
  end;

This is the exact same thing you did before with the octal: only three things have changed:
line 7: the set of valid digits have changed
line 10: ok, well that hasn't changed...
line 12: the radix is 2 instead of 8

You'll have to watch how you translate individual digits from hexadecimal. I suggest using upcase, pos, and a string that looks like this: '0123456789ABCDEF' Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You've already got code that converts octal to a number (which you call OctToDec).

Remember, "octal", "decimal", etc. --these are not numbers. They are strings. Only people read and write strings.

A number is an integer or a real or some other scalar type. Computers understand numbers, not strings.

So conversion from, say, binary to octal is a two-step process.

1. Convert your binary (string) in to a number (integer).
2. Convert your number (integer) to an octal (string).

You'll need two procedures: one for each step.

Remember, you've already done step 1 once (with an octal string to an integer). You can do it the same way for binary or decimal or hexadecimal --the only difference between them is the radix: 2 (binary), 8 (octal), 10 (decimal), or 16 (hexadecimal).
For your OctToDec routine (listed here) you've got the radix (the number 8) on line 24, and the set of valid digits on line 16. I don't know how you fixed line 23 to convert the digit (a character) to a number (integer), but you'll have to do the same sort of thing for every radix. Except for those three lines, everything else is the same.

To go the other way the math is just reversed. Instead of building up a number by tearing down a string, you'll build up a string by tearing down a number.

Think about it a bit and give it a go. …

Duoas 1,025 Postaholic Featured Poster

Remember the switch statement.

Good luck.

Duoas 1,025 Postaholic Featured Poster

Standard containers don't actually free memory they use (AFAIK). You have to replace them.

One way to do that is to swap it with itself: v1.swap( v1 ); I am shocked, however, that a 1.5 MB datafile uses 20MB memory. How exactly are you storing the data from the file?

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

Heh heh heh... Glad you got it working.

Now i need to change color when im editing manualy the StringGrid, how can i do that?

That, my friend, is a whole new can of beans. A really big, really deep one. Essentially you have to write your own cell editor. It isn't particularly difficult, just involved. Can you live with the way it works now? Or do you want to continue?

Duoas 1,025 Postaholic Featured Poster

I apologize but I'm not understanding, wouldn't this produce a positive result? negative by negative = positive.

I think you need to reconsider you math.

In particular, remember the definition of multiplication: [b]a multiplied by b is a added to itself b times[/b] Now we'll have to use the associative property and distributive property (of multiplication over addition). In the following, [b]a[/b][I]n[/I] is to be understood as the nth term of a. A couple steps are skipped for brevity. -[B]b[/B] x [B]a[/B] = (-1 x [B]b[/B]) x [B]a[/B] = -1 x ([B]b[/B] x [B]a[/B]) = -1 x ([B]a[/B][I]1[/I] + [B]a[/B][I]2[/I] + ... + [B]a[/B][I](b-1)[/I] + [B]a[/B][I]b[/I]) = (-1 x [B]a[/B][I]1[/I]) + (-1 x [B]a[/B][I]2[/I]) + ... + (-1 x [B]a[/B][I](b-1)[/I]) + (-1 x [B]a[/B][I]b[/I]) = -[B]a[/B][I]1[/I] - [B]a[/B][I]2[/I] + ... - [B]a[/B][I](b-1)[/I] - [B]a[/B][I]b[/I] So, if we were to say b is 5 (as in, we are multiplying a by -2), we can substitute to get: -[B]a[/B] -[B]a[/B] -[B]a[/B] -[B]a[/B] -[B]a[/B] Suppose a is 2: -2 -2 -2 -2 -2 Suppose a is -2: -(-2) -(-2) -(-2) -(-2) -(-2) = 2 + 2 + 2 + 2 + 2

And I'm still getting a stack overflow error. The integers I use for testing are 2 and -5.

OK, that is odd. Let's see your code.

Duoas 1,025 Postaholic Featured Poster

I'm sorry but I don't see the logic error here. Did you actually cut-and-paste this code in or did you eyeball-to-fingers type it in?

(BTW. Please use [[b][/b]code[b][/b]=Delphi] ... [[B][/B]/[B][/B]code[B][/B]] tags.)

A couple of observations:

1. ComputerWord should be filled with uppercase letters, but you are using a lowercase 'a' in your button click method. It shouldn't ever match. (Hence my first question. That and ShowMessage doesn't terminate the game either...)

2. I hope you didn't have to repeat a click method for each letter of the alphabet. You can get away with just one by using the button's caption.

procedure THangmanForm.AlphaButtonClick( Sender: TObject );
  var
    letter: char;
    count:  integer;
  begin
  with Sender as TButton do
    begin
    enabled := false;
    letter  := caption
    end;
  
  for count := 1 to ...
  end;

A good rule of thumb is that if you notice yourself doing something almost exactly the same more than once or twice, that's a good candidate for a single, parameterized procedure. In this case, you can just create the above procedure once, and attach every one of your alphabet buttons' OnClick event to it.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Ah, you've been brain-damaged by PHP. My condolences... er,

Oh, so you know PHP? Cool!

:)


Call it with the full path to your program and the command line arguments exactly as you would type them at the prompt: ExecProcess( "C:\WINDOWS\notepad.exe", "myfile.txt" ); If you don't like the idea of the new program having access to your open file descriptors, set the last argument to FALSE.

Hope this helps.