2010-11-12 2 views
1

Я пытаюсь разбить строку каждые X количество символов, а затем сохранить каждую строку в массиве структур. Тем не менее, мне интересно, какой будет короткий и эффективный способ сделать это. Я думал, что, возможно, я мог бы использовать sscanf, но не очень уверен, как это сделать. Любая помощь будет оценена. До сих пор у меня есть:C - split/store string длины X в массив структур

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

struct st {char *str;}; 

int main() 
{ 
    struct st **mystruct; 

    char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used."; 
    size_t max = 20, j = 0; // max length of string 
    size_t alloc = strlen(tmp)/max + 1; 

    mystruct = malloc(alloc * sizeof *mystruct); 
    for (j = 0; j < alloc; j++) 
     mystruct[j] = malloc(sizeof *mystruct[j]); 

    const char *ptr = tmp; 
    char field [ max ]; 
    int n; 

    while (*ptr != '\0') { 
     int line = sscanf(ptr, "%s", field, &n); // not sure how to use max in here 
     mystruct[j]->str = field; 
     field[0]='\0'; 
     if (line == 1) 
      ptr += n; 
     if (n != max) 
      break; 
     ++ptr; 
     ++j; 
    } 

    return 0; 
} 

Так что, когда я итерация по моей структуре, я могу получить что-то вроде:

For configuration op 
tions (arch/xxx/conf 
ig.in, and all the C 
onfig.in files),some 
what different inden 
tation is used. 

ответ

3

Вы можете использовать strncpy.

FYI:

char field [ max ]; 
while (...) { 
    mystruct[j]->str = field; 

Две проблемы с этим: (1) каждая структура в массиве будет в конечном итоге, указывая на ту же строку, которая будет иметь значение последнее, что вы отсканированного (2) они указывают на переменную в стеке, поэтому, когда эта функция вернется, они будут уничтожены. Это явно не проявляется здесь (например, ваша программа не взрывается), потому что функция оказывается «основной», но если вы переместили ее в отдельную подпрограмму и вызвали ее для разбора строки, вы бы получили мусор ,

mystruct не обязательно должен быть указателем на указатель. Для массива 1D просто выделите блок N * sizeof *myarray для N элементов.

Общая информация о C идиоме при работе с структурами заключается в использовании typedef, поэтому вам не нужно набирать struct foo все время. Например:

typedef struct { 
    int x, y; 
} point; 

Теперь вместо того, чтобы печатать struct point pt вы можете просто сказать point pt.

+0

Вы могли бы разработать немного больше, когда говорите, используя strncpy? спасибо – demit1501

1

Если строка не изменится после того, как вы разбить его, я бы рекомендовал использовать на структуру, как это:

struct st { 
    char *begin; 
    char *end; 
}; 

или альтернатива:

struct st { 
    char *s; 
    size_t len; 
}; 

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

+0

Я не люблю эти идеи, потому что во всех случаях эти «char *» не будут указывать на правильные строки с нулевым завершением, представляющие отдельные строки. Так, например, если он должен зациклиться на структурах и вызвать что-то вроде 'printf («% s \ n », s.begin)», выход будет не таким, как требуется. –

+0

@Dave: Сделайте это: const char * p = s.begin; while (p! = s.end) putchar (* p ++); –

+1

@Dave: Или используя начальную и среднюю версии: printf ("%. * S \ n", s.len, s.s); –

0

Один из вариантов - сделать это по-характеру.

Рассчитать количество строк, которое вы сейчас делаете.

Выделяет памяти = (StrLen (TMP) + NUMBER_OF_LINES) * SizeOf (Char)

Прогулку через входную строку, копирование символов из входных данных для вновь выделенной памяти. Каждый 20-й символ вставляет нулевой байт, чтобы разграничить эту строку. Сохраните указатель на начало каждой строки в вашем массиве структур.

0

Его достаточно легко?

#define SMAX 20 
typedef struct {char str[SMAX+1];} ST; 

int main() 
{ 
    ST st[SMAX]={0}; 
    char *tmp = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used."; 
    int i=0,j; 
    for(; (st[i++]=*(ST*)tmp).str[SMAX]=0 , strlen(tmp)>=SMAX; tmp+=SMAX); 

    for(j=0;j<i;++j) 
    puts(st[j].str); 

    return 0; 
} 
0

Вы можете использовать (non C standard, но GNU) функцию strndup().

#define _GNU_SOURCE 
#include <string.h> 

struct st {char *str;}; 

int main() 
{ 
    struct st *mystruct; /* i wonder if there's need for double indirection... */ 

    char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used."; 
    size_t max = 20, j = 0; // max length of string 
    size_t alloc = (strlen(tmp) + max - 1)/max; /* correct round up */ 

    mystruct = malloc(alloc * sizeof mystruct); 
    if(!mystruct) return 1; /* never forget testing if allocation failed! */ 

    for(j = 0; j<alloc; j++) 
    { 
     mystruct[j].str = strndup(tmp+alloc*max, max); 
    } 
} 
Смежные вопросы