Задавайте вопросы, мы ответим
Вы не зашли.
Доброй ночи, Господа программисты!
Я понимаю что вопрос немного не по теми, но на других форумах умные молчат а те кто чуть больше меня знают мало что вразумительно отвечают, извините за отклонение от темы, но очень надо разобраться, косвенно всё равно связано с MySQL…
И так, есть файл:
(em0) BSD at Jun 24 01:40:47 - Jun 24 01:52:17
Summary: 19351337 data bytes, 20348509 all bytes, 7 records
From Port To Port Proto Data All
195.39.211.38 80 192.168.202.202 client tcp 16780399 17240403
204.152.184.112 80 192.168.202.202 client tcp 2293691 2360815
192.168.202.202 client 195.39.211.38 80 tcp 106 309166
192.168.202.202 22 192.168.202.1 client tcp 237812 304412
192.168.202.1 client 192.168.202.202 22 tcp 14436 63156
192.168.202.202 client 204.152.184.112 80 tcp 119 44939
217.69.128.43 80 192.168.202.202 client tcp 24774 25618
(em0) BSD at Jun 24 01:52:17 - Jun 24 01:57:22
Summary: 330456 data bytes, 377216 all bytes, 2 records
From Port To Port Proto Data All
192.168.202.202 22 192.168.202.1 client tcp 313452 335572
192.168.202.1 client 192.168.202.202 22 tcp 17004 41644
Нужно его открыть в и разобрать на 7 переменных, ну по колонкам, в примере что бы на экран вывести а в дальнейшем что бы в MySQL базу загнать!
Вот просто пример который просто выводит но меня не устраивает то, что у него не получается чётко на 7 переменных разбить((( Ну и разумеется хламовые строки такие как загловочный отбросить...
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main(void)
{
ifstream in("./foxtraf.em0");
if(!in)
{
cout <<"не получилось открыть файл! \n";
return 1;
}
string s1, s2, s3, s4, s5, s6, s7;
while(!in.eof())
{
in >> s1 >> s2 >> s3 >> s4 >> s5 >> s6 >> s7;
cout <<"| "<<s1<<"| " << s2<<"| " << s3<<"| " << s4<<"| " << s5<<"| " << s6<<"| " << s7 <<"\n";
}
in.close();
}
Он выводит безумие:
| (em0)| BSD| at| Jun| 24| 01:40:47| -
| Jun| 24| 01:52:17| Summary:| 19351337| data| bytes,
| 20348509| all| bytes,| 7| records| From| Port
| To| Port| Proto| Data| All| 195.39.211.38| 80
| 192.168.202.202| client| tcp| 16780399| 17240403| 204.152.184.112| 80
| 192.168.202.202| client| tcp| 2293691| 2360815| 192.168.202.202| client
| 195.39.211.38| 80| tcp| 106| 309166| 192.168.202.202| 22
| 192.168.202.1| client| tcp| 237812| 304412| 192.168.202.1| client
| 192.168.202.202| 22| tcp| 14436| 63156| 192.168.202.202| client
| 204.152.184.112| 80| tcp| 119| 44939| 217.69.128.43| 80
| 192.168.202.202| client| tcp| 24774| 25618| (em0)| BSD
| at| Jun| 24| 01:52:17| -| Jun| 24
| 01:57:22| Summary:| 330456| data| bytes,| 377216| all
| bytes,| 2| records| From| Port| To| Port
| Proto| Data| All| 192.168.202.202| 22| 192.168.202.1| client
| tcp| 313452| 335572| 192.168.202.1| client| 192.168.202.202| 22
| tcp| 17004| 41644| 192.168.202.1| client| 192.168.202.202| 22
Мне рекомендовали воспользоваться функцией split, но я не много не понимаю нет примеров что бы подсмотреть а я новичок нету опыта…
Посоветуйте или покажите пример толковый, за ранние спасибо!
Неактивен
Выводит оно не безумие, а ровно то, что Вы его "попросили" ).
Что Вы делаете в программе: считывайте построчно файл (пока файл не кончится), и из каждой строки берете семь подстрок (подстроки, разделены, видимо, пробелами (или знаками табуляции, по файлу вашему не вполне понятно)), потом выводите их на экран. Естественно, если в строке больше, чем 7 элементов, то результат не тот, что вы ожидаете (вернее выводит не так).
Я бы рекомендовал вам проверять каждую s1 на то, является ли она ip-адресом (как я понял, заголовки и прочее Вы хотите отсеять), и лишь если является - выводить на экран (ну или в базу писать, смотря что Вы дальше хотите делать).
Как это можно сделать:
while(!in.eof())
{
in >> s1 >> s2 >> s3 >> s4 >> s5 >> s6 >> s7;
if (inet_addr(s1.c_str())==INADDR_NONE) continue; // s1 не является ip-адресом, поэтому считаем очередную строку в надежде, что она окажется правильной
// Здесь могла быть Ваша реклама, точнее - дальше уже то, что считаете нужным - вывод на экран или написание в базу или еще что
mysql_query(...);
}
P. S. inet_addr порядком устарела, лучше использовать inet_pton (man inet_pton).
И не забудьте
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
(Это для Linux, для freebsd нужно ман смотреть)
P. P. S. Фанаты чистого c++ - не бейте по голове, я знаю, что рекомендую функции чистого c в c++-программе , но это один из самых простых способов определить валидность ip-адреса.
Отредактированно deadka (26.06.2010 13:55:15)
Неактивен
А Вам нужно именно на C++? Кажется, это все пишется на awk/perl куда быстрее.
Неактивен
Добрый день!
На Perl у меня уже есть, просто я пишу одну большую софтинку которая будет выполнять много задачь, перл высокого уровня и C++ его превзойдут по производительносте, но не это важно я изучаю С++ и по этому я стораюсь писать всё на С++, что бы быстрей научится чему-то...
Я последовал вашему совету и нашёл ман по inet_pton
http://www.opennet.ru/man.shtml?topic=i … %D4%D8+man
Но что то у меня не выходит вот пример:
[root@BSD /home/fox/wrk/fileopen]# cat ./test.cpp
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
using namespace std;
int main(void)
{
char s[1024];
int r;
int w;
cout <<"Enter IP host: ";
cin >> s;
//int inet_pton(int af, const char *src, void *dst);
r = inet_pton(w,s,NULL);
cout << r <<"| " <<s <<" "<<w<<"\n";
}
И вот всегда результат:
[root@BSD /home/fox/wrk/fileopen]# ./test
Enter IP host: 192.168.32.5
-1| 192.168.32.5 72
Он всегда -1 возрощает, где я что то не понял?
Спасибо за внимание!
Неактивен
Ну, во-первых:
В мануале (приведенном Вами же ;-) ) сказано:
Данная функция преобразует строку символов src в сетевой адрес (типа af)
На текущий момент поддерживаются следующие типы адресов:
AF_INET
src указывает на строку символов, содержащую сетевой адрес IPv4 в формате "ddd.ddd.ddd.ddd". Адрес преобразуется в struct in_addr и копируется в переменную dst, размер которой должен быть равен sizeof(struct in_addr) байтам.
AF_INET6
src указывает на строку символов, содержащую адрес сети IPv6 в разрешенном для сети IPv6 формате адреса. Адрес преобразуется в struct in6_addr и копируется в переменную dst, размер которой должен быть sizeof(struct in6_addr) байтов.
Вы же передаете переменную w, которая вообще ничем не инициализирована (то есть там может быть АБСОЛЮТНО любое значение), вот и возвращается ошибка.
То есть надо либо так:
r = inet_pton(AF_INET,...
либо
int w=AF_INET;
r = inet_pton(w,...
Во-вторых: (опять же из мануала) Данная функция преобразует строку символов src в сетевой адрес (типа af), затем копирует полученную структуру с адресом в dst.
Вы же третьим параметром передаёте NULL - функция попытается записать значение в NULL - и сегфолт обеспечен.
Так что Ваш код должен иметь примерно такой вид:
#include <iostream>
#include <string>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
using namespace std;
int main(void)
{
char s[1024];
struct sockaddr_in sa;
int r;
cout <<"Enter IP host: ";
cin >> s;
r = inet_pton(AF_INET,s,&sa);
cout << r <<"| " <<s <<" "<<w<<"\n";
return 0;
}
Отредактированно deadka (27.06.2010 13:38:00)
Неактивен
Огромное спасибо!
Вы лучшие, потому что на других форумах люди не доброжелательные, задают глупые вопросы а помочь даже не пытаются! А на вашем форуме мне уже в какой раз помогают преодолеть сложности, мои сложности может быть глупые но я только, только начинаю изучать, читаю С++ книжки, но практика это другое дело, её мне позарез не хватает!
А тут всегда помогут, направят, подскажут, ещё раз огромное человеческое спасибо!
Вот код, работает, делает так как надо:
Отредактированно fox (27.06.2010 18:07:40)
Неактивен
Вы приобрели опыт в С. В С++ пишут сетевые приложения с использованием
boost::asio
Неактивен
Добрый день!
А как бы написать валидацию ip с помощью boost::asio если конечно Вам не сложно?
Спасибо за внимание!
Неактивен
Подключать boost::asio для валидации IP - из пушки по воробьям )). Я, конечно, не знаю всей задачи, но пока Топикстартер обозначил лишь парсинг файла с логами; сетевым программированием здесь и не пахнет - просто имхо в контексте задачи проще всего было отсеять лишние строки именно такой проверкой.
Неактивен
Ясно!
Просто любопытно как будет выглядить код? Хотя бы для того примера:
Неактивен
А такой вопрос, я тут новенький в C/C++ насколько кретично, или считается правельным C и C++ смешивать?
Неактивен
Не сказал бы, что из пушки по воробьям. Это ж заголовочная библиотека — код
не увеличится в обьеме, но будет плюсатым с точки зрения идеологии
Смешивать код не критично совсем. Просто Вы пишете не на С++, а на С. Взять
хотя бы char s[1024]. Это заведомо плохо, т.к. переполнения и т.п.
Неактивен
Спасибо! :-)
А вот ещё вопросы:
1. Почему Вы используете std::cin а не using namespace std; ну а потом в коде писать просто cin?
2. Что производительней string или char масив? То-есть, что лучше использовать для продуктивности?
3. Почему вы не пишите void в скопках главной функции main?
Я просто стараюсь детально изучить, что бы понять философию принципа C++...
Шилд понятно объясняет но я без практики не всё понимаю, Страуструпа немогу найти что бы купить, дочитаю Шилда и кровь из носа найду, что бы прочитать, как все ссылаются что у него много философии...
Но всё равно у меня жутко практики не хватает!
Неактивен
1. Это, скорее, дело привычки
2. Смотря что Вы хотите получить. Объекты обычно обрабатывают медленнее,
чем их низкоуровневые аналоги. Но Вы не заметите разницы в производитель-
ности, конечно. Если Вас интересует производительность — надо писать на
ассемблере (только писать нормально, а не в процессе обучения, а то можно
и медленнее сделать ).
3. Это не обязательно, разумеется. Куда более интересный вопрос — почему
я написал const и ссылку при перехвате исключения
Почитайте Страуструпа, правда.
Неактивен
Из пушки по воробьям я говорил скорее в контексте разработки не только под linux ). Если пишем под windows (а тут уж извольте boost качать, собирать)) - то я бы скорее проверку сделал так, как указывал выше, дабы такую махину как буст не прикручивать к проекту ( даже отдельные части.) Идеологически - согласен, генерация исключения более плюсовой пример нежели возврат -1 ))), но платить размером в лишний мегабайт у exe-шника (ну или dll-ку большую с собой таскать...) за идеологию в данном случае я бы не стал ).
Между прочим, можно не использовать массив символов, а работать с объектом типа std::string, а в функцию inet_pton передавать c_str() от него - и не будет ошибок с переполнением.
int main(), а не void main() - см. стандарт - программа должна возвращать операционной системе код возврата.
Смешивание кода - если отбросить в сторону идеологию, то можно все. Только осторожно. А в случае смешивания кода c++ и чистого c - предельно осторожно ).
Отредактированно deadka (28.06.2010 16:19:12)
Неактивен
Спасибо!
Я понимаю что из пушки по воробьям но я больше интересуюсь написанием кодов, да бы понять их рработу...
FreeBSD не линух boost поставился за пару минут make config; make install clean и всё... не вопрос в общем, то что таскать пару метров я согласен, но изучить код куда ценней для меня чем написать саму прогу, я пишу потому-что иизучаю.
int main() в чом разница int main(void) ?
Спасибо за внимание!
Неактивен
Эм. Обсуждение становится совсем идеологическим
Готов возразить Под виндоус asio использовать тем более проще — WinAPI
предоставляет невменяемые интерфейсы (тот же inet_pton называется
WSAStringToAddressA), я бы сказал, бустовый интерфейс понятнее и милее
Неактивен
И ещё вопрос, а как правельно выбрать компилятор?
Например у BSD есть g++ или с++ или с99... Я использую g++ но это так от фоноря, как правильно выбирать компилятор?
Неактивен
Вероятность почти 100%, что c++ — это симлинка на g++ а c99 — это симлинка
на gcc
Всё, предлагаю тему закрыть, т.к. она к MySQL ну совсем никакого отношения
не имеет.
Неактивен
Хорошо, извините...
А Вы не думали расширить форум сделать подразделение C/C++?
Было бы здорово, потому что у вас одни из самых квалифицированных специалистов!
А вот не получается скомпелить:
[root@BSD /home/fox/wrk/fileopen]# g++ test2.cpp -o test2
test2.cpp: In function 'int main()':
test2.cpp:10: error: 'asio' has not been declared
test2.cpp:10: error: expected `;' before 'addr'
Это ваш код, для проверки ip на подленность при помощи boost...
Отредактированно fox (28.06.2010 16:39:07)
Неактивен
deadka уже предлагал. Как только согласится админить раздел на
webew.ru — сразу же заведем
celestia:~/build/tmp$ cat a.cc #include <iostream> #include <asio.hpp> int main() { std::string s; std::cin >> s; try { asio::ip::address addr = asio::ip::address::from_string(s); } catch (const std::exception &x) { std::cerr << "Bad IP: " << x.what() << std::endl; } } celestia:~/build/tmp$ g++ a.cc -lpthread celestia:~/build/tmp$ echo 1.2.3.4 | ./a.out celestia:~/build/tmp$ echo 1.2.3. | ./a.out Bad IP: Invalid argument
Неактивен
Добрый вечер!
Извините, что я пишу не по теми, и не в нужном месте но очень надо, вторые сутки бьюсь голов об стену не могу понять как это так…
Вот код:
Неактивен
Ох. Срочно сотрите, чтобы это никто не видел
Когда пишете на С, надо очень хорошо следить за выделением памяти.
Например, когда Вы скармливаете strftime число 80, вы должны перед
этим выделить 80 байт в буффер. А потом, соответственно, освободить.
То, что оно не падает на первом вызове, — случайность
Возвращать char* из функции — тоже жуткая штука. Вы должны тогда
освободить память не внутри функции, а снаружи. Ну и пользуйтесь
printf, cout — это другой язык
Неактивен
Я знал, что вы незабудите меня, Спасибо!
А можно поподробней, я подозревал, что я напутал с указателями, тут я ещё очень слаб и знаю из книжки, что можно память покрашит, а как правильно переписать? Как правельно возврощать char массив?
Помогите а то у меня уже нет сил боротся, удилите пожалуйста внимание указателям и возрату массива а то я совсем запутался в последнее время, читаю книгу вроде понимаю начинается практика ничего не понимаю, а Вы очень грамотно объясняете тогда я чотко понимаю!
Спасибо за внимание!
Неактивен
Ну, если Вы читаете книжку по С, то читаете ее недостаточно внимательно
Неактивен