2 Mayıs 2019 Perşembe

conversion lexical_cast

Giriş
Şu satırı dahil ederiz.
#include <boost/lexical_cast.hpp>
String'e Çevirme - boost::chrono::nanoseconds
Şöyle yaparız.
#include <iostream>
#include <string>
#include "boost/lexical_cast.hpp"
#include "boost/chrono.hpp"

int main()
{
  boost::chrono::nanoseconds test1{1000}; // could use long long here directly
  auto text = boost::lexical_cast<std::string>(test1);
  std::cout << text << '\n';
  auto val = boost::lexical_cast<boost::chrono::nanoseconds>(text);
  std::cout << val << '\n';
}
Çıktı olarak şunu alırız.
1000 nanoseconds
1000 nanoseconds
String'e Çevirme - double
Altta sprintf() çağrısını kullanır. Şöyledir.
sprintf(begin, 
  "%.*g", static_cast<int>(boost::detail::lcast_get_precision<double>()), val);
lexical_cast string çıktısını formatlama konusunda iyi değil. O yüzden tavsiye etmem. Açıklaması şöyle
For more involved conversions, such as where precision or formatting need tighter control than is offered by the default behavior of lexical_cast, the conventional std::stringstream approach is recommended.
Örnek
Şöyle yaparız.
std::wcout << boost::lexical_cast<std::wstring>(5.453) << std::endl;
Çıktı olarak şunu alırız.
5.4530000000000003
Örnek
detail isim alanını kullanarak şöyle yaparız.
#include <boost/lexical_cast.hpp>

#ifdef BOOST_LCAST_NO_COMPILE_TIME_PRECISION
#    error unsupported
#endif

template <>
struct boost::detail::lcast_precision<double> : std::integral_constant<unsigned, 5> { };


std::cout << boost::lexical_cast<std::string>(0.0009) << std::endl;
Çıktı olarak şunu alırız.
0.0009
String'e Çevirme - Kendi Sınıfımız
Sınıfımız için tanımladığımız << operatörü çağrılır.
Örnek
Şöyle yaparız.
namespace Nodes {
  struct Building { std::string id; };

  static inline std::ostream& operator<<(std::ostream& os, Building const& b)
  { return os << "Building " << b.id; }
  ...
  
}
Şöyle yaparız.
boost::lexical_cast<std::string>(building);
Örnek
Ya da yardımcı sınıf kullanırız. Şöyle yaparız.
template <typename Container>
struct pipe_manip {
  Container const& _data;

  friend std::ostream& operator<<(std::ostream& os, pipe_manip const& manip) {
    bool first = true;
    for(auto& i : manip._data) {
      if (!first) os << "|";
      first = false;
      os << i;
    }
    return os;
  }
};

template <typename Container>
pipe_manip<Container> as_pipe(Container const& c) { return {c}; }
Şöyle yaparız.
std::vector<uint> s { {1,2,3,4,5} };
std::cout << "Source is " << as_pipe(s) << "\n";

std::string text = boost::lexical_cast<std::string>(as_pipe(
  std::set<std::string>{"foo", "bar", "qux"}));
std::cout << "Other containers work too: " << text << "\n";
Çıktı olarak şunu alırız.
Source is 1|2|3|4|5
Other containers work too: bar|foo|qux
Örnek
Elimizde şöyle bir kod olsun. Kendi sınıfımız için tanımlı operator exception fırlattığı için boost::lexical_cast başarısız olur.
enum class MyType {};

std::ostream& operator<<( std::ostream&, MyType const& )
{
  throw "error";
}

int main()
{
  try 
  {
    boost::lexical_cast< std::string >( MyType{} );
  }
  catch(...)
  {
    std::cout << "lexical_cast exception";
  }
}
String'den Okuma - double 
Bilimsel formatlı stringler çevrilebilir. Şöyle yaparız.
std::string     val = "2.12e-6";
double y = boost::lexical_cast<double>(val);
wstring'den çevirmek için şöyle yaparız.
std::wstring t = L"91.25";
float r = boost::lexical_cast<float>(t);
String'den Okuma - short
Şöyle yaparız.
short myInt = boost::lexical_cast<short>(*argv);
std::string backToString = boost::lexical_cast<std::string>(myInt);
String'den Okuma - Kendi Sınıfımız
Şöyle yaparız. Sınıfımız için yazdığımız >> operatörünün N isim alanı içinde olması gerekir.
namespace N {
  enum class alarm_code_t {
    BLAH
  };

  std::istream& operator>>(std::istream& is, N::alarm_code_t& code) {
    std::string tmp;
    is >> tmp;

    if (tmp == "BLAH")
        code = N::alarm_code_t::BLAH;
    else
        is.setstate(std::ios::failbit);

    return is;
  }
}

int main() {
  auto code = boost::lexical_cast<N::alarm_code_t>("BLAH");
}
String'den Okuma - Boost Yoksa
Eğer elimizde boost yoksa çok basit bir şekilde şöyle yaparız.
#include <sstream>
#include <iostream>
#include <string>
#include <stdexcept>

template<typename T>
T ConvertStringToNumber(const std::string& str)  
{  
  std::istringstream ss(str);  
  T number = 0;  

  ss >> number;  

  if (ss.fail( )) 
  {
    throw std::invalid_argument("ConvertStringToNumber:" + str);
  }

   return number;  
}

int main(int argc, char argv[]){
  std::string num_str = "10.5";
  float f = ConvertStringToNumber<float>(num_str);

  std::cout << f << std::endl;

  return 0;
}
bad_lexical_cast exception Sınıfı
Şöyle tanımlı. Dolayısıyla sadece std::exception olarak yakalamak mümkün.
class bad_lexical_cast : public std::bad_cast

Eğer istersek kendisini de yakalayabiliriz.
catch (const boost::bad_lexical_cast& e)
{
  std::cout << "Exception: " << e.what() << "\n";
}
Çıktı olarak şunu verir.
Exception: bad lexical cast: source type value could not be interpreted as target

3 Ocak 2019 Perşembe

graph kruskal_minimum_spanning_tree

Giriş
Kruskal algoritması "Disjoint set" ile gerçekleştirilebilir. Açıklaması şöyle
Path compression and other optimizations like union-by-rank should be applied any time you call the find operation on your disjoint-set forest.

One way to see this: from the perspective of Kruskal's algorithm, you just need to be able to call find and union and have them work correctly. You shouldn't need to worry about the details of how you're making find and union work correctly, just that they do. It's the responsibility of the disjoint-set forest to ensure that everything runs quickly, and so the calls to find are where you'll see the compression occurring.
İmzası şöyle
template <class Graph, class OutputIterator, class P, class T, class R>
OutputIterator kruskal_minimum_spanning_tree(
  Graph& g, 
  OutputIterator tree_edges, 
  const bgl_named_params<P, T, R>& params = all defaults
);
Örnek
Bir graph'ın weight alanlarına bakarak çalışır. Dolayısıyla weight map verilmesi gerekir. Şöyle yaparız
typedef adjacency_list<vecS, vecS, undirectedS, 
                       property<vertex_name_t,char>,
                       property<edge_weight_t,float>
                      > InternalPropGraph;


vector<edge_t> mst;
kruskal_minimum_spanning_tree(g, std::back_inserter(mst), 
                        weight_map( get(&Edge::weight, g) );


25 Aralık 2018 Salı

BOOST_SCOPE_EXIT Macrosu

Örnek
Şöyle yaparız.
auto prevState{currState};
currState = newState;
BOOST_SCOPE_EXIT(&currState, &prevState)
{
  currState = prevState;
} BOOST_SCOPE_EXIT_END