scanf in Borland C++ Builder

1.8k views Asked by At

I'm trying to check type of my variable with function scanf. It works fine for Dev C++(my input is int), but it doesn't using Borland. Here is what I've tried:

AnsiString as = Edit1->Text;
string b = as.c_str();

int testb = atoi(b.c_str());

if(scanf("%i", &testb)==1){
do sth;
}

Any ideas?

[edit1] moved from comment by Spektre

I have another problem. My input value should look like xx-xx-xxxx so it's a date.
I have to check if day, month and year are integer.
I tried like this:

AnsiString a = Edit1->Text;
date = a.c_str();
 if (a==AnsiString().sprintf("%i",atoi(a.SubString(0,2).c_str()))
  && a==AnsiString().sprintf("%i",atoi(a.SubString(3,2).c_str()))
  && a==AnsiString().sprintf("%i",atoi(a.SubString(6,4).c_str())) )
 { 
 //do sth
 }
  • but it check only a day. Does anyone know why? – J. B. 20 hours ago
2

There are 2 answers

3
Spektre On

I do it in this way

AnsiString s=Edit1->Text; // copy to real AnsiString ... the AnsiStrings inside visual components are not the same ... some functions/operations does not work properly for them
int e,i,l=s.Length();

for(e=0,i=1;i<=l;) 
 {
 e=1; // assume it is integer
 if (s[i]=='-') i++; // skip first minus sign
  for (;i<=l;i++) // scan all the rest 
   if ((s[i]<'0')||(s[i]>'9')) // if not a digit
    { 
    e=0; // then not an integer
    break; // stop
    }
 break;
 }
// here e holds true/false if s is valid integer

now you can use safely
if (e) i=s.ToInt(); else i=0;
  • not sure If s.ToInt() is also so buggy but at least until BDS2006
  • if you call s.ToDouble() for invalid number then an unmaskable exception is thrown
  • so for example if you try to convert 0.98 and the decimal point is not set to . your program crashes (atoi and atof are safe)

you can also use sprintf:

AnsiString s=Edit1->Text;
if (s==AnsiString().sprintf("%i",atoi(s.c_str()))) /* valid integer */;
0
Remy Lebeau On

You are making this horribly more complicated than it should be.

scanf() reads from STDIN, but a GUI proces does not use STDIN for input, which is why it is not working for you. Use sscanf() instead:

int testb;
if (sscanf(AnsiString(Edit1->Text).c_str(), "%d", &testb) == 1)
{
    // do sth ...
}

Alternatively, use the RTL's TryStrToInt() instead:

int testb;
if (TryStrToInt(Edit1->Text, testb))
{
    // do sth ...
}

As for checking a date string, you can use sscanf() for that:

int day, month, year;
if (sscanf(AnsiString(Edit1->Text).c_str(), "%2d-%2d-%4d", &day, &month, &year) == 3)
{
    // do sth ...
}

Or use the RTL's TryStrToDate():

TDateTime testb;

TFormatSettings fmt = TFormatSettings::Create();
fmt.DateSeparator = '-';
fmt.ShortDateFormat = "d-m-y";

if (TryStrToDate(Edit1->Text, testb, fmt))
{
    // do sth ...
}