[MFC] Cum formatez un string la run-time?

Despre MFC, ATL si alte biblioteci C++ de la Microsoft (forum moderat)
Post Reply
User avatar
Ovidiu Cucu
Fondator
Fondator
Posts: 3778
Joined: 11 Jul 2007, 16:10
Judet: Iaşi
Location: Iasi
Contact:

[MFC] Cum formatez un string la run-time?

Post by Ovidiu Cucu » 20 Oct 2007, 17:05

Problema
Pentru exemplu, sa zicem ca avem de formatat o instructiune SQL SELECT in care valorile din clauza WHERE sunt date la run-time, avand o functie cu urmatorul prototip:

Code: Select all

void CFoo::FormatSQL(CString& strSelect,
                     LPCTSTR pszLastName, UINT nCountryID,
                     UINT nCityID, UINT nSalary, LPCTSTR pszBirthDate);

strSelect va trebui sa contina ceva de genul

SELECT FirstName, LastName, Country, City, BirthDate FROM Employee, Countries, Cities WHERE Countries.CountryID = Employee.CountryID AND Cities.CityID = Employee.CityID AND LastName = 'Ionescu' AND CountryID = 123 AND CityID = 123456 AND Salary < 1200 AND BirthDate = '17.08.1961'

Metoda #1
Transformam, acolo unde este nevoie in stringuri, apoi le concatenam folosind operatorii + si += ai lui CString.

Code: Select all

void CFoo::FormatSQL(CString& strSelect,
                     LPCTSTR pszLastName, UINT nCountryID,
                     UINT nCityID, UINT nSalary, LPCTSTR pszBirthDate)
{
   CString strCountryID, strCityID, strSalary;

   strCountryID.Format(_T("%u"), nCountryID);
   strCityID.Format(_T("%u"), nCityID);
   strSalary.Format(_T("%u"), nSalary);

   strSelect = _T("SELECT FirstName, LastName, Country, City, BirthDate")
               _T(" FROM Employee, Countries, Cities") 
               _T(" WHERE")
               _T(" Countries.CountryID = Employee.CountryID")
               _T(" AND Cities.CityID = Employee.CityID")
               _T(" AND LastName = '");
   strSelect += pszLastName; 
   strSelect += _T("' AND CountryID = ") + strCountryID
             + _T(" AND CityID = ") + strCityID
             + _T(" AND Salary < ") + strSalary
             + _T(" AND BirthDate = '") + pszBirthDate;
   strSelect += _T("'");
}
Metoda #2
Utilizam functia CString::Format.

Code: Select all

void CFoo::FormatSQL(CString& strSelect,
                     LPCTSTR pszLastName, UINT nCountryID,
                     UINT nCityID, UINT nSalary, LPCTSTR pszBirthDate)
{
   strSelect.Format(_T("SELECT FirstName, LastName, Country, City, BirthDate")
                    _T(" FROM Employee, Countries, Cities")
                    _T(" WHERE")
                    _T(" Countries.CountryID = Employee.CountryID")
                    _T(" AND Cities.CityID = Employee.CityID")
                    _T(" AND LastName = '%s'")
                    _T(" AND CountryID = %u")
                    _T(" AND CityID = %u")
                    _T(" AND Salary < %u")
                    _T(" AND BirthDate = '%s'"),
                    pszLastName,
                    nCountryID,
                    nCityID,
                    nSalary,
                    pszBirthDate);
}
Metoda #3
Apelam la std::stringstream.

Code: Select all

void CFoo::FormatSQL(CString& strSelect,
                     LPCTSTR pszLastName, UINT nCountryID,
                     UINT nCityID, UINT nSalary, LPCTSTR pszBirthDate)
{
   // note: tstringstream is defined as wstringstream if UNICODE;
   //                     else is defined as stringstream. 
   std::tstringstream ss;
   ss << _T("SELECT FirstName, LastName, Country, City, BirthDate")
         _T(" FROM Employee, Countries, Cities")
         _T(" WHERE")
         _T(" Countries.CountryID = Employee.CountryID")
         _T(" AND Cities.CityID = Employee.CityID ")
      << _T(" AND LastName = '") << pszLastName << "'" 
      << _T(" AND CountryID = ") << nCountryID
      << _T(" AND CityID = ") << nCityID
      << _T(" AND Salary < ") << nSalary
      << _T(" AND  BirthDate = '") << pszBirthDate << "'";

   strSelect = ss.str().c_str();
}
Metoda #4
Utilizam doar functii CRT si/sau raw Windows API.

Code: Select all

   // once we are using MFC, there is no time to waste for it... 
Un pic de analiza
  • #1 - Desi des folosita, este solutia pe care as alege-o cel mai rar. Rezulta cod incalcit, greu de modificat si de corectat. Nota: m-am staduit aici sa scriu cat de cat "frumos" ceea de in realitate nu fac intotdeauna toti programatorii.
  • #2 - Desi unii spun ca functia CString::Format este "lenta", scoate timpi comparabili cu #1, chiar mai buni, castigand teren cu cat avem mai multi parametri non-string. Principalul avantaj este ca am rezolvat totul dintr-un singur apel de functie, rezultand cod mai mic, mai clar si deci mai usor de tinut in mana.
  • #3 - Este cea mai lenta (in exemplul de mai sus a iesit cam de 3 ori mai puturoasa decat #2). Totusi, pare cea mai clara desi pentru formatari mai complexe s-ar putea sa se complice. As denumi-o "solutia carcalete" (carcalete = amestec de bauturi alcoolice care da dureri de cap).
  • #4 - Just forget it!
In loc de concluzie
Pana la prima sedinta de code inspection, fiecare are dreptul sa aleaga pe oricare dintre cele patru.

<< Back to MFC index



Post Reply