Другое решение, подобное ответу Локи Астари , в C ++ 11. Строки здесь std::tuple
s данного типа. Код сканирует одну строку, затем сканирует до каждого разделителя, а затем преобразует и выгружает значение непосредственно в кортеж (с битом кода шаблона).
for (auto row : csv(file, ',')) {
std::cout << "first col: " << std::get<0>(row) << std::endl;
}
Авансы:
std::tuple
через operator>>
. Что отсутствует:
Основной код:
#include
#include
#include
namespace csvtools {
/// Read the last element of the tuple without calling recursively
template
typename std::enable_if= std::tuple_size>::value - 1>::type
read_tuple(std::istream &in, std::tuple &out, const char delimiter) {
std::string cell;
std::getline(in, cell, delimiter);
std::stringstream cell_stream(cell);
cell_stream >> std::get(out);
}
/// Read the @p idx-th element of the tuple and then calls itself with @p idx + 1 to
/// read the next element of the tuple. Automatically falls in the previous case when
/// reaches the last element of the tuple thanks to enable_if
template
typename std::enable_if>::value - 1>::type
read_tuple(std::istream &in, std::tuple &out, const char delimiter) {
std::string cell;
std::getline(in, cell, delimiter);
std::stringstream cell_stream(cell);
cell_stream >> std::get(out);
read_tuple(in, out, delimiter);
}
}
/// Iterable csv wrapper around a stream. @p fields the list of types that form up a row.
template
class csv {
std::istream &_in;
const char _delim;
public:
typedef std::tuple value_type;
class iterator;
/// Construct from a stream.
inline csv(std::istream &in, const char delim) : _in(in), _delim(delim) {}
/// Status of the underlying stream
/// @{
inline bool good() const {
return _in.good();
}
inline const std::istream &underlying_stream() const {
return _in;
}
/// @}
inline iterator begin();
inline iterator end();
private:
/// Reads a line into a stringstream, and then reads the line into a tuple, that is returned
inline value_type read_row() {
std::string line;
std::getline(_in, line);
std::stringstream line_stream(line);
std::tuple retval;
csvtools::read_tuple<0, fields...>(line_stream, retval, _delim);
return retval;
}
};
/// Iterator; just calls recursively @ref csv::read_row and stores the result.
template
class csv::iterator {
csv::value_type _row;
csv *_parent;
public:
typedef std::input_iterator_tag iterator_category;
typedef csv::value_type value_type;
typedef std::size_t difference_type;
typedef csv::value_type * pointer;
typedef csv::value_type & reference;
/// Construct an empty/end iterator
inline iterator() : _parent(nullptr) {}
/// Construct an iterator at the beginning of the @p parent csv object.
inline iterator(csv &parent) : _parent(parent.good() ? &parent : nullptr) {
++(*this);
}
/// Read one row, if possible. Set to end if parent is not good anymore.
inline iterator &operator++() {
if (_parent != nullptr) {
_row = _parent->read_row();
if (!_parent->good()) {
_parent = nullptr;
}
}
return *this;
}
inline iterator operator++(int) {
iterator copy = *this;
++(*this);
return copy;
}
inline csv::value_type const &operator*() const {
return _row;
}
inline csv::value_type const *operator->() const {
return &_row;
}
bool operator==(iterator const &other) {
return (this == &other) or (_parent == nullptr and other._parent == nullptr);
}
bool operator!=(iterator const &other) {
return not (*this == other);
}
};
template
typename csv::iterator csv::begin() {
return iterator(*this);
}
template
typename csv::iterator csv::end() {
return iterator();
}
Я поставил крошечный рабочий пример на GitHub ; Я использовал его для разбора некоторых числовых данных, и он служил своей цели.
Вы можете посмотреть на /sys/class/net/eth0/operstate
, где eth0 - ваш интерфейс, чтобы увидеть, поднят ли он.
Посмотрите на /sys/class/net/eth0/carrier
, чтобы узнать, есть ли носитель.
Хотя я полагаю, что выполнение ifconfig
и друзей даст вам больше совместимости с *BSD.
Помните, что в Linux «все» - это файл.
Лучшим способом было бы использовать одобренную связь ядра <-> в пользовательском пространстве, а именно sysfs
, смонтированную в / sys
. Сетевые устройства связаны в / sys / class / net
. Если вы хотите использовать интерфейс ioctl
, посмотрите man netdevice
Как вы хотите идентифицировать сетевую карту? Вы можете попробовать взглянуть на /etc/udev/rules.d/70-persistent-net.rules
, который преобразует аппаратные MAC-адреса в красивые имена (например, eth0).
Затем, когда у вас будет более удачное имя, вы можете запустить такие вещи, как ethtool eth0
, чтобы определить, [физически] ли он подключен (последняя строка), ifconfig eth0
, чтобы определить, если он активен (ищите "UP BROADCAST ..."), и если у него есть IP-адрес.
Я готов предположить, что для этого есть автоматические библиотеки; ты огляделся? Я не уверен, есть ли в NetworkManager легкодоступный код, но это должно быть хорошим первым местом для поиска.
Выполните вывод getifaddrs
, вы можете использовать канальный уровень для MAC-адреса, чтобы идентифицировать адаптер и проверить ifa_flags
для IFF_UP. Используйте AF_NETLINK
для уведомлений об изменениях интерфейса.