Каков наилучший способ разбирать слова при поиске нескольких целевых символов - PullRequest
0 голосов
/ 14 октября 2019

Я пытаюсь написать связанный список, который должен разбирать слова на узлы. На данный момент у меня это работает с использованием strtok на основе пробелов. Тем не менее, я хочу включить некоторые дополнительные правила для разбора, где я бы рассматривал

"яблоки с апельсинами" как одно слово

"яблоки с апельсинами" как 5 слов («яблоки», «-», «к», «-», «апельсины»)

«яблоки к апельсинам» как 3 слова («яблоки», «-»-oranges ')

"Джек. \", чтобы быть 3 словами ("Джек",'. ',' \ ')

и

"/// \\ "быть двумя словами ('///', '\\')

По сути, я хочу в любое время рассматривать символ '-' между двумя словами как часть слова, в противном случае все знаки препинаниянезависимо от того, сколько раз повторяется одно слово.

Можно ли каким-либо образом изменить мою существующую функцию strtok, которая по существу существует следующим образом

sourcechar = strtok (line," ");

            while (sourcechar != NULL)
            {
                strtemp = malloc(sizeof(char)*(strlen(sourcechar) + 1));
                strcpy(strtemp, sourcechar);
                head = insertToList(head, strtemp);
                sourcechar = strtok (NULL, " ");
            }

, чтобы рассмотреть правило одного'-' между двумя словами все должны рассматриваться как одно слово?

Если нет, я предполагаю, что мне пришлось бы использовать strncpy или strcpy для сравнения i-го и i-го символов. В таком случае, как я буду отслеживать начало и конец слова, которое будет вставлено в мой связанный список.

1 Ответ

0 голосов
/ 14 октября 2019

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

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

char **strcustomdlm ( char *psource);
char **freedlm ( char **pp);

int main ( void) {
    char *input = "  apples-.-to--oranges-to---bananas zebra- -tiger..?z;, .,,  ";
    char **parsed = NULL;
    int each = 0;

    printf ( "%s\n", input);
    //do not skip consecutive delimiters
    //do not retain terminating delimiter
    parsed = strcustomdlm ( input);
    //print each extracted string
    each = 0;
    if ( parsed) {
        while ( parsed[each]) {
            printf ( "parsed[%2d] %s\n", each, parsed[each]);
            each++;
        }
    }
    //free memory and set NULL
    parsed = freedlm ( parsed);

    return 0;
}

char **freedlm ( char **pp) {
    int each = 0;

    if ( pp) {
        while ( pp[each]) {
            free ( pp[each]);
            each++;
        }
        free ( pp);
    }

    return NULL;
}

char **strcustomdlm ( char *psource) {
    char **items = NULL;
    char **temp = NULL;
    char *pnt;
    char *cur;
    int span = 0;
    int item = 0;

    if ( psource) {
        cur = psource;
        pnt = psource;
        while ( *pnt) {
            span = 0;//reset on each iteration
            if ( ispunct ( *pnt) && ! ispunct ( *cur)) {//check for punct and not punct
                span = pnt - cur;
                if ( '-' == *pnt) {//test for single - trailing or within
                    if ( '-' != *(pnt + 1)) {
                        span = 0;
                    }
                }
            }
            if ( ! ispunct ( *pnt) && ispunct ( *cur)) {//check for not punct and punct
                span = pnt - cur;
                if ( '-' == *cur) {//test for single - leading
                    if ( '-' != *(cur + 1)) {
                        span = 0;
                    }
                }
            }
            if ( ispunct ( *pnt) && ispunct (*cur)) {//check for two punct
                if ( *cur == *(cur + 1)) {//fails in case of a single leading -
                    while ( *pnt == *cur) {
                        pnt++;//advance for duplicate
                    }
                }
                span = pnt - cur;
            }
            if ( isspace ( *pnt) || 0 == *pnt) {//space or end of string
                span = pnt - cur;
                if ( cur == psource) {//leading space
                    span = 0;//set span to ignore
                    while ( isspace ( *cur)) {//advance past multipls whitespace
                        cur++;
                    }
                    pnt = cur;
                }
            }

            if ( span) {//capture a span of characters

                //allocate item + 2 pointers
                if ( NULL == ( temp = realloc ( items, ( item + 2) * sizeof ( char *)))) {
                    break;
                }
                items = temp;
                //allocate for token plus zero terminator
                if ( NULL == ( items[item] = malloc ( span + 1))) {
                    break;
                }
                //copy substring to allocated memory
                memcpy ( items[item], cur, span);
                items[item][span] = 0;//zero terminate
                item++;
                items[item] = NULL;//sentinel NULL

                cur = pnt;//advance cur to pnt position in string
                while ( isspace ( *cur)) {//advance past multipls whitespace
                    cur++;
                    pnt++;
                }
            }
            if ( *pnt) {//not at end of string
                pnt++;//advance to next character
            }
        }
    }
    return items;
}
...