:$ Actually, I was just trying to be helpful.
At least I didn't make any really dumb errors this time... :-O
:$ Actually, I was just trying to be helpful.
At least I didn't make any really dumb errors this time... :-O
You are correct. The process file table and the current working directory are not modified by exec(), so the new executable inherits it all.
GCC has very limited support for tail recursion. The C++ standard does not require it, so if you want those kinds of optimizations you'll have to read your compiler's documentation on how to do it.
Iterative languages typically do not support tail recursion anyway... But that is usually a moot point since iterative and functional languages target a different application domain.
:-/ :)
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.
Well good grief. Is there some sort of timeout on editing posts? I haven't been gone that long.
Anyway, to fix a couple of simple errors in the last...
#include <string>
#include <windows.h>
HANDLE ExecProcess(
const std::string& arg0,
const std::string& args,
BOOL is_inherit_handles = TRUE
) {
HANDLE result = INVALID_HANDLE_VALUE;
std::string cmdline;
STARTUPINFO startup_information = {0};
PROCESS_INFORMATION process_information = {0};
startup_information.cb = sizeof( STARTUPINFO );
cmdline = std::string( 1, '\"' ) +arg0 +"\" " +args;
if (CreateProcess(
arg0.c_str(), // full path of program to execute
const_cast<char*>(
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;
}
You're getting a stack overflow on windows? Are you on Windows 98 or something?
In any case, make sure you don't multiply too large of a number. It costs a lot more than you think in stack space to call a function, so it adds up fast.
The reason you are getting a positive number is that you only subtract the first addend, and add the remainder. You have to subtract all of them.
The best way to do that is this:
if (Multiplier < 0)
{
Number = -Number;
Multiplier = -Multiplier;
}
Now every time you add Number, you are adding a negative number; i.e. subtracting. If both terms were negative, you'll also properly get a positive result.
Hope this helps.
I'm sorry. You said "pid" and I immediately went into *nix mode.
In Windows the terminology is that each process has a handle. Which is the same thing. Go figure.
Anyway, yes, CreateProcess() is what you want. Here's a little function to automate it a little for simple (usual) cases.
#include <string>
#include <windows.h>
HANDLE ExecProcess(
const std::string& arg0,
const std::string& args,
LONGBOOL is_inherit_handles = TRUE
) {
HANDLE result = INVALID_HANDLE_VALUE;
std::string cmdline;
STARTUPINFO startup_information = {0};
PROCESS_INFORMATION process_information = {0};
startup_information.cb = sizeof( STARTUPINFO );
cmdline = string( '\"' ) +arg0 +"\" " +args;
if (CreateProcess(
arg0.c_str(), // full path of program to execute
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;
}
You can use the returned handle to obtain information about the child process and wait for specific events. For example, to wait for the child to terminate, use
WaitForSingleObject( my_childs_process_handle, INFINITE );
Hope this helps.
Unfortunately the standard decided that such lowly things as file descriptors are too device-dependent, so there is no standard way to do that.
That said, many compiler systems provide a way to create an iostream connected to a file descriptor. Check your compiler documentation.
If you are up to it, a better solution would be to derive an iostream class that does it. Since this is a common problem, solutions by other people exist.
http://www.josuttis.com/cppcode/fdstream.hpp.html (very compact and simple)
http://www.boost.org/doc/libs/1_35_0/libs/iostreams/doc/index.html (very powerful)
Hope this helps.
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.
Argh. You made me go and do this myself. I forgot how primitive a TStringGrid is... It derives from TCustomGrid but hides its DrawCell method...
Alas. I also forgot to wrap the method body in an appropriate with statement above. (All this stuff is in the documentation.)
procedure Form1.sGridDrawCell( ... );
...
begin
with Sender as TStringGrid do
begin
savefg := Font.Color;
savebg := Canvas.Brush.Color;
if not (gdFixed in State)
then ...
// Fill the background color of the cell
Canvas.FillRect( Rect );
// Draw the text with the desired foreground color
Canvas.TextRect( Rect, Rect.Left +2, Rect.Top +2, Cell[ ACol, ARow ] );
...
end
end;
When I messed with this before (Long Ago), I wrote my own TGrid descendant, so DrawCell was available to me. Sorry I forgot about that.
Good luck.
1. Yep. Exactly. Sender should be sGrid.
2. Oops! It should be sGrid.DrawCell( ACol, ARow, Rect, State );
I just typed this stuff in off the top of my head...
You can resolve things like this by placing the cursor over the name "DrawCell" and pressing F1. The online help will give you choices of TCustomGrid objects to choose from. This means that DrawCell is a method of a TCustomGrid (or descendant), not TForm.
3. However you change the cell, you must somewhere remember that the cell has been changed.
The TStringGrid.Objects[] property allows you to attach arbitrary data to each cell. You can use a simple class to keep information about the change state of the cell:
type
TCellDataModified = class end;
Then, when you modify a cell, tag it by the presence of a modified class:
with sGrid do
begin
Cells[ 1, 0 ] := x;
if not Assigned( Objects[ 1, 0 ] )
then Objects[ 1, 0 ] := TCellDataModified.Create
end;
And finally, inside the IsHighlightMyCell function, you can simply return whether or not the cell has an attached TCellDataModified object:
function TForm1.IsHighlightMyCell( Sender: TStringGrid; row, col: longint ): boolean;
begin
result := Assigned( Sender.Objects[ col, row ] )
end;
You will have to remember to free all objects you create at some point (like if you delete a row or column, or when you delete the whole table).
// delete entire table
with sGrid do
for row := 0 to RowCount -1 …
The problem is with types and initializer syntax.
Make sure that an empty OPTIONS is { string(), vector<string>(), 0 }
NULL is not a valid vector<>.
Hope this helps.
It seems like you are having some trouble with functions.
You might want to take a look through the Functions I and II parts of this C++ Language Tutorial on cplusplus.com. It is very complete and easy to read. You'll need to understand this stuff to finish your assignment with top grade.
You forgot to list the index of the field you want to max/min/avg.
To use setw() and the like you must #include <iomanip>
Hope this helps.
Yes. I know.
But you ought to be able to do it yourself.
You'll need a CString in your Form class to remember the name of the file. If there is no file, the string should be empty.
You'll need an if statement somewhere in the function to see whether or not to call the dialog. If you do, you'll have to update the remembered filename variable.
Then open the file and write it.
Good luck.
Mmmm. Dinner was good.
Thanks for the link. It looks like I've got you going the right way.
What I suggest doing also is making another function that just scans the file for unique dates and puts them in some sort of iterative container (like an array or a vector).
If you are allowed to use vectors, you can just return a vector of dates: vector<string> get_dates( ifstream& file );
If you aren't, you could use new to allocate an array for the dates and return it: string* get_dates( ifstream& file );
You would have to delete[] the returned array before your program terminates.
Or you could just pass in a reference to an array: void get_dates( ifstream& file, string dates[], int& size );
(where size tells on input how large the array is and on output tells how many elements were actually used).
Or something like that. The function would work very much like the other function I suggested, except all you have to do is extract each line, from the file, and from each line extract the first field, and add it to the array if it isn't already there.
Then, when you are asked about, say, min/max temp, ... for every day, just run a loop that calls the other function I suggested with each date and print out the date and results before continuing with the next loop.
If you think that it would make things look …
More joy.
You are going to have to get the dates you can use out of the file too.
Before I suggest much further, I think you ought to go talk to your teacher for specific help on the assignment. I don't want to get you doing too much stuff he may not be looking for.
You will have to keep track of whether or not the user has supplied a filename yet.
If not, display the save dialog.
If he has, then don't bother displaying the dialog and just save the file.
Essentially, your OnClick handler for the button should work like this:
if (user has not supplied a filename)
{
get filename from user using the dialog;
if user canceled, return;
}
save the file;
return;
Hope this helps.
Joy. So, when the user presses '2' is the program supposed to ask for the day or just list the min & max temp for each day in the file?
[edit] and if I'm quick enough on this edit, does your teacher expect you to split the date up into numbers or can you just assume that the user will input a complete and properly constructed date?
OK then, I'll give you the simpler suggestion. (Don't worry, I won't do your work for you.) It doesn't have the same coolness factor, but it is just as effective.
Since you have several options that require you to parse the file once for each option, that means you will have to repeat a lot of code to do basically the same thing in your already very large, hard to read (because it is so big) main() function.
What I suggest that you do is make another function that handles all the parsing of the file. All you have to do is tell it which field number you are interested in, and the function will search through the file and compute the minimum, maximum, and average for the selected field.
You may also want to control which subset of records are accessed based upon the date. For example, above in my example I only accessed records where field 0 contained the date "07/01/1999".
So, given those options (pronounced arg-u-ments ;) ) we can write a function prototype:
void read_file(
ifstream& file, // The open and ready-to-read csv data file
string targetdate, // The date we are interested in (see note below)
int fieldindex, // The index of the field we are interested in
double& min, // Where to put the minimum of the indexed field
double& max, // Where to put the maximum
double& avg // Where to put the average
);
You can then, …
No, I mean convert bin (a string) to integer. Then convert the integer to hex (another string).
I hope that makes more sense.
Oops! I switch between C++ and Delphi a lot... so those :=
s should be =
s... (sorry :$ )
You will also have to do the following after each time you look through the entire file:
weatherfile.clear();
weatherfile.seekg( 0 );
That turns off the EOF bit (which would prevent further attempts to read the file) and resets the read pointer to the beginning of the file.
BTW, is this homework? (Because if it isn't I can show you something that will make organizing your program much easier, but it is pretty advanced so if it is homework your teacher won't like it and I'll suggest something else.)
10110011101 is binary. You don't have to break it into anything. Just convert it to a number.
Once you get your number from the first step, convert it into hexadecimal: 59D.
Remember, the difference between digit powers is the radix.
Remember, binary and decimal and octal and whatever is text, writing, strings, human readable stuff. They aren't numbers.
Convert a string to a number using one radix.
Convert the number to a string using another radix.
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.
In your OnDrawCell event you need to choose your color based on whatever criteria you are interested in. The criteria may apply to more than one cell, even.
procedure TForm1.sGridDrawCell(
Sender: TObject;
ACol, ARow: Longint;
Rect: TRect;
State: TGridDrawState
);
var
savefg: TColor;
savebg: TColor;
begin
// Save the current colors
savefg := Font.Color;
savebg := Canvas.Brush.Color;
if not (gdFixed in State)
and IsHighlightMyCell( Sender, ARow, ACol ) // note 1
then if (gdSelected in State)
then begin
// Something really bright for highlighted special cells
Font.Color := clYellow;
Canvas.Brush.Color := clRed
end
else begin
// Something not quite so bright for normal special cells
Font.Color := clLtGray;
Canvas.Brush.Color := clMaroon
end;
// All I wanted is to change colors,
// so we'll let the string grid draw itself.
DrawCell( Sender, ACol, ARow, Rect, State );
// Restore the original colors
Canvas.Brush.Color := savebg;
Font.Color := savefg
end;
The line labeled "note 1" is what you are interested in. You should have a function as: [B]function[/B] TForm1.IsHighlightMyCell( Sender: [B]TStringGrid[/B]; row, col: [B]longint[/B] ): [B]boolean[/B];
which indicates whether or not the indicated cell needs to be highlighted. You can choose any criteria as to whether the cell is highlighted or not.
For example, you could have the function body as: result := (Sender.Cells[ row, col ] = 'Hello');
This would be true for every cell with the text "Hello".
You could highlight the third column: result := (col = 2);
Whatever you want.
Hope this helps.
BTW. Thanks Vernon.
I was kind of hoping to get another cookie from Narue for this... :S
You'll need to call Randomize at the beginning of your program, and use Random to generate each number. number := random( 45 ) +1;
generate random number in 1..45
You'll also have to decide how to store each lotto sequence. For example, a 6/45 sequence might be:
type
LottoNumber = 1..45;
LottoNumbers = array[ 1..8 ] of LottoNumber; // 6 + 2 supplimentary
You can then write a function that generates the lotto numbers using something along the lines of the following pseudo-code:
for each number to generate
repeat
num := generate a random number in 1..high(LottoNumber)
until num not in numbers[ 1..i-1 ]
numbers[ i ] := num
end for
You'll have to figure out how to write the code that does it, but the above algorithm should be your guide.
Hope this helps.
You know that you can getline() with any character as delimiter, so why not use that to test for a potential separator sequence?
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> read_lines( istream&ins, const string& separator )
{
vector<string> lines;
string line;
char head = separator[ 0 ];
string tail = separator.substr( 1 );
while (getline( ins, line, head ))
if (line.compare( 0, tail.length(), tail ) == 0)
// we've found a separator. split lines
if (lines.size() == 0) lines.push_back( line );
else lines.push_back( line.substr( tail.length() ) );
else
// oops! not a separator!
if (lines.size() == 0) lines.push_back( line );
else lines.back() += string( head ) +tail;
return lines;
}
Using it then is elementary:
#include <fstream>
...
ifstream file( "fooey.txt" );
if (!file) complain();
vector<string> lines = read_lines( "@\n@" );
file.close();
for (unsigned i = 0; i < lines.size(); i++)
cout << i << ":" << lines[ i ] << endl;
cout << "done.\n";
Hope this helps.
I recommend writing yourself a little procedure to do it
You'll have to write that function yourself.
For hexadecimal, remember that the values of the digits are:
digits: values
0..9: 0..9
A..F: 10..15
So the DigitToInt( 'C' )
should return the value 12.
Good luck.
You need to be working with floats on the right-hand side to get floating-point division. Right now you are doing integer divisions. s -= 1.0/(i*i);
This one gets everyone at least once a year. Hope this helps.
Sorry, it is a limitation of stream iterators. I forgot to reset the file between max and min. I repaired my post above so that it will work correctly now.
Remember, a char is a different type than an integer. You cannot add or multiply characters.
Also remember, the point is that the digits 0, 1, 2, 3, ... are representations of numbers, not numbers themselves.
Line 23: Result:=result+[b]octal[len][/b]*base;
You'll have to convert the bolded part from a character into a number. I recommend writing yourself a little procedure to do it, so you can change the code to something like: Result:=result+[b]DigitToInt(octal[len])[/b]*base;
Very good job on the procedure, by the way.
You don't actually need the 'counter' variable. Just use [b]downto[/b] 1
.
Hope this helps.
Or rather:
#include <limits>
...
int main()
{
...
cout << "Press Enter to continue...";
cin.ignore( numeric_limits<streamsize>::max(), '\n' );
return 0;
}
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
It is just an example.
It is a really simple version of a handy little Unix utility called head. It just displays the first ten lines of a file and quits.
Woops. Brain-farts strike me again. :X
You'll also improve your program's safety by using the std::string type:
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string filename;
cout << "Name your file> ";
getline( cin, filename );
fstream file( filename.c_str() );
if (!file)
{
cout << "I could not open the file. Fooey.\n";
return EXIT_FAILURE;
}
else
{
string line;
int count = 10;
while ((count > 0) && getline( file, line ))
{
cout << line << '\n';
count--;
}
file.close();
}
return EXIT_SUCCESS;
}
Hope this helps.
It is because you are trying to pass a temporary object to the function. Temps are const. Therefore your function header should be: void CreateCostGrid(const vector<ScanPoint> &Data, int whichcol, vector<LiDARScan> &LiDARGrid);
If you want to modify the data, then your getColumn() function must return a non-const reference. vector<ScanPoint>& getColumn(...);
Hope this helps.
Treat them as any other stream. So yes, watch for EOF.
Hope this helps.
Argh.
Use an iterator.
template<typename A, typename B>
void print_5( const multimap<A, B>& m )
{
multimap<A, B>::const_iterator i;
for (
int n = 0, i = m.begin();
(n < 5) and (i != m.end());
n++, i++
) {
cout << i->second << endl;
}
}
template<typename T, typename U>
void print_first_five( map<T,U> m )
{
for (int i = 0; i < (m.size() >= 5) ? 5 : m.size(); i++)
cout << m[i].second;
}
Hope this helps.
It would be just as easy, and permit multi-digit numbers, to input as a string and convert it...
#include <algorithm>
#include <cctype>
#include <functional>
#include <sstream>
#include <string>
using namespace std;
int main()
{
string s;
int n;
cout << "Please enter a number> ";
getline( cin, s );
if (find_if( s.begin(), s.end(), not1(ptr_fun<int,int>(isdigit)) ) != s.end())
{
cout << "That's not a number.\n";
}
else
{
stringstream( s ) >> n;
cout << "You entered the number " << n << endl;
}
cout << "Have a nice day!\n";
return EXIT_SUCCESS;
}
You are screwing-up your gcount() by using ignore(). Get the count first, then ignore.
Hope this helps.
Get rid of that -c
and try again. Linux only executes ELFs, not OBJs.
Please tell us: