работа с текстом
От: Wolandino  
Дата: 18.08.05 18:56
Оценка:
Приветствую,

В общем, Си я практически не знаю, работаю с другим языком — но возникла задача на Си реализовать следующее:

Есть файл, в котором содержится в таком некая информация, среди которой есть вот такого вида записи:

#test1
blabla
blablabla
blabla
#/test1


#test2
blabla
blablabla
blabla
#/test2


#test3
blabla
blablabla
blabla
#/test3

Нужно вырезать блок текста, заключенного между вот этими test — То есть может возникнуть ситуация, когда нужно вырезать текст между test1 и /test1, а может и между test2 и test2/....в общем, в зависимости от ситуации...

Каким образом это можно реализовать? Делается это под никс, но думаю, что в условиях данной задачи платформа неважна... Буду благодарен (не хочется использовать awk для этих целей)
Re: работа с текстом
От: Анатолий Широков СССР  
Дата: 18.08.05 20:31
Оценка:
#include <stdio.h>
#include <stdlib.h>

#define line_size 80

void main(int argc, char* argv[])
{
    enum {search, show_tag} state = search;
    char line[line_size] = {'\0'};
    int result = 0;

    if( argc < 2 )
    {
        printf("usage: %s <tag> < <source_file>\n", argv[0]);
        exit(1);
    }

    while( gets(line) )
    {
        switch(state)
        {
        case search:
            if( line[0] == '#' )
            {
                result = strcmp(line + 1, argv[1]);
                if( result == 0 )
                    state = process;
            }
            break;
        case show_tag:
            if( line[0] == '#' && line[1] == '/')
            {
                result = strcmp(line + 2, argv[1]);
                if( result == 0 )
                    goto done;
                    
            } else
                puts(line);
            break;
        }
    }
done:
    exit(0);
}
Re[2]: работа с текстом
От: vnp  
Дата: 19.08.05 00:12
Оценка: 8 (1)
Здравствуйте, Анатолий Широков, Вы писали:

АШ>
...
АШ>void main(int argc, char* argv[])
АШ>{
АШ>    enum {search, show_tag} state = search;
...
АШ>    while( gets(line) )
АШ>    {
АШ>        switch(state)
...
АШ>                    goto done;
...
АШ>done:
АШ>    exit(0);
АШ>}
АШ>


Сложновато как-то, не находите? И никогда-никогда не вызывайте gets...


int main(int argc, char ** argv)
{
    char * opentag = malloc(1 + strlen(argv[1]) + 1);
    char * closetag = malloc(2 + strlen(argv[1]) + 1);
    char line[LONG_ENOUGH + 1];

    sprintf(opentag, "#%s\n", argv[1]);
    sprintf(closetag, "#/%s\n", argv[1]);

    /* Пропустить все до открывающего тэга */
    while(fgets(line, LONG_ENOUGH, stdin) && strcmp(line, opentag))
        ;

    /* Печатать все до закрывающего тэга */
    while(fgets(line, LONG_ENOUGH, stdin) && strcmp(line, closetag))
        puts(line);

    return 0;
}



Один баг здесь еще присутствует: если среди blabla в нужном месте окажется нужный текст, файл будет обработан неправильно.

Так что по-хорошему, sed -n -e '0,/testX/d;/^#\/testX/q;0,$p/'
Re[3]: работа с текстом
От: Анатолий Широков СССР  
Дата: 19.08.05 11:22
Оценка:
vnp>Сложновато как-то, не находите? И никогда-никогда не вызывайте gets...
На счет gets — да, конечно, в случае превышения длины строки программа свалится, но должны же быть в программе какие-то недостатки — вы тоже ведь в своем варианте не позаботись об удалении памяти.

vnp>Один баг здесь еще присутствует: если среди blabla в нужном месте окажется нужный текст, файл будет обработан неправильно.


Не увидел — вроде, нет такого бага.

vnp>Так что по-хорошему, sed -n -e '0,/testX/d;/^#\/testX/q;0,$p/'


Если это сама цель, то да.
Re[4]: работа с текстом
От: vnp  
Дата: 19.08.05 16:50
Оценка:
Здравствуйте, Анатолий Широков, Вы писали:

vnp>>Один баг здесь еще присутствует: если среди blabla в нужном месте окажется нужный текст, файл будет обработан неправильно.


АШ>Не увидел — вроде, нет такого бага.


Предтсавьте себе строку вида

xxx...xxx#test2

где xxx...xxx состоит из ровно LONG_ENOUGH символов. fgets прочитает ее в два приема, и на втором произойдет (ложное) совпадение.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.