nixp.ru v3.0

18 января 2017,
среда,
04:46:30 MSK

DevOps с компанией «Флант»
decvar написал 17 июня 2004 года в 23:27 (462 просмотра) Ведет себя как мужчина; открыл 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.

Uncle Theodore
decvar
Есть штук пять строк(char*) задача обьединить в одну. И так и эдак я strcat вертел, что-то оно не того…..

char* qwe="qwe";
char* asd="asd";
char* zxc="zxc";
char* result = ....?



char* qwr = "qwr";
  char* asd = "asd";
  char* zxc="zxc";
  char *result = (char*)malloc(sizeof(char));
  strcat(result, qwr);
  strcat(result, asd);
  strcat(result, zxc);
//Or, in one giant step
  strcat(strcat(strcat(result, qwr), asd), zxc);


Попутно педложения, по тому как распарсить вывод некой консольной команды в stdout. Запихав его в 3 массива. Вывод вида:

goo1     goo2                goo3
-----           ------          ------
inf11     inf21     inf31
inf12     inf22     inf32
.....           ....         ....

соответствеено, массив для inf1X inf2X и inf 3X.

Этого вопроса я что-то не понял… Прога табличку выводит, а тебе ее в массив загнать надо? Ну, читай по строкам и разделяй по разделителю, что он там, таб или пробел?

Good Luck,

UT

1) snprintf

2) strsep (хотя многие говорят, что оно сосет)

decvar

в первым сам уже разобрался

Во втором:

Как пропарсить я и так понимаю, strtok по строкам лексемы мне отдаст. Только не ясно вот что. Сделаю я

system("/bin/prog");

Как мне получить ее вывод в буффер, что бы его(буфер) парсить?

Продублирую:

popen + fscanf

или popen + fgets + strsep

decvar

вообщем со вторым подразобрался

FILE* out_stream;
char* output=(char*)malloc(1024);
out_stream = popen(command,"r");
fgets(output,1024,out_stream);
printf("%s",output);

Только это отдает мне первую строку, до \0. Как и должно по описанию. А мне нужны все строки, начиная с той, где есть слово «Server».

Что-то не пойму как это сделать?

Стандартный вариант:

#define KEY «Server»

while (!feof(out_stream)) {

fgets (output,1024,out_stream);

if (strstr (output, (KEY)))

do_something();

}

итп

Longobard

есть еще dup2 для связываения потоков. С его помощью мона присосацца к выходному потоку проги и читать из него :)

decvar

позняк метаться, проблема уже решена. Хотя dup2 может пригодиться потом.

[man]

dup and dup2 create a copy of the file descriptor oldfd.

[/man]

decvar

Кто-нить может объяснить почему этот код дает SegFault?

#include 
                                                                                                                                              
int main()
{
char* result;
char* output="one two";
const char* separator=" ";
                                                                                                                                              
result = strsep(&output,separator);
                                                                                                                                              
                                                                                                                                              
printf("%s",result);
return 0;
                                                                                                                                              
}
Uncle Theodore
decvar
Кто-нить может объяснить почему этот код дает SegFault?

#include 
                                                                                                                                              
int main()
{
char* result;
char* output="one two";
const char* separator=" ";
                                                                                                                                              
result = strsep(&output,separator);
                                                                                                                                              
                                                                                                                                              
printf("%s",result);
return 0;
                                                                                                                                              
}

Выдели память под result.

Good Luck,

UT

decvar

Это первое что я делал.

char* result = (char*)malloc(sizeof(char*)); /* (char*)malloc(1024); */

не спасают.

Кстати, по 'man stpsep' память выделять не нужно

sas
decvar
Это первое что я делал.

char* result = (char*)malloc(sizeof(char*)); /* (char*)malloc(1024); */

не спасают.

Кстати, по 'man stpsep' память выделять не нужно

Вы правы, выделять память не надо. Кстати Вы выделили место на 1 указатель только.

strsep пытается написать в const область памяти поэтому все и валится

Вам надо сделать что-то вроде

char buf[ BUFSZ ];

strncpy( buf, output, BUFSZ — 1 );

buf[ BUFSZ - 1 ] = '\0\′;

Потом strsep на buf (кстати strsep не очень переносим)

Успехов

— sas

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

ЗЫ Код не тестирован, тоже может быть с ошибками :(

Uncle Theodore

char* qwr = "qwr";
  char* asd = "asd";
  char* zxc="zxc";
  char *result = (char*)malloc(sizeof(char));
  strcat(result, qwr);
  strcat(result, asd);
  strcat(result, zxc);
//Or, in one giant step
  strcat(strcat(strcat(result, qwr), asd), zxc);

Этого вопроса я что-то не понял… Прога табличку выводит, а тебе ее в массив загнать надо? Ну, читай по строкам и разделяй по разделителю, что он там, таб или пробел?

Good Luck,

UT

decvar
sas
Вы правы, выделять память не надо. Кстати Вы выделили место на 1 указатель только.

Я пробовал выделять и 1024. Не спасоало, да это и не важно.

strsep пытается написать в const область памяти поэтому все и валится

это в const chat* separator ? А зачем он туда пишет?

Вам надо сделать что-то вроде

char buf[ BUFSZ ];

strncpy( buf, output, BUFSZ — 1 );

buf[ BUFSZ - 1 ] = '\0\′;

Потом strsep на buf (кстати strsep не очень переносим)

Мне надо парсить именно char*. Я даже не знаю его размер. Я получаю его из

.....
char* command =(char*)malloc(100);
          FILE* out_stream;
        char* output=(char*)malloc(100);
....
....
                out_stream=popen("my_command","r");
                while (!feof(out_stream)) {
            fgets (output,100,out_stream);
            if (strstr (output, (KEY))){
                  g_print("Found KEY line. Beging dump.\n"); //Print it
                  g_print("Moveing to next line to dump.\n");
                  
                  //Writing output lines
                  while (!feof(out_stream)){
                        fgets(output,100,out_stream);
                        g_print("%s",output);
                        //
                        //            Здесь парсим вывод
                        //                        и фигачим их в массив(два)
                        //
                  }
   }
}
sas

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

decvar
Я пробовал выделять и 1024. Не спасоало, да это и не важно.

это в const chat* separator ? А зачем он туда пишет?

Мне надо парсить именно char*. Я даже не знаю его размер. Я получаю его из

.....
char* command =(char*)malloc(100);
          FILE* out_stream;
        char* output=(char*)malloc(100);
....
....
                out_stream=popen("my_command","r");
                while (!feof(out_stream)) {
            fgets (output,100,out_stream);
            if (strstr (output, (KEY))){
                  g_print("Found KEY line. Beging dump.\n"); //Print it
                  g_print("Moveing to next line to dump.\n");
                  //Writing output lines
                  while (!feof(out_stream)){
                        fgets(output,100,out_stream);
                        g_print("%s",output);
                        //
                        //            Здесь парсим вывод
                        //                        и фигачим их в массив(два)
                        //
                  }
   }
}

decvar

В моем коде мне надо парсить полученый в вложеном while{ }

char* output;

я предполагал это делать так:

.....
         char* tmp;
        char* command =(char*)malloc(100);
          FILE* out_stream;
        char* output=(char*)malloc(100);
         GList* list_name=NULL;
          GList* list_info=NULL;
....
....
                out_stream=popen("my_command","r");
                while (!feof(out_stream)) {
            fgets (output,100,out_stream);
            if (strstr (output, (KEY))){
                  g_print("Found KEY line. Beging dump.\n"); //Print it
                  g_print("Moveing to next line to dump.\n");
                  
                  //Writing output lines  
                  while (!feof(out_stream)){
                        fgets(output,100,out_stream);
                        g_print("%s",output);
                     /* вывод команды после KEY представляет собой
                           out11      out12
                           out12      out22
                                 ...........
                          разделеные табом */
                        tmp=strsep(&output,"\t"); //первая часть до \t
                         list_name=g_list_append(list_name,tmp); //записываем в список      
  
                         tmp=stpsep(&output,"\t"); // то что после \t
                       list_info=g_list_append(list_info,tmp); // тоже пишем в другой список
                  }// след. строка вывода.
   }
}

Так как мне тогда парсить полученый char* output?

PS

Шуруп, сделай что-нить, что бы сохранялось форматирование, может fixed использовать для отображения и ввода?

sas

вот маленький набросок кода для 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

decvar
В моем коде мне надо парсить полученый в вложеном while{ }

char* output;

я предполагал это делать так:

.....
         char* tmp;
        char* command =(char*)malloc(100);
          FILE* out_stream;
        char* output=(char*)malloc(100);
         GList* list_name=NULL;
          GList* list_info=NULL;
....
....
                out_stream=popen("my_command","r");
                while (!feof(out_stream)) {
            fgets (output,100,out_stream);
            if (strstr (output, (KEY))){
                  g_print("Found KEY line. Beging dump.\n"); //Print it
                  g_print("Moveing to next line to dump.\n");
                  //Writing output lines
                  while (!feof(out_stream)){
                        fgets(output,100,out_stream);
                        g_print("%s",output);
                     /* вывод команды после KEY представляет собой
                           out11      out12
                           out12      out22
                                 ...........
                          разделеные табом */
                        tmp=strsep(&output,"\t"); //первая часть до \t
                         list_name=g_list_append(list_name,tmp); //записываем в список
                         tmp=stpsep(&output,"\t"); // то что после \t
                       list_info=g_list_append(list_info,tmp); // тоже пишем в другой список
                  }// след. строка вывода.
   }
}

Так как мне тогда парсить полученый char* output?

PS

Шуруп, сделай что-нить, что бы сохранялось форматирование, может fixed использовать для отображения и ввода?

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»

decvar

вот этот код у меня в конце делает SegFault.

#include 
#include 
#include 
                                                                                                                                              
#define BUFSZ   50
#define KEY "Server"
#define QUIT_TOKEN  "quit"
                                                                                                                                              
int main( int argc, char **argv )
{
  const char delim[] = "\t";
  char buf[ BUFSZ ];
  char *c1, *c2, *output, **out_ptr;
   FILE* out_stream;
                                                                                                                                              
  out_stream=popen("cat output.txt","r");
                                                                                                                                              
  while ( !feof(out_stream)){
  output= fgets(buf,BUFSIZ,out_stream);
                                                                                                                                              
  if(strstr(output,KEY)){
                                                                                                                                              
   while ( !feof(out_stream) ) {
    output = fgets( buf, BUFSZ, out_stream );
    if ( strchr( output, '\t' ) ) {
         out_ptr = &output;
         c1 = strsep( out_ptr, delim );
        c2 = strsep( out_ptr, delim );
        fprintf( stdout, "Column 1 =[%s]\tColumn 2 = [%s]\n", c1, c2 );
    }
    else
 fprintf( stderr, "Wrong string in input!!! [%s]\n", buf );
  }
 }
}
  return 0;
}

output.txt

http://people.linux-online.ru/decvar/files/output.txt

sas

Попробуйте это:

#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

decvar
вот этот код у меня в конце делает SegFault.

#include 
#include 
#include 
#define BUFSZ   50
#define KEY "Server"
#define QUIT_TOKEN  "quit"
int main( int argc, char **argv )
{
  const char delim[] = "\t";
  char buf[ BUFSZ ];
  char *c1, *c2, *output, **out_ptr;
   FILE* out_stream;
  out_stream=popen("cat output.txt","r");
  while ( !feof(out_stream)){
  output= fgets(buf,BUFSIZ,out_stream);
  if(strstr(output,KEY)){
   while ( !feof(out_stream) ) {
    output = fgets( buf, BUFSZ, out_stream );
    if ( strchr( output, '\t' ) ) {
         out_ptr = &output;
         c1 = strsep( out_ptr, delim );
        c2 = strsep( out_ptr, delim );
        fprintf( stdout, "Column 1 =[%s]\tColumn 2 = [%s]\n", c1, c2 );
    }
    else
 fprintf( stderr, "Wrong string in input!!! [%s]\n", buf );
  }
 }
}
  return 0;
}

output.txt

http://people.linux-online.ru/decvar/files/output.txt

vnp
decvar
Я пробовал выделять и 1024. Не спасоало, да это и не важно.

это в const chat* separator ? А зачем он туда пишет?

Он не туда пишет. Он пишет в '\0\′ туда, где нашел разделитель. В данном случае, в тело строки «one two», которая размещена в read-only области.

Мне надо парсить именно char*. Я даже не знаю его размер. Я получаю его из

.....
        char* output=(char*)malloc(100);
....
                  while (!feof(out_stream)){
                        fgets(output,100,out_stream);
                        g_print("%s",output);
                        //
                        //            Здесь парсим вывод
                        //                        и фигачим их в массив(два)
                        //
                  }
   }
}

Это совершенно другой разговор. Здесь тоже segfault? Если да, то причины ему другие.

decvar

Здесь Сегфолта нет.

Всем спасибо — проблема решена.

vnp

Прошу прощения за предыдущий пост.

Здесь проблема в том, что !feof() не гарантирует успеха последующего fgets(). Порядок примерно такой: fgets читает последнюю строку потока. Попытки чтения за пределами файла не было. При следующем обороте цикла feof говорит, что все в порядке. fgets натыкается на конец файла, не прочтя ничего, и возвращает 0 (вот теперь feof вернет не-ноль). Этот 0 программа пытается разобрать, и погибает.

Поэтому, вместо

while ( !feof(out_stream)) {
  output= fgets(buf,BUFSIZ,out_stream);

рекомендую

while((fgets(buf,BUFSIZ,out_stream)) != 0) {
ecobeingecobeing.ru
Экология и вегетарианство на благо всем живым существам Планеты.