Разбор форматированных C строк, которые разбиты на части - PullRequest
0 голосов
/ 08 апреля 2020

Я хочу реализовать функцию, которая разлагает данную строку. но я не уверен, как go об этом. любая помощь приветствуется.

/* Parses *str and creates a new StringBundle object containing the
 * separate fields of *str.
 *
 * Pre: str points to a GIS record string, properly terminated
 *
 * Returns: a pointer to a new proper StringBundle object
 */
 StringBundle* createStringBundle(const char* const str){

 }

например, эта строка разделена '|':

901051|Becker|Locale|NM|35|Eddy|015|322833N|1040812W|32.4759521|-104.1366141|||||959|3146|
Carlsbad East|11/01/1992|

Я хочу разбить ее на набор строк, некоторые из которых могут быть пустыми.

0 901051
1 Becker
2 Locale
3 NM
4 35
5 Eddy
6 015
7 322833N
8 1040812W
9 32.4759521
10 -104.1366141
11
12
13
14
15 959
16 3146
17 Carlsbad East
18 11/01/1992
19

И я использую пакет структурной строки

/** A StringBundle contains an array of nTokens pointers to properly-
 * terminated C strings (char arrays).
 *
 * A StringBundle is said to be proper if:
 * -Tokens == NULL and nTokens == 0
 * or
 * -nTokens > 0 and Tokens points to an array of nTokens char pointers,
 * -each char pointer points to a char array of minimum size to hold
 * its string, including the terminator (no wasted space)
 */
 struct _StringBundle {
     char** Tokens; // pointer to dynamically-allocated array of char*
     uint32_t nTokens; // dimension of array pointed to by Tokens
 };

Поле Tokens является char**, поскольку оно указывает на первый элемент в массиве char* переменных.

Я могу использовать любую из этих c библиотечных функций: mallo c (), callo c (), reallo c (), free (), strncpy (), memcpy (), strlen (), sscanf ().

Ответы [ 2 ]

0 голосов
/ 08 апреля 2020

Минимальный конечный автомат (если вы хотите перехватить символы в новые строки, вам нужно только перераспределить fput c () с помощью операций добавления к строке):


#include <stdio.h>

int main(void)
{
int ch, pos,lin;

for (pos=lin=0;;) {
        ch = getc(stdin);
        if (ch != EOF && pos==0) printf("\n%d:" , lin);
        if (ch == EOF) break;
        switch (ch) {
        default: putc(ch,stdout); break;
        case '|': lin++; pos = 0; continue;
        case '\n': putc(ch,stdout); continue;
                }
        pos++;
        }
return 0;
}

Использование:


echo '901051|Becker|Locale|NM|35|Eddy|015|322833N|1040812W|32.4759521|-104.1366141|||||959|3146|Carlsbad East|11/01/1992|' \
| ./a.out
0 голосов
/ 08 апреля 2020

Вы можете сделать это за два прохода

Первый проход для подсчета количества элементов:

uint32_t nTokens = 0;
char *ptr = str;

while (*ptr)
{
    if (*ptr == '|')
    {
        nTokens++;
    }
    ptr++;
}

Затем вы резервируете место для строк:

char **Tokens = malloc(sizeof(*Tokens) * nTokens);

И во втором проходе вы присоединяете строки:

for (uint32_t i = 0; i < nTokens; i++)
{
    char *ptr = strchr(str, '|'); // Find the delimiter
    char *tok = malloc(ptr - str + 1); // Reserve space for the token

    if (tok == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    snprintf(tok, ptr - str + 1, "%s", str); // Copy delimited string
    Tokens[i] = tok; // Attach token
    str = ptr + 1; // Advance the  pointer to the next token
}

Этот подход быстрее, чем использование realloc, но если вы вынуждены его использовать:

uint32_t nTokens = 0;
char *ptr;

while ((ptr = strchr(str, '|')))
{
    char *temp = realloc(Tokens, sizeof(*Tokens) * ++nTokens);

    if (temp == NULL)
    {
        perror("realloc");
        exit(EXIT_FAILURE);
    }
    Tokens = temp;

    char *tok = malloc(ptr - str + 1); // Reserve space for the token

    if (tok == NULL)
    {
        perror("malloc");
        exit(EXIT_FAILURE);
    }
    snprintf(tok, ptr - str + 1, "%s", str); // Copy delimited string
    Tokens[nTokens - 1] = tok; // Attach token
    str = ptr + 1; // Advance the  pointer to the next token
}
...