Duoas 1,025 Postaholic Featured Poster

According to MSDN:
"This function is useful for input idle detection. However, GetLastInputInfo does not provide system-wide user input information across all running sessions. Rather, GetLastInputInfo provides session-specific user input information for only the session that invoked the function."

Even if that were not so, you are trying to do something that Windows was designed against. I can't imagine why you are trying to do this, but I suspect no one who knows how, if possible, has ever tried...

Sorry.

[EDIT] You might try using a global hook. See SetWindowsHookEx() for more.

Duoas 1,025 Postaholic Featured Poster

So why can't you do:

template <typename T>
Graph<T> *get_data() {
  Graph<T> *result = new Graph<T>;
  // fill graph from file here
  return result;
  }

It is the same as returning a pointer to anything else you dynamically allocate.

Duoas 1,025 Postaholic Featured Poster

getch() and variants are not cross-platform.

Your best bet is to use the curses library. There are three variants: curses (the oldest and most basic), ncurses (a big improvement), and pdcurses (ditto). Most (if not all) Unix/Linux platforms have at least curses, if not ncurses. PDCurses, in addition to Unix variants, comes available on DOS, OS/2, Windows, Plan 9, and the Amiga.

That covers many desktop systems people will be using (including OS X), but nowhere near all.

Here's an example in another post of mine --doing exactly what you want.

Keep in mind, like WaltP said, there is no truly cross-platform method. Also, once you start using curses you cannot use the standard C/C++ I/O --it is one or the other.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

/me re-reads the first post

Ah, just use new to create an array big enough to hold the head of each linked list. node **listarray = new node*[ number_of_lists ]; Then return listarray.

Hope this helps.

Ratte commented: Very helpful replies. +1
Duoas 1,025 Postaholic Featured Poster

Actually, you are doing things the Right Way. Five stars for you for using your head.

Things are only temporary if you don't plan to use them long. In C++, you can pass things around easily enough and extend their life beyond normal even.

Local variables only live as long as the function they are declared in. But stuff you allocate on the heap is global. You only use local variables to play with it.

Here's a fun program you can play with:

#include <iostream>
#include <sstream>
#include <cctype>
using namespace std;

struct node {
  string name;
  int    age;
  node*  next;
  };

node *get_list() {
  node *first = NULL;
  node *current;
  string name, s;
  do {
    cout << "Enter a name: ";
    getline( cin, name );
    cout << "Enter " << name << "'s age: ";
    getline( cin, s );

    if (first == NULL) first = current = new node;
    else {
      current = current->next = new node;  // pay attention here!
      current->next = NULL;
      }
    current->name = name;
    if (!(stringstream( s ) >> current->age)) current->age = 0;

    cout << "More (y/n)? ";
    getline( cin, s );
  } while (toupper( s[ 0 ] ) != 'N');

  return first;
  }

void print_oldest( node *list ) {
  node *oldest = list;
  for (; list != NULL; list = list->next)
    if (list->age > oldest->age) oldest = list;
  if (oldest != NULL)
    cout << oldest->name << " is the oldest.\n";
  }

node *delete_list( node *list ) {
  node *n;
  while …
Duoas 1,025 Postaholic Featured Poster

The windows progress bar displays the percent-complete in the center, so that is a good choice. Delphi status bars are a pain in the nose to use, but I think you can add a panel containing a progress bar... I don't think I would bother with the form caption.

The reason it takes so long to load is because you are using a TListView... sorry to say.

Take a look at the OnMouseMove event for mouse over stuff.
Also, the PlaySound Win32 function. You'll probably want to compile your sounds into your program, so you'll need to read up on using resources.

Your program is designed to read and write text files. Binary files are a no-no. You'll damage them irrevocably. To auto-append a specific extension, just test the filename once you've got it to see if it has an extension or not, and add it if not.

The filename itself is just a string, so add an underscore the usual way basename + '_' + intToStr( 12 ) + fileext Just because you can save a file named "foo.pdf" does not make it a PDF file. It is still just a plain-text file. Remember, PDF, etc. are binary files. RTF is a text file, but it is not your run-of-the-mill text file. Its contents have a specific format. Load one into Notepad to see.

Good luck.

Duoas 1,025 Postaholic Featured Poster

Glad to have helped. :)

Now I see why you are calling application.processMessages. I didn't realize you were loading super-gigantic lists.

However, doing so introduces a bug: what if the user clicks, say, Remove Duplicate Entries or (gasp) Clear List while processing messages before the list is finished loading? That's a serious problem! :'(

So, how long do you have to wait loading the largest imaginable list? If it is only several seconds or less, you should instead turn your cursor to crHourGlass and/or put up a little message saying something like "Please wait" --or even, if you want to get fancy, use a a progress bar.

If it is longer, disable all the buttons that can affect the list before beginning to load, and call processMessages as you were during the load, then re-enable all the disabled buttons after loading. Or something like that.

Good luck. :cool:

Duoas 1,025 Postaholic Featured Poster

This is a math problem. You want to separate a number into hundreds.

141251 / 100 = 1412 R 51

and

1412 / 100 = 14 R 12

and

14 / 100 = 0 R 14

The C++ remainder operator is %.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

When you post code, stick it in code blocks:

[[I][/I]code=Pascal[I][/I]]
program Hello;
begin
writeln( 'Hello, world!' )
end.
[[I][/I]/code[I][/I]]

becomes:

program Hello;
begin
writeln( 'Hello, world!' )
end.

This is the easiest to read and use. Click the little Toggle Plain Text link at the top to get something you can copy and paste.

You have not posted the code you tried to compile. There is no := in there at all.

Some suggestions:
- Don't use delay. It is obnoxious and unnecessary.
- Your array should be: firstnameletters: string; Strings are capable of reporting their length:

var firstname: string;
begin
  write( 'Please enter your first name> ' );
  readln( firstname );
  writeln( 'Your name has ', length( firstname ), ' letters.' )
end.

Please post all the code you are having trouble with in code blocks.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You most certainly can return arrays from functions. Here are two ways to solve your problem.

program u;
{$APPTYPE CONSOLE}
uses
  SysUtils;

type
  tPerson = record
    name: string;
    age:  integer;
    end;
  tPeople = array of tPerson;

var people: tPeople;

//procedure getPeople( var result: tPeople );  // Method 1
function getPeople: tPeople;  // Method 2
  var
    s: string;
    i: integer;
  begin
  i := 0;
  repeat
    setLength( result, i+1 );
    write( 'Please enter a name> ' );
    readln( result[ i ].name );
    write( 'Please enter ', result[ i ].name, '''s age> ' );
    readln( result[ i ].age );
    write( 'Are there more (yes/no)? ' );
    readln( s );
    inc( i )
  until upCase( s[ 1 ] ) = 'N'
  end;

begin
// Method 1
//getPeople( people );

// Method 2
people := getPeople;

writeln( 'You entered ', length( people ), ' people.' )
end.

Uncomment the method you want (the procedure/function body was written so that it will work with whichever header you uncomment).

The trick is that everything in Pascal must be strongly typed. Notice how the array itself has a specific type. Oh yeah, this is also a dynamic array...

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Replied in kind. Lots of little fixes, a couple big ones. Most by way of suggestion and organization.

Let me know if your problem disappears with the changes.

Duoas 1,025 Postaholic Featured Poster

The DJGPP is a 16-bit DOS compiler, and as such, will not likely keep up with the most recent C++ standards.

Either get Cygwin, which is a small Unix environment running under windows --it includes the most recent version of the GCC (gcc and g++ and a few other languages),

Or get MinGW, which is the GCC compiler but without the Unix environment. I personally prefer MinGW, but most people tend to like Cygwin better. You can compile both Cygwin and Windows-native applications using Cygwin. I think it is a little easier to install too...

Hope this helps.

Oh yeah, the << and >> are bitwise operators. << is shift-left and >> is shift-right.
The number 2 in binary is 0010 .
So 0010 << 2 (read the value 2 bit-shifted left two places) becomes 1000 .
Likewise, 0010 >> 1 is 0001 .
It is possible to shift too far. 0010 >> 2 is 0000 (the 1 got pushed off the end).

In C++, the << and >> operators suggested themselves to putting something in an output stream: cout << "Hello there"; and getting something from an input stream: cin >> my_int; They are still actually shift operators, but they have been overloaded to do something else. C++ doesn't prevent that. You could, for example, overload the + operator to do multiplication. It would just confuse everyone...

Duoas 1,025 Postaholic Featured Poster

How did you know 2 was the mode of (1,2,2,3,4)? Figure out how you knew that then you can tell the computer how to know it. Does that make sense?

I find that a piece of paper and a pencil help a lot. There are several ways I can think of to do this... the two simplest being rather brute-force but very intuitive. It is perfectly OK to add other variables to help keep track of what numbers you have looked at so far, how many times a particular number appears, etc.

Hope this helps.

P.S. What about (1,2,2,3,1)? Or (1,2,3)?

Duoas 1,025 Postaholic Featured Poster

If you don't set min_val and max_val to something, it will be some random number to start --which may be lower or higher than any value in your array. So, if your array were 3 5 97 -2 12 but min_val were -349762, you'd have a problem.

Both values must be a value in the array, and both values must not be smaller/larger than the smallest/largest value in the array. Might as well initialize them to the first value in the array, thus guaranteeing both conditions are true.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Use the stringstream class:

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

int main() {
  stringstream ss;
  string user_input_string;
  int    user_input_int;

  cout << "Please enter a word and a whole number: ";
  cin >> user_input_string >> user_input_int;
  cin.ignore( 10000 );

  ss << "The word is \"" << user_input_string
     << "\" and the number is " << user_input_int << ".";

  cout << ss.str() << endl;
  return EXIT_SUCCESS;
  }

A string stream is like a file stream, but it works on a string instead of a file ;->
Get the string from the string stream with the str() member function (see line 17).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

That's not a circular list, by the way, it is just a regular, forward-only linked list.

What you've got there won't compile. When the compiler starts spitting out errors, look at the first error and the line number it says. Go to that line and fix that error then try to compile again.

The InsertLast() function belongs to a template class, so it should say

template <typename elemtype>
void CircularLinkedListType<elemtype>::InsertLast( const elemtype &Item ) {

at the top of the function. Please go re-read your textbook on how to use template classes and functions. The actual code inside the function is fine.

The IsPalindrome() function has the same problem. Also, because you are not indenting your code, you cannot see which two { and } match. There is a problem with them in this function.

In main(), you should have char x[ 100 ]; A char * is just a pointer, but it doesn't point to any chars anywhere. An array of 100 chars is different --there are actual chars you can use.

Also, you call List.IsPalindrome(), but totally ignore the boolean result. As a consequence, you can't tell the user whether or not the list is or isn't a palindrome. Try something like:

if (List.IsPalindrome()) cout << "Yeah! It is a palindrome!" << endl;
else cout << "Oh no! It is NOT a palindrome!" << endl;

Try to find some examples of functions that return boolean values, template functions, template classes, char …

Duoas 1,025 Postaholic Featured Poster

Your drawing should have a little arrow pointing from a variable named first in the main() function to the beginning of your list. ;-)

I like your new avatar, btw.

Duoas 1,025 Postaholic Featured Poster

I've looked over the sources you sent me again and I can't see why it shouldn't work.

CodeGear bought Borland's Delphi and C++ IDE/compilers, so you are actually using Delphi 2007 (the latest version) to compile your code.

The OnClick for Button12 is properly set to Button12Click in the DFM file, and the procedure itself does: lines_per_block := strToInt( edit6.text ); if saveDialog1.execute then so there is no valid reason why the dialogue shouldn't appear... except if edit6 contains an invalid number.

Why don't you change the first line to this and see if it catches the error:

try lines_per_block := strToInt( edit6.text )
except
  showMessage( 'You must specify how many lines to save per file' );
  edit6.setFocus;
  exit
end;

If that doesn't fix it then I'm completely baffled...

Duoas 1,025 Postaholic Featured Poster

Eh, sorry for the double post. Here're your problems (yes, more than one) with delet().

Line 24: ptr never becomes NULL unless you are trying to delete the last element.

However, that leaves a list like this
[1] points to [2]
[2] points to [3]
[3] was deleted!
That's a segmentation fault waiting to happen.

I want you to think about this one a bit instead of just giving you the answer. Please do as I ask and get out a piece of paper and pencil and draw yourself a little linked list, full of arrows and everything, and work your way through removing/deleting an element cleanly. Once you understand how to do it on paper you'll be able to tell the computer how to do it with ease.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Er, before anything else, you really need to watch your I/O. Don't mix C++ and C.
Find every getch() (non-standard evil!) and replace it with cin.get(); . Find every gets(s); and replace it with getline( cin, s ); .

Also, I know everyone teaches and tutorials and etc. this, but try not to use cin>>myint; when getting user input. Better to do what the user expects and head-off any input problems by getting a temporary string and converting it:

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

int main() {
  string s;
  int i;

  cout << "Please enter an integer> ";
  getline( cin, s );

  if (!(stringstream( s ) >> i))
    cout << "That wasn't an integer!\n";
  else
    cout << "Thank you\n";

  return EXIT_SUCCESS;
  }

This code is very forgiving about input errors (gets a number whenever it can) and never leaves the input stream messed up.


OK, your linked list. You add a first for the first, then you add an x for every additional. However, you are still modifying first, not x in your input statements. Notice that when you display() the list the last one you entered is displayed properly, but all the others are garbage?

Also, you have memory leaks. What if the user chooses '1' twice? You should initialize first to NULL before anything else in your program. Then check it at the case 1 to see if it is still NULL. If not, you need to either delete …

Duoas 1,025 Postaholic Featured Poster

Don't forget that you'll have to free() the array when you are done with it.

int *array_without_doubles = remove_doubles( array_with_doubles );
print_array( array_without_doubles );
free( array_without_doubles );

Good luck.

Duoas 1,025 Postaholic Featured Poster

All these little things are important, but I think you need to spend more time thinking about how you are going to solve the problem. The computer is too stupid to do it, so you have to figure it out yourself first.

I say this all the time but I don't think anyone has ever done it that I haven't sat next to and forced them to: get out a piece of paper and a pencil and write down and draw what you understand about the problem. Don't stop until you can solve the problem on paper. Once you know what steps you took to solve the problem --only then can you tell the computer how to do it.

For this problem, the first thing I would do is draw a little sinusoid and mark it up. (Appologies for the badly GIMPed image.)
[IMG]http://home.comcast.net/~michaelthomasgreer/temp/samples_per_cycle.gif[/IMG]
I drew three cycles, and I imagined that I wanted four samples per cycle. I then counted how many samples total there were: 12. If I want to take a sample at x=0 also then I would say 13 samples total. To recap for this example:
- the user asked for 3 cycles
- the user asked for 4 samples per cycle
- therefore, I need to write 3 * 4 (and maybe one extra for the beginning sample) to file.

Now I need to think about a little math. Each orange mark is a sample. …

Duoas 1,025 Postaholic Featured Poster

There are syntax and type errors throughout (maybe only a little dyslexia, perhaps?).

For example: printf("n\Thank you. You entered %s\n" PurchaseAmount); should read: printf("\nThank you. You entered %d\n", PurchaseAmount); The main problem, though, is how you are handling types. Ah, I just previewed and I see Salem has noted the scanf() problem.

The last thing is that you are using all integers. This isn't necessarily a bad thing (I entered compiled and entered 1290 for $12.90), except that when you calculate the tax rates you are dividing small numbers by a really big number: DelMarTaxRate = 725/10000; That's less than zero, and since you are using integers, the fraction is lost and the DelMarTaxRate is set to zero. To get the cents you'd have to multiply the numerator by 100 first. Or change all your ints to floats (and use the proper scanf and printf formats).

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

SIGSEGV is a memory access violation --meaning that you tried to read (or write, but in your case read) memory that doesn't belong to you.

The problem lies in lines 23 and 25. The condition at 23 is blissfully ignored by the loop at 25, which will continue until you try to read past your accessible memory.

You can use the strcmp() function to compare strings instead of doing it yourself.

You haven't given very much code or the structure of your galaxy, so it is hard to examine more deeply than that.

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Yes, it gives the dialogue and all.

Ah, I forgot to mention that your program shouldn't have compiled at all because you had listed in your uses clause unit1 instead of unit1_helpme. So I'm not sure exactly what is wrong.

I used Delphi 5 to compile it. You said you were using FPC? Give me a day and I'll see if I can make it work with FPC.

Duoas 1,025 Postaholic Featured Poster

No, the only function is random. If you say x = random( 7 ); then x will be one of (0, 1, 2, 3, 4, 5, 6).

Duoas 1,025 Postaholic Featured Poster

You need to read up on how to declare a function and how to call a function.

The function you are trying to use is declared as: bool hasaletter( string, char ); To use it: if (hasaletter( "1024x768", 'x' )) cout << "It sure does...\n"; Hope this helps.

Duoas 1,025 Postaholic Featured Poster

While all true, I think your input paradigm is broken.

how you do it matters
Whenever you ask for input from the user what you expect him (or her) to do is type some number of characters and press the ENTER key. That's what getline( cin, s ); is for. It reads and stores each character until either the newline (ENTER) character or the end of the input stream is encountered.

However, the istream class is not designed for that kind of input. (Notice how the getline() function is not a member function?) The class is designed for whitespace delimited tokenizing. What that means is that it takes a sequence of "words" (lists of characters not containing whitespace) and attempts to convert them to the target data type.

For example, the input string

Hello  12     -3.141592   A

   "What up?"

has six tokens in it. You can read it using cin (or any other istream) thusly:

string hello, what, up;
int twelve;
double neg_pi;
char c;
cin >> hello >> twelve >> neg_pi >> c >> what >> up;

Notice how the "What up?" is two strings? (There's a space in the middle.) Whitespace is any sequence of characters made up of spaces, tabs, and newlines. You could have twelve new lines between the "What and up?" and it would read the same.

This is roughly equivalent to the C scanf( stdin, "%s%d%lf%c%s%s", &hello, &twelve, &neg_pi, &c, &what, &up ); except that it is …

Duoas 1,025 Postaholic Featured Poster

If you don't want the same random numbers over and over again, at the very beginning of your program, call the randomize procedure.

begin
  randomize;  // init number generator from system clock
  ...
end.

As for the range, the problem is purely mathematical. If you have a list of seven numbers (0, 1, 2, 3, 4, 5, 6), what do you have to do to it to make it (-3, -2, -1, 0, 1, 2, 3)?

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

You sent that to me so quickly I took a look at it already. I still can't reproduce your error --the program works fine for me.


Testing
Are you sure you are saving in the same directory you loaded from? Here is what I did:
click "Load List", select my input file "in.txt". The list loads.

My list had twelve items, so I put something like 5 in the edit box. (I also tested with 4. As part of your error checking you need also to make sure that the number in the edit box is strictly greater than 1.)

I click "Go" to save. I select the same directory I loaded from and type an output file name "out.txt". Using explorer (or the command prompt) I look at the directory and I see three files:
- out1.txt
- out2.txt
- out3.txt
Examining the files shows they are properly formed.

The load and save directory need not be the same. Even if you load something the save directory is still at the default directory. You can force them to match by saying saveDialog1.initialDir := extractFileDir( openDialog1.filename ); before calling saveDialog1.execute.


Some errors
My debugger complained about a couple of things, so I looked them over. They are all in Button1Click. Here it is fixed:

procedure TForm1.Button1Click(Sender: TObject);  // load/open file
  var
    txt : TextFile;
    Buffer : String;
  begin
  if openDialog1.Execute() then  //(1)
    begin
    AssignFile(txt, openDialog1.FileName);
    Reset(txt); …
Duoas 1,025 Postaholic Featured Poster

I can't reproduce your error. If you can't figure it out by tomorrow then go to your project directory, zip everything up, and send it to me at michael thomas greer (without the spaces)
my provider is comcast.net Use whatever compression program you like (ZIP, TGZ, RAR, etc.) I won't take EXEs though.

Duoas 1,025 Postaholic Featured Poster

It works, it just doesn't tell you it did. Check your directory for files.

Remember also that the TListView must be populated with at least one item for it to work. (You loaded your list so that's not a problem.) When I did it, I just added three items using the designer, set the number of items per file to 2, and clicked the button --producing two files (the first containing two lines and the last containing one). I'm sure you must have a ton of files in the directory you saved to.

Most programs indicate that a save worked successfully by putting a message on the statusbar or changing the main form's caption or some other like thing.

Another thing you should be aware of is that there is currently no error checking to make sure that Edit6 contains a number, so if the user puts in "fooey" the program will crash. Go ahead and try it. There are several ways to fix this, but the easiest is something like:

try
  lines_per_block := strToInt( edit6.text )
except
  showMessage( 'You must specify how many lines to save per file.' );
  edit6.setFocus;
  exit
  end;
if saveDialog1.execute then ...

Glad to be of help.

Duoas 1,025 Postaholic Featured Poster

OK, that was enough. You need two changes.

In your class definition:

private
    { Private declarations }
    procedure saveNLines(filename: string; items: tListItems; startAt: integer; numLines: integer);
  public
    { Public declarations }
  end;

You must declare your procedures and functions before you can use them. Also, the compiler was complaining about passing the TListView.items as a var argument, so you will notice that I removed the var from the parameter list. The actual procedure definition must match, so change it below the same way:

procedure TForm1.saveNLines(filename: string; items: tListItems; startAt: integer; numLines: integer);

That compiled and worked correctly for me.

Duoas 1,025 Postaholic Featured Poster

1. n is the number of elements in the array, where k is 0, 1, 2, ..., n-1.

2. There is no need to calculate the average inside the loop. Move that stuff outside.

3. Don't forget to set total to zero first, otherwise you'll just have some random number.

4. If total is not a float or double, your average will be an integer, which is probably not what you want. For floating point division, make sure at least one of the operands is a floating point number.

total = 0;
avgTemp= 0;
for( k = 0; k < n; k++){
  total += temps[k];
  }
avgTemp = float( total ) /n;

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

That would work.

You would have to create a new form, and show it to display the message, and hide it to stop displaying the message. The trick is to let the user dismiss the form, which means responding to button presses or the [X] button or "Close" option of the window menu or if the user presses ENTER or ALT+F4. To do that stuff you'd have to display the form with showmodal, which I don't think you know enough to do easily.

If you are using Free Pascal and not the GNU Pascal (the Bloodshed Dev IDE works with both), then make sure you have the Dialogs unit in your uses clause: uses Windows, SysUtils, [B]Dialogs[/B], Messages; and to display a message use: showMessage( 'Hello world!' ); This displays a popup with the message and an OK button.

Or use: messageDlg( 'Hello world!', mtCustom, [], 0 ); to display the dialog without buttons. (I have never tried to show one without buttons. It may or may not work. Either way, you will still be able to click the [X] button or press ESC to terminate the dialog.)

Hope this helps. (And please read-up like I asked.)

Duoas 1,025 Postaholic Featured Poster

Yeah, I know. I've gone through the same things... Over and over and over again. It's just part of programming...

Post your entire unit and I'll take a look-see. It has to be something painfully silly.

I once spent an entire week on about 60-70 lines of C code and was just at the point of burning my PC when I figured out that I had misplaced a } somewhere. Most. Obnoxious. Error. Ever.

Things get better after a while. Honest they do. Just don't give up. (Right now I'm banging my own head against the windows console... the stupid thing doesn't have a WndProc, permit event hooks, anything... it is for all intents and purposes an actual GUI-less process. All I want to know is if the user grabs the window and sizes it... but apparently that "can't happen". Alas...)


I think you put the saveNLines inside your TForm1 class definition, but defined it below as procedure saveNLines( ... ); instead of procedure TForm1.saveNLines( ... ); I'm not sure what the second error is, so post everything so I can find it.

Duoas 1,025 Postaholic Featured Poster

You need to read up on how to use procedures and functions.
Here's a nice tutorial.

Also, to use the MessageDlg function, you will need to put the Dialogs unit in your uses clause.

Good luck.

Duoas 1,025 Postaholic Featured Poster

Heh, I often find that things get lost between my brain and the keyboard too... :P

Duoas 1,025 Postaholic Featured Poster

You've made a syntax error somewhere. Please post your code.

Duoas 1,025 Postaholic Featured Poster

Oh yeah... (sorry for the double-post)

the error checking in the example is fairly simplistic. It glosses over errors like lines that are too long in the file. So, for example, if your description is longer than 999 characters, the player will see only the first 999 and the rest are ignored.

It would be better to dynamically allocate the space for description. That way it can be as large or small as you want...

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Yes, such abstraction is usually best. However, in C, you must build your own.

I've taken some liberties here.
1. First, I changed your direction type to an enumeration.
2. Second, I added a whole lot of error checking. (I am assuming this is not a school project. Please don't make me wrong.)

Some notes:
1. Don't name files other than C source code "anything.c". I renamed "maps.c" to "maps.txt".
2. Don't use C++ comments in a C program.
3. Don't forget to close files when you are done with them.
4. This code aborts on error, but does not inform you that an error actually occurred. Hence, if the nth record contains an error, you will only get n-1 records out of the file, and main() won't know any different. There are a number of ways to settle this error... the easiest being to check to see if any record has a dest1 or dest2 >= the number of records read. You'll have to do that.
5. Care is taken not to hardcode the length of any string in the readRooms() function. (Note the use of the sizeof operator.) Keep in mind this only works for char strings. (Unicode strings would need a bit more help.)

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

typedef enum {
  d_none, d_north, d_south, d_east, d_west,  d_error = -1
  } direction_t;

const char *directions[] = {
  "none", "north", "south", "east", "west"
  };

typedef …
Duoas 1,025 Postaholic Featured Poster

http://www.daniweb.com/forums/thread95939.html

You really should do your own work.

Duoas 1,025 Postaholic Featured Poster

Heh, don't worry 'bout it.

deadswitch
Why did you change your fgets(rooms[i].room_name, 80, fin); (which worked fine) to fscanf(fin, "%s", &rooms[i].room_name); (which only reads until whitespace is encountered)?

Duoas 1,025 Postaholic Featured Poster

Is there anyway that you can convert the '\n' in windows which is 2bytes to the '\n' 1byte so that the linux could read it?

Sure. There is a little Unix utility called dos2unix. It is found on most *nix systems.

To do it in code, just set your output file mode to "binary". Doing so turns off the '\n' to "\r\n" translations, so when you write your file you get exactly what you write --single newline and all.

In addition, does the fread() function can use wchar_t* type as buffer?

No, it uses char. Sorry.

However, there are usually functions to convert a binary string to a unicode string...
(I don't know what they are though.)

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

I think you are going to have to ask your professor.

Like I said, I don't have access to anything that has to do with MPLAB SIM, so I couldn't tell you... and I don't think anyone else here can either...

Alas.

[EDIT] Oh yeah, I discovered that if you type [[I][/I]code=asm[I][/I]] that you can highlight for Intel assembly.

Duoas 1,025 Postaholic Featured Poster

I haven't played with scanf() in a long while, but what is probably happening is that you are reading the room number, but not the newline. Thereafter, you scan for a room name and get the newline immediately, which terminates the string.

Try getting the room number like this instead: fscanf( fin, "%d%*[ \t]\n", &rooms[i].room_number ); This gets an int, skips spaces and tabs (if any) and reads a newline, leaving the fp at the beginning of the line containing the room name. Then, when you read the room name it works.

I hope this is correct.

[EDIT] Aia, that completely ignores his input format requirements.

Duoas 1,025 Postaholic Featured Poster

Look, I haven't meant to make you feel stupid.

1. Look at posts #4 and #10, where I gave you an event handler and which you correctly modified to use the TListView.
2. Now look at post #16 where I gave you a function that prints x lines from a TListView's item list.
3. Put them both in your code. Change the word "save250" from post #10 to "saveNLines".


I know you are new to programming. That is why I have asked you to read about procedures and about types. All your errors are due as a direct consequence of your failure to do that.

You are being defensive and angry. And you presume too much to say I am unwilling or that I misunderstand. I understand better than you think, and I have stated repeatedly I am willing to help, if you are willing to follow the advice given you. I have no interest in wasting my time to lead you in circles.

Please consider that I know what it is to learn how to program and how much information overload it is to find simple answers. The truth is that there are no simple answers when it comes to programming, and you are going to have to wrap your mind around a few things --none of which come easily-- to get it right. Until you do, even a gift horse looks like a mule.

Duoas 1,025 Postaholic Featured Poster

You are missing plus signs between chr(13) and chr(10).

Since we are using a BP dialect, you could also just say + #13#10 For the ndx, use the ord() function ndx := ord(ch) -ord('a'); Hope this helps.

Duoas 1,025 Postaholic Featured Poster

A quick re-org to help:

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

// typedefs don't belong inside functions (not usually, anyway...)
typedef struct {
    int room_num;
    char room_name[80];
    char desc[1000];
    int num_links;
    char direction1[6];
    int dest1;
    char direction2[6];
    int dest2;
} roomStruct;

// Functions need complete types
void readRoom ( roomStruct rooms[] );

// int main() doesn't take any void arguments.
int main () {
  roomStruct rooms[100];

  readRoom(rooms);

  return 0;
}

// And the type must be the same as the prototype's
void readRoom ( roomStruct rooms[] ) {

    FILE *fin;
    int i = 0;

    fin = fopen("maps.c", "r");

    fscanf(fin, "%d", &rooms[i].room_num);

    fgets(rooms[i].room_name, 80, fin);

    printf("Room number: %d ... Room name: %s\n", rooms[i].room_num, rooms[i].room_name);

    // no need to "return" from a void function
}

Hope this helps.

Duoas 1,025 Postaholic Featured Poster

Perhaps you meant to post in the C forum? (This is C++.)

Think about what the program is supposed to do, and write down a sort of "how to" to get it done:

1. get an integer from the user
2. get another integer from the user
3. get yet another integer from the user
4. figure out which integer is the smallest and print it
5. figure out which is neither smallest nor largest and print it
6. figure out which is the largest and print it

Looking that over, you might want to add "ask the user for three integers" before step 1.

Once broken down into smaller steps like this, you can deal with one step at a time. Since you need to keep track of three integers, that suggests three variables: int a, b, c; Use scanf() to get input from the user: scanf( "%d", &a ); // get the first integer from user Refer to your class notes and textbook for more help.

Hope this helps.