Разберите текст XML в C - PullRequest
0 голосов
/ 22 июля 2011

Это довольно долго, так со мной ...

Хорошо, вот моя цель: прочитать текстовый файл XML и разбить каждое слово и тег на свою строку в массиве.

Например, если я введу этот текст в свою программу:

<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don't forget me this weekend!</body>
</note>

Я получу это:

<note>
<to>
Tove
</to>
<from>
...

Прямо сейчас у меня есть код, который может успешно выполнитьэто, но только со словами, поэтому вместо приведенного выше списка я получаю:

note
to
Tove
...

Я хочу сохранить теги, или я не смогу делать то, что я хочу с ним.Итак, я пытался заставить его также добавлять теги, но мне не удавалось

Хорошо, вот мой код:

//While the file is not empty
while(fgets(buffer, sizeof(buffer), stdin) != NULL){
    int first = 0;
    int last = 0;

    //While words are left in line
    while(last < INITIAL_SIZE && buffer[last] != '\0'){
        int bool = 0;
        //Tag detected
        if(buffer[last] == '<'){
            while(buffer[last] != '>'){
                last++;
            }

            bool = 1;
        }else{
            //While more chars are in the word
            while(last < INITIAL_SIZE && isalpha(buffer[last])){
                last++;
            }
        }
        //Word detected
        if(first < last){
            //Words array is full, add more space
            if(numOfWords == sizeOfWords){
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words, sizeOfWords*sizeof(char *));
            }               
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last-first+1, sizeof(char));


            for(i = 0; i < (last-first); i++){
                words[numOfWords][i] = buffer[first + i];
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;   
        }           
        //Move "Array Pointers" accordingly
            last++;
            first = last;
    }       
}

У любого есть идеи, с приведенным выше кодомэто распечатка:

<note
<to
Tove
to 
<from
Jani
from
<heading
...
Don
t
forget
me
this
weekend
</body
</note

Итак, после этой стены текста кто-нибудь имеет представление о том, как я могу изменить свой текущий код, чтобы заставить его работать?Или у кого-нибудь еще есть альтернатива?Любые предложения или помощь приветствуется.

Ответы [ 4 ]

0 голосов
/ 03 августа 2011

Лучший совет, который я могу дать здесь, это то, что мне дали, когда я разместил это на comp.lang.c.

Функция

Практически везде, где вы написали полный комментарий, важными словами из комментария должны быть имена функций, вызываемых в этот момент.

ProcessFile
    while(fgets..)
        ProcessWords()

ProcessWords
    if(DetectTag)
        ...

Рефакторинг таким образом значительно упрощает чтение сложного кода (и для вас тоже). Это позволяет вашей логике верхнего уровня читать как псевдокод, в то время как все биты могут быть сгруппированы вместе. Возможно, когда-нибудь теги будут использовать фигурные скобки. Поместите свои литералы в #define с или даже enums. Таким образом, простые изменения синтаксиса могут быть легко сделаны позже.

Цель в том, чтобы вы могли видеть все тело функции на экране одновременно. Это позволяет проверять каждый фрагмент отдельно.

0 голосов
/ 22 июля 2011

Мой основной способ мышления таков:

first - первая буква , включенная в текущее слово;

last - это первая буква , не включенная в текущее слово.

В вашей программе, когда вы обнаруживаете теги, вы не включаете >. Кроме того, last++ в конце не требуется, так как вы правильно разбираете слова, после включения > это бесполезно. Кроме того, вы забыли проверить не только \0 как конец строки, но также \n как конец строки.

Вот мое решение:

while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    int first = 0;
    int last = 0;

    //While words are left in line
    while (last < INITIAL_SIZE && buffer[last] != '\0' 
          && buffer[last] != '\n')  { // <--------- Add this
        int Bool = 0;
        //Tag detected
        if (buffer[last] == '<') {
            while (buffer[last] != '>') {
                last++;
            }

            last++; // <--------- This
            Bool = 1;
        } else {
            //While more chars are in the word
            while (last < INITIAL_SIZE && isalpha(buffer[last])) {
                last++;
            }
        }
        //Word detected
        if (first < last) {
            //Words array is full, add more space
            if (numOfWords == sizeOfWords) {
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words,
                        sizeOfWords * sizeof(char *));
            }
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last - first + 1,
                    sizeof(char));

            for (i = 0; i < (last - first); i++) {
                words[numOfWords][i] = buffer[first + i];
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;
        }
        //Move "Array Pointers" accordingly
        first = last; // <--------- And change this
    }
}
0 голосов
/ 03 августа 2011

Несмотря на то, что весьма сомнительно, что кто-нибудь когда-либо будет использовать это, я заставил его работать, используя логику логического типа.

while (fgets(buffer, sizeof(buffer), stdin) != NULL) {
    int first = 0;
    int last = 0;

    //While words are left in line
    while (last < INITIAL_SIZE && buffer[last] != '\0' && buffer[last] != '\n'){
        int Bool = 0;
        //Tag detected
        if (buffer[last] == '<'){
            while (buffer[last] != '>')
                last++;
            Bool = 1;
        }else
            //While more chars are in the word
            while(last < INITIAL_SIZE && !isspace(buffer[last]) && buffer[last] != '<')
                last++;

        //Word detected
        if (first < last) {
            //Words array is full, add more space
            if (numOfWords == sizeOfWords) {
                sizeOfWords = sizeOfWords + 10;
                words = (char **) realloc(words, sizeOfWords * sizeof(char *));
            }
            //Allocate memory for array
            words[numOfWords] = (char *) calloc(last - first + 1, sizeof(char));

            int xHolder = 0;
            if(buffer[first] == '/'){
                words[numOfWords][0] = '<';
                xHolder++;
                Bool++;
            }
            for (i = 0; i < (last - first + Bool); i++) {
                words[numOfWords][xHolder] = buffer[first + i];
                xHolder++;
            }
            //Add terminator to "new word"
            words[numOfWords][i] = '\0';
            numOfWords++;
        }
        //Move "Array Pointers" accordingly
        last++;
        first = last;
    }
}
0 голосов
/ 22 июля 2011

Возможно, у вас проблемы с внутренним циклом

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...