Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I am new in programming. Actually I am in 2nd year of college and starting an internship. They want me to do a program in C++ builder but I only know C. What I studied. And I don't have any knowledge about OOP.

So my question is.

I have TEdit1 and I want to verify if the data introduced in that textbox is a number. I know to verify if it is a number but I don't know how to put data from TEdit into string.

I wrote some code but it doesn't work.

void __fastcall TForm1::Button1Click(TObject *Sender) 
    int Size = Edit1->GetTextLen(); //Get length of string in Edit1
    Size++;                         //Add room for null character
    Char *Buffer = new Char[Size];  //Creates Buffer dynamic variable
    std::auto_ptr<Char> Buffer(new Char[Size]);
    Edit1->GetTextBuf(Buffer.get(),Size); //Puts Edit1->Text into Buffer
    ShowMessage(Buffer);

And I get these errors:

 E2034 Cannot convert 'std::auto_ptr<wchar_t>' to 'UnicodeString'
 E2342 Type mismatch in parameter 'Msg' (wanted 'const UnicodeString', got              std::auto_ptr<wchar_t>')

Can you please explain what i did wrong, or where i can found Embarcadero C++ Builder tutorials? I searched all google and didn't find something to help me.

  • you are declaring two Buffer variables in the same scope. That is not allowed. You need to remove one of them.

  • you are passing the std::auto_ptr itself to ShowMessage(), but it expects a System::UnicodeString instead, thus the compiler error message. You can use the std::auto_ptr::get() method to get the wchar_t* pointer and pass it to ShowMessage(), as UnicodeString has a constructor that accepts wchar_t* as input:

    ShowMessage(Buffer.get());
    
  • despite the above, you actually cannot use a pointer from new[] with std::auto_ptr to begin with. std::auto_ptr uses delete instead of delete[] to free the memory being pointed at. You must always use delete with new, and delete[] with new[]. So, while the code will compile, it will not free the memory correctly at runtime. C++11 introduced a new std::unique_ptr class to replace std::auto_ptr, and std::unique_ptr supports new[] and delete[] (however, C++Builder's 32bit compiler does not support C++11 yet - that is in the works - but its 64bit compiler does):

    #include <memory>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int Size = Edit1->GetTextLen(); //Get length of string in Edit1
        Size++;                         //Add room for null character
        std::unique_ptr<Char[]> Buffer(new Char[Size]); //Creates Buffer dynamic variable
        Edit1->GetTextBuf(Buffer.get(), Size); //Puts Edit1->Text into Buffer
        ShowMessage(Buffer.get());
    

    Now, with that said, if you are going to continue using C++Builder, you should learn how to use its built-in functionalities, like UnicodeString, which the RTL/VCL relies heavily on (use the System::String alias for most code, use UnicodeString directly only when absolutely necessary).

    Your example can be vastly simplified using the TEdit::Text property:

    void __fastcall TForm1::Button1Click(TObject *Sender) 
        String s = Edit1->Text; //Get string in Edit1
        ShowMessage(s);
    

    The simplest solution to your problem would be to use the TCSpinEdit component instead of TEdit, as TCSpinEdit only allows numeric input in the first place, and has a Value property that returns an int:

    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number = CSpinEdit1->Value;
        ShowMessage("It is a number");
        // use number as needed...
    

    But, if you have to stick with TEdit, there are many ways to check a UnicodeString for numeric content.

    You can set the TEdit::NumbersOnly property to true so the user cannot enter a non-numeric value (unless they use copy/paste, but let's ignore that for the moment), and then use the RTL's StrToInt() function, or System::UnicodeString::ToInt() method, to convert it as-is:

    #include <System.SysUtils.hpp>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number;
            number = StrToInt(Edit1->Text);
            // or: number = Edit1->Text.ToInt();
        catch (const EConvertError&)
            // not a number, do something else...
            ShowMessage("It is not a number");
            return;
        ShowMessage("It is a number");
        // use number as needed...
    

    Or you can use the RTL's System::Sysutils::TryStrToInt() function:

    #include <System.SysUtils.hpp>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number;
        if (TryStrToInt(Edit1->Text, number))
            // use number as needed...
            ShowMessage("It is a number");
            // not a number, do something else...
            ShowMessage("It is not a number");
    

    Or you can use the STL's std::wistringstream class:

    #include <sstream>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number;
        std::wistringstream iss(Edit1->Text.c_str());
        if (iss >> number)
            // use number as needed...
            ShowMessage("It is a number");
            // not a number, do something else...
            ShowMessage("It is not a number");
    

    Or, since you have a C background, you can use the C _wtoi() function (which doesn't offer much in the way of error checking):

    #include <cstdlib>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number = std::_wtoi(Edit1->Text.c_str());
        if (number != 0)
            // use number as needed...
            ShowMessage("It is a valid number");
            // not a number, do something else...
            ShowMessage("It is not a valid number");
    

    Or you can use the C wcstol() function:

    #include <cstdlib>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        String s = Edit1->Text;
        Char *p = s.c_str(), *end;
        int number = std::wcstol(p, &end, 10);
        if (end != p)
            // use number as needed...
            ShowMessage("It is a number");
            // not a number, do something else...
            ShowMessage("It is not a number");
    

    Or you can use the C swscanf() function:

    #include <cstdio>
    void __fastcall TForm1::Button1Click(TObject *Sender) 
        int number;
        if (std::swscanf(Edit1->Text.c_str(), L"%d", &number) == 1)
            // use number as needed...
            ShowMessage("It is a number");
            // not a number, do something else...
            ShowMessage("It is not a number");
                    XE5's bcc32 has std::unique_ptr. It's not quite compliant (it requires its template parameter to be a complete type in some situations where C++11 allows an incomplete type) but it's good enough for many uses, including pImpls
    – M.M
                    Jul 18, 2015 at 2:54
                    @MattMcNabb: sure, that would address the specific example Cantor gave, but not the overall task Cantor is trying to solve.
    – Remy Lebeau
                    Jul 19, 2015 at 3:33
            

    Thanks for contributing an answer to Stack Overflow!

    • Please be sure to answer the question. Provide details and share your research!

    But avoid

    • Asking for help, clarification, or responding to other answers.
    • Making statements based on opinion; back them up with references or personal experience.

    To learn more, see our tips on writing great answers.

  •