C++ Converting textbox content to a Float - visual-c++

Tried carefully code from this thread
Converting textbox string to float?
Tried to leavemy question in a comment, but yet not allowed to do so...
The summary of that goes like having two text boxes, taking data from first, doing something, and returning the result to the second.
String^ i1 = Textbox1->Text;
float rez = (float)(Convert::ToDouble(i1)*4);
Textbox2->Text = rez.ToString();
and it works pretty good unless Textbox1 got a float within itself (upd. it works ok with '65', but doesn't work with '65.5').
Trying to execute that code - crushes a program
> Calc.exe!Calc::Form1::Button0_Click(System::Object^ sender = 0x01b29c58, System::EventArgs^ e = 0x01b45e40) Line 123 + 0x30 byte C++

Convert::ToDouble
Using the ToDouble(String) method is equivalent to passing value to the Double.Parse(String) method. Value is interpreted by using the formatting conventions of the current thread culture.
So, you need
Catch possible exceptions
try {
float rez = (float)(Convert::ToDouble(i1)*4);
}
catch (FormatException) {
// handle format error exception here
}
catch (OverflowException) {
// handle overflow exception here
}
Use IFormatProvider

Related

How do I remove the last character from a string in a textBox?

I am trying to create a calculator program similar to what Windows has, and I am currently having trouble with making a backspace key. It should, when clicked, remove the last character from the textBox Text field.
Here what I was thinking would work:
private: System::Void button14_Click(System::Object^ sender, System::EventArgs^ e) {
textBox1->Text[textBox1->TextLength] = ""; }
The error list looks like this:
I have also seen suggestions to use pop_back(), remove() and erase() on the Internet, but I don't have an idea how to use them.
Strings are immutable... you can't technically change the string.
IDK how to write this in the weird CLI C++ syntax, but something close to:
String^ s = textBox1->Text;
s = s^.Substring(0, s.Length - 1); // original s preserved, but no longer used
textBox1->Text = s;
IDK if it would allow something like, but if it does, I'd prefer it:
auto s = textBox1->Text;
s = s^.Substring(0, s.Length - 1); // original s preserved, but no longer used
textBox1->Text = s;

What's the Easiest Way to Skip a Line in a Managed String^ VC++

I'm trying to Skip a line in a Visual C++ managed String^ or String^ array but I haven't found any easy way to do so. In-fact, I've spent two days on something that would take less than 30 seconds in C#. There is a method .Skip() within C# Enumerable
https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.skip?view=netframework-4.7.2
and I'd like something similar for VC++ if possible.
Here's what I've tried:
auto a = gcnew cli::array<String ^>{ "Alpha", "Bravo", "Charlie", "Delta" };
auto xs = gcnew System::Collections::Generic::List<String^>(a);
System::Collections::Generic::IEnumerator<String^>^ e = xs->GetEnumerator();
e->MoveNext();
^^ that throws exception class System::EventArgs has no member "MoveNext"
EDIT: I know what's causing the exception System::EventArgs has no member "MoveNext" .. using ' e ' in Visual Studio causes the compiler to think I'm referring to the e for EventArgs as in e) click_method .. I switched to another name and it populates as this: System.Collections.Generic.List`1+Enumerator[System.String]
I also tried referencing System::Linq and then
System::Collections::Generic::List<String ^>^ _list = gcnew System::Collections::Generic::List<String ^>(System::IO::File::ReadAllLines(filename));
System::Collections::Generic::List<String ^>^ _list2 = _list->Skip(1);
which seems like it would work in C# but get the following exception
class System::Collections::Generic::List has no member skip
so the .NET library doesn't work in CLI / C++
Another thing I attempted was:
System::Collections::Generic::List<String ^>^ _list = gcnew System::Collections::Generic::List<String ^>(System::IO::File::ReadAllLines(filename));
System::Collections::Generic::List<String ^>^ _list2 = _list->RemoveAt(0);
but got exception:
a value of type "void" cannot be used to initialize an entity of type System::Collections::Generic::List^
I'm trying to do it without using marshal_string if possible, but I'm open for any suggestions, as I've been pulling my hair out on this, not sure what else to try =[
EDIT: this reads as an array not a String^ but I couldn't figure out how to do it with a String^ on it's own.
definitely not the quickest way but this skips x number of lines.
I am sick of CLI/C++/VC++ and can't wait to stop using it (I should have never used it in the first place and kick myself daily for not making this in C#).
//read the file to a CLI array (each line is a member)
auto a = System::IO::File::ReadAllLines("test66.txt");
//create a List from the array
auto xs = gcnew System::Collections::Generic::List<String^>(a);
//create a collection from the List
System::Collections::Generic::IEnumerator<String^>^ test66 = xs->GetEnumerator();
//the number of lines we want to skip
int x = 0;
//for loop stopping # x
for (int nxt; nxt <= x; nxt++)
{
test66->MoveNext();
}
//present selected array item to user or you could feed this into a String^
textBox11->Text = test66->Current;
feel free to give a better answer. I couldn't find much information since CLI/C++ is absolutely awful compared to C# and just about every other modern language. (IMO)

Error C2228 left of '.size' must have class/struct/union on Winform

I'm creating my first program on Winform with C++. I have a function and a string input. However, when I run the program, I get the following error with text.size(): "Error C2228 left of '.size' must have class/struct/union"
Relevant code:
private: System::Void bntGet_Click(System::Object^ sender, System::EventArgs^ e) {
in_itext = txtText->Text;
itext = Convert::ToString(in_itext);
for (Int32 index = 1; index <= itext.size(); index++)
{
if (itext[index] == '#')
{
while (itext[index - 1] != ' ')
{
index--;
}
while (itext[index] != ' ')
{
next_email += itext[index];
index++;
if (itext[index] == '\0')
break;
}
break;
}
}
txtEmail->Text = next_email;
}
Any suggestions? Thanks everyone!
Standard warning: While it's certainly possible to write the main body of your application in C++/CLI, or even write the GUI in C++/CLI using WinForms, it is not recommended. C++/CLI is intended for interop scenarios: where C# or other .Net code needs to interface with unmanaged C++, C++/CLI can provide the translation between the two. For primary development, it is recommended to use C# with either WinForms or WPF if you want managed code, or C++ with MFC if you want unmanaged.
That said:
for (Int32 index = 1; index <= itext.size(); index++)
and
"Error C2039 'length': is not a member of 'System::String'"
Size is not how you get the length of a System::String in .Net. For that, you want the Length property. You were close on your second attempt, but you need a capital "L". (size() is how std::string does it, but std::string is a completely different beast from System::String.)
Other issues:
in_itext = txtText->Text;
itext = Convert::ToString(in_itext);
It's already a string, you don't need to convert it.
while (itext[index - 1] != ' ')
{
index--;
}
You can easily run off the beginning of the string if you do this. (You'll get an exception when index is equal to zero.) Add a check against zero.
while (itext[index] != ' ')
{
next_email += itext[index];
index++;
if (itext[index] == '\0')
break;
}
Strings in .Net are not null-terminated, you need to check against the Length.
If we take a step back, what problem are you actually trying to solve here? My best guess is that you've got some text with an email address somewhere in the middle, and you just want to extract the email address. If that's the case, then I'd probably try using a regular expression to extract the email address. You've got the full power of the .Net Library available to you, use it! See Using a regular expression to validate an email address for the regex to use, and read up on regular expressions with the introduction page and class reference.

iterating through PictureBoxes in visual c++

I'm programming in visual c++, and I have about 60 pictures (indexed p0...p63). I want to make a loop that goes through all the pictures and change their ImageLocation under some conditions.
I figured the Tag property and one of my attempts was like this:
I tagged my pictures from 0 to 63 and then tried the following:
for(int i=0; i<64; i++)
{
PictureBox->Tag[i]->ImageLocation="possible-.gif";
}
It's not working... I get this error:
syntax error : missing ';' before '->' line: 1514
syntax error : missing ';' before '->' line: 1514
(twice, same line)
What's the right way of doing it?
Thank you!
edit:
OK now I have the pictures in an array. Is there a way to have a common rule for all of them? I want to make a click event for each and every one of the pictures. Is the only way setting a rule for each independently? Or can I set a rule for the array itself by saying something like:
if(Pictureboxes[i]_Clicked)
{
Pictureboxes[i].something = "something else";
}
I found the way to solve it. So I guess I'm gonna answer myself:
I made an array of PictureBoxes:
private: static array<System::Windows::Forms::PictureBox^>^ pictures=(gcnew array<System::Windows::Forms::PictureBox^>(64));
and filled it with the pictures:
pictures[0] = p0;
pictures[1] = p1;
pictures[2] = p2;
...
Then i clicked each of the pictures to create click_events.
In each event i typed this:
int place = (/*pic number*/);
IndexOf(pictures);
This code sends to a function named IndexOf the picture i clicked.
And here is IndexOf():
static System::Void IndexOf(int& place)
{
int flag = 0;
if(pictures[place]->ImageLocation == "possible-.bmp")
{
flag = 1;
/*DO CODE*/
}
if(flag)
/*OTHER CODE*/
}
Now i can do whatever code i want for pictures[i] at /do code/ above.

Listing files in directory

I have created a windows form in c++ which, upon a button click, opens a dialog box for folder selection.
Now what I would like to do is get the list of files in that directory so that I can process them one by one.
I have googled it in many ways, and found many ways which include external libraries (such as boost and diren.h). I would not like to use external resources, but the ones at my disposal, the default ones.
I've read about FindFirstFile and FindNextFile, but couldnt get that combination to work.
Could you please assist?
Thanks a lot,
Idan.
Here is the updated code:
HANDLE hFind;
WIN32_FIND_DATA FindFileData;
FolderBrowserDialog^ folderBrowserDialog1 = gcnew FolderBrowserDialog;
if (folderBrowserDialog1->ShowDialog() == System::Windows::Forms::DialogResult::OK)
{
String ^ selected = folderBrowserDialog1->SelectedPath;
selected += "\\*";
char* stringPointer = (char*) Marshal::StringToHGlobalAnsi(selected).ToPointer();
hFind = FindFirstFile((LPCWSTR)stringPointer, &FindFileData);
while(hFind != INVALID_HANDLE_VALUE)
{
printf("Found file: %s\r\n", FindFileData.cFileName);
if(FindNextFile(hFind, &FindFileData) == FALSE)
break;
}
}
You obviously compile for UNICODE (wide char) since you need to cast the newStr for the lpFileName parameter of FindFirstFile. But since you pass an ANSI string, you probable won't get a useful result. Youd didn't write, what you expect to find.
In the code beforer FindFirstFile you manually convert the SelectedPath value to ANSI char. That makes no sense, when you need a wide char string anyway. Get the LPCWSTR from the String selected with the StringToHGlobalUni method. This looks somehow like this (not tested):
LPCWSTR stringPointer = Marshal::StringToHGlobalAnsi(selected).ToPointer();
hFind = FindFirstFile(stringPointer, &FindFileData);
In general: Don't use casts except when you need to adapt a bad designed interface. Use it only when you know exactly what you are doing.
Further you don't check the hFind result of FindFirstFile. It will be INVALID_HANDLE_VALUE if you pass a pointer to the wrong string format.

Resources