decvar
написал 17 июня 2004 года в 23:27 (1015 просмотров)
Ведет себя
как мужчина; открыл 111 тему в форуме, оставил 1838 комментариев на сайте.
Есть штук пять строк(char*) задача обьединить в одну. И так и эдак я strcat вертел, что-то оно не того…..
char* qwe="qwe"; char* asd="asd"; char* zxc="zxc"; char* result = ....?
Попутно педложения, по тому как распарсить вывод некой консольной команды в stdout. Запихав его в 3 массива. Вывод вида:
goo1 goo2 goo3 ----- ------ ------ inf11 inf21 inf31 inf12 inf22 inf32 ..... .... ....
соответствеено, массив для inf1X inf2X и inf 3X.
Последние комментарии
- OlegL, 17 декабря 2023 года в 15:00 → Перекличка 21
- REDkiy, 8 июня 2023 года в 9:09 → Как «замокать» файл для юниттеста в Python? 2
- fhunter, 29 ноября 2022 года в 2:09 → Проблема с NO_PUBKEY: как получить GPG-ключ и добавить его в базу apt? 6
- Иванн, 9 апреля 2022 года в 8:31 → Ассоциация РАСПО провела первое учредительное собрание 1
- Kiri11.ADV1, 7 марта 2021 года в 12:01 → Логи catalina.out в TomCat 9 в формате JSON 1
ecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.
Этого вопроса я что-то не понял… Прога табличку выводит, а тебе ее в массив загнать надо? Ну, читай по строкам и разделяй по разделителю, что он там, таб или пробел?
Good Luck,
UT
1) snprintf
2) strsep (хотя многие говорят, что оно сосет)
в первым сам уже разобрался
Во втором:
Как пропарсить я и так понимаю, strtok по строкам лексемы мне отдаст. Только не ясно вот что. Сделаю я
Как мне получить ее вывод в буффер, что бы его(буфер) парсить?
Продублирую:
popen + fscanf
или popen + fgets + strsep
вообщем со вторым подразобрался
Только это отдает мне первую строку, до \0. Как и должно по описанию. А мне нужны все строки, начиная с той, где есть слово «Server».
Что-то не пойму как это сделать?
Стандартный вариант:
#define KEY «Server»
while (!feof(out_stream)) {
fgets (output,1024,out_stream);
if (strstr (output, (KEY)))
do_something();
}
итп
есть еще dup2 для связываения потоков. С его помощью мона присосацца к выходному потоку проги и читать из него :)
позняк метаться, проблема уже решена. Хотя dup2 может пригодиться потом.
[man]
dup and dup2 create a copy of the file descriptor oldfd.
[/man]
Кто-нить может объяснить почему этот код дает SegFault?
Выдели память под result.
Good Luck,
UT
Это первое что я делал.
не спасают.
Кстати, по 'man stpsep' память выделять не нужно
Вы правы, выделять память не надо. Кстати Вы выделили место на 1 указатель только.
strsep пытается написать в const область памяти поэтому все и валится
Вам надо сделать что-то вроде
char buf[ BUFSZ ];
strncpy( buf, output, BUFSZ — 1 );
buf[ BUFSZ - 1 ] = '\0\′;
Потом strsep на buf (кстати strsep не очень переносим)
Успехов
— sas
Прошу прощения за предидущий пост — случайно отправил.
К сожалению Ваш код имеет некоторые недостатки:
1. Под result выделено место под 1 char, т.е. при записи по этому указателю мы будем перезаписывать «чужую» память
2. malloc в отличии от calloc не обнуляет память, следовательно выделенная память может содержать мусор. str(n)cat пытается найти '\0\′ в области памяти на которую указывает result.
Здесь есть 2 возможности:
a) Находит и добавляет начиная с этой позиции, а позиция может быть уже и вне выделенной памяти…
b) Не находит вообще и тогда я не знаю что будет. Наверное зависит от реализации. man ничего об этом не говорит
Должно быть что-то вроде:
char *ss[] = { «111111», «22222», «3333», «44444», NULL };
char **p = ss;
char *res;
int l = 0;
/* — pass 1 to allocate memory — */
while ( *p ) l += strlen( *p++ );
l += 1; /* for final '\0\′ */
res = (char *)malloc( l * sizeof( char ) );
if ( NULL == res )
fprintf( stderr, «malloc failed!!!» );
else {
res[ 0 ] = '\0\′;
p = ss;
while ( *p ) strcat( res, *p++ );
fprintf( stdout, «Result [%s]\n», res );
}
Успехов
— sas
ЗЫ Код не тестирован, тоже может быть с ошибками :(
Я пробовал выделять и 1024. Не спасоало, да это и не важно.
это в const chat* separator ? А зачем он туда пишет?
Мне надо парсить именно char*. Я даже не знаю его размер. Я получаю его из
1. Прочитайте man strsep внимательно. Вот он что примерно делает:
**параметр_1 — указатель на указатель
*результат = *параметр_1
пока не конец строки
если символ == разделитель, то
вместо него пишем '\0\′
если следующий за найденым разделтелем символ == '\0\′
*параметр_1 = NULL
если не конец строки, то
*параметр_1 передвигаем на следующий символ за перезаписаным разделителем
возвращаем *результат
если не разделитель идем в начало цикла
конец пока
Алгоритм не полон и служит для пояснения того как strsep ИЗМЕНЯЕТ исходную строку
Конечно увеличение выделенной памяти Вам не помогло. Просто выделять динамически 1 байт всегда очень не выгодно. Выделение/освобождение памяти дорогостоящая операция. Кроме того существует так называемая фрагментация памяти, но это тема отдельного разговора (пулы памяти и т.д.)
На самом деле Вам вообще нет никакого резона пользоваться malloc
В чем разнится между
char *buf = (char*)malloc( 100 * sizeof( char ) );
и
char buf[ 100 ];
???
Мой прошлый пример объяснял проблему в Вашем коде когда char *output указаывает на НЕИЗМЕНЯЕМУЮ область памяти
char* output="one two»;
В Вашем коде присланном в этом посте Вы не показали части которая отвечает за разбор строки.
Удачи
— sas
В моем коде мне надо парсить полученый в вложеном while{ }
char* output;
я предполагал это делать так:
Так как мне тогда парсить полученый char* output?
PS
Шуруп, сделай что-нить, что бы сохранялось форматирование, может fixed использовать для отображения и ввода?
вот маленький набросок кода для strsep
#include
#include
#include
#define BUFSZ 50
#define QUIT_TOKEN «quit»
/*
* instead of file we will use stdin like a data source.
*
* Since i do not want to play with GList etc i will print results to the STDOUT
*/
int main( int argc, char **argv )
{
const char delim[] = «\t»;
char buf[ BUFSZ ];
size_t l = strlen( QUIT_TOKEN );
char *c1, *c2, *p, **pp;
fprintf( stdout, «Please type \«%s\» (no double quotes around) to exit.\nExpecting string with 2 parts delimited by tab\n\n», QUIT_TOKEN );
while ( 1 ) {
p = fgets( buf, BUFSZ, stdin );
if ( !strncmp( p, QUIT_TOKEN, l ) ) break;
if ( strchr( p, '\t' ) ) {
pp = &p;
c1 = strsep( pp, delim );
c2 = strsep( pp, delim );
fprintf( stdout, «Column 1 =[%s]\tColumn 2 = [%s]\n», c1, c2 );
}
else
fprintf( stderr, «Wrong string in input!!! [%s]\n», buf );
}
return 0;
}
Удачи
— sas
А так даже лучше :)
#include
#include
#include
#define BUFSZ 50
#define QUIT_TOKEN «quit»
/*
* instead of file we will use stdin like a data source.
*
* Since i do not want to play with GList etc i will preint results to the STDOUT
*/
int main( int argc, char **argv )
{
const char delim[] = «\t»;
char buf[ BUFSZ ];
size_t l = strlen( QUIT_TOKEN );
char *c1, *c2, *p;
fprintf( stdout, «Please type \«%s\» (no double quotes around) to exit.\nExpecting string with 2 parts delimited by tab\n\n», QUIT_TOKEN );
while ( 1 ) {
fgets( buf, BUFSZ, stdin );
p = (char *)buf;
if ( !strncmp( p, QUIT_TOKEN, l ) ) break;
if ( strchr( p, '\t' ) ) {
c1 = strsep( &p, delim );
c2 = strsep( &p, delim );
fprintf( stdout, «Column 1 =[%s]\tColumn 2 = [%s]\n», c1, c2 );
}
else
fprintf( stderr, «Wrong string on input!!! [%s]\n», p );
}
return 0;
}
Вообще говорят, что strsep и strtok не очень рулят, вследствие своих бестолковых \0. Имхо гораздо лучше и удобнее воспользоваться хитрой форматной строкой для fscanf — что-то типа «%[^ ]s»
вот этот код у меня в конце делает SegFault.
output.txt
http://people.linux-online.ru/decvar/files/output.txt
Попробуйте это:
#include
#include
#include
#define BUFSZ 50
#define KEY «Server»
#define QUIT_TOKEN «quit»
typedef enum { false, true } bool;
int main( int argc, char **argv )
{
const char delim[] = «\t»;
char buf[ BUFSZ ];
char *c1, *c2, *output;
FILE* out_stream;
bool is_after_key = false;
out_stream=popen(«cat /Users/sas/tmp/output.txt«,»r»);
if ( NULL == out_stream ) {
fprintf( stderr, «popen failed!\n» );
}
else {
while ( !feof(out_stream)){
output = fgets(buf,BUFSIZ,out_stream);
if ( output ) {
if(false == is_after_key && strstr(output,KEY))
is_after_key = true;
if ( is_after_key ) {
if ( strchr( output, '\t' ) ) {
c1 = strsep( &output, delim );
c2 = strsep( &output, delim );
fprintf( stdout,
«Column 1 =[%s]\tColumn 2 = [%s]\n», c1, c2 );
}
else
fprintf( stderr, «Wrong string in input!!! [%s]\n», output );
}
}
else {
if ( feof( out_stream ) )
fprintf( stderr, «EOF\n» );
else if ( ferror( out_stream ) ) {
perror( «fgets failed » );
}
}
}
pclose( out_stream );
}
return 0;
}
Советую не забывать про проверки возвращаемых значений
Успехов
— sas
Он не туда пишет. Он пишет в '\0\′ туда, где нашел разделитель. В данном случае, в тело строки «one two», которая размещена в read-only области.
Это совершенно другой разговор. Здесь тоже segfault? Если да, то причины ему другие.
Здесь Сегфолта нет.
Всем спасибо — проблема решена.
Прошу прощения за предыдущий пост.
Здесь проблема в том, что !feof() не гарантирует успеха последующего fgets(). Порядок примерно такой: fgets читает последнюю строку потока. Попытки чтения за пределами файла не было. При следующем обороте цикла feof говорит, что все в порядке. fgets натыкается на конец файла, не прочтя ничего, и возвращает 0 (вот теперь feof вернет не-ноль). Этот 0 программа пытается разобрать, и погибает.
Поэтому, вместо
рекомендую