2009-07-22 3 views
1

Я написал программу, в которой в основной функции я объявляю массив указателей, а затем я вызываю функцию, которая разбивает данное предложение, а затем хочет назначить его массиву указателей в main(). Я не могу этого сделать. Не могли бы вы проверить приведенный ниже код:Удвоение двойного указателя в C

int main(void) 
    { 
     char *data[3]; 

     allocate(data); 
     /* Unable to print the strings here */ 
     printf("Main is %s\n", data[0]); 
     printf("" 

    } 

    void allocate(char **dt) 
    { 
     int i; 
     char buf[] = "The great Scorpion"; 
     char delims[] = " "; 

     size_t len; 
     char *p; 
     char *result = NULL; 
     result = strtok(buf," "); 
     *dt = result; 
     int j = 1; 
     while(result!=NULL) 
     { 

      result = strtok(NULL, delims); 
      dt[j]=result; 
      j++; 

     } 
     /* able to print values here */ 
     printf("result is %s\n", dt[0]); 
     printf("result is %s\n", dt[1]); 
     printf("result is %s\n", dt[2]); 
    } 

Может ли кто-нибудь помочь мне?

+0

Я предполагаю, что может быть какая-то проблема с функцией strtok, которую я думаю.IF Я передаю строку непосредственно в функции allocate, я могу получить эти значения, отраженные в основной функции. – 2009-07-22 18:26:20

+1

В чем проблема с указанным кодом? Каков фактический вопрос, на который вы хотите ответить? – jalf

+0

Я хочу, чтобы строки, выделенные в функции выделения, отражались в основной функции. – 2009-07-22 18:28:42

ответ

-1

Вы не выделили память, которая будет использоваться внутри данных [X], только что выделенные данные.

данные [0] == пустого указателя

+0

Имеет смысл для меня. J начинается с 1, а не 0. –

+0

Роберт: Я использую функцию strtok. Так просто wann попасть в цикл. – 2009-07-22 18:30:28

+0

Вы пропустили '* dt = result;' - он устанавливает 'dt [0]' –

14

strtok не выделяют новые строки, она возвращает указатель на существующую строку (и замещающих разделители с нулевыми символами вместо). Итак, в allocate вы заполняете dt указателями на buf. Поскольку buf является автоматической переменной, срок ее жизни заканчивается, когда возвращается allocate, и все указатели в dt признаны недействительными.

+0

Вы можете исправить проблему автоматической переменной, выполнив 'char const * const buf =" Великий скорпион "' b/c, а затем 'buf' будет быть указателем на статическую константную строку, ** BUT **, тогда вы не сможете использовать 'strtok()', так как это будет хотеть изменить строки 'buf' points, что не разрешено. – rampion

+0

So он мог бы исправить проблему, дав статическую продолжительность хранения buf: static char buf [] = «The Great Scorpion»; – caf

2

Если я правильно помню, strtok() не выполняет динамическое распределение, он фактически изменяет строку, которую вы передаете, в первый раз, когда вы ее вызываете. Таким образом, в этом случае он изменяет buf. Таким образом, dt представляет собой массив указателей в buf. И когда вы выходите из функции, buf уничтожается.

0

Ok,

  1. У вас есть allocate функцию, которой вы передаете массив возвращает указатель.
    • Внутри функции вы выделяете строку на стеке, и,
    • Сделайте strtok возвращают указатели на эту область стека вне функции
    • В этот момент вы «оборванный» указатели на строки - эффективно
    • Затем вы вызываете printf, которые убивают данные в нераспределенном стеке
    • вы пропускаете строки в printf.

Если вы хотите сделать это, правильный путь будет
действительно выделить строки в вашей allocate функции и
затем освободить их от основной после того как вы сделали с ними.

Старшего способ работы с strtok был использовать strdup в allocate и бесплатно позже.


OldStuff ... Я думаю, вам нужно пройти &data к вашей allocate функции.
Либо это, или я еще не все проснулся.

+0

Ему это не нужно. 'data' имеет тип' (char *) [] 'и будет распад на 'char **', который является типом аргумента функции. Если он делает то, что вы предлагаете, он получит (char []) *, что не будет совместимый тип аргумента. –

0

На самом деле вы можете просто добавить статическую информацию в свою декларацию buf.

0

Как небольшой отложенный (на самом деле это не влияет на вашу программу), ваш цикл структурирован неправильно.

int j = 1; 
    while(result!=NULL) 
    { 

     result = strtok(NULL, delims); 
     dt[j]=result; 
     j++; 
    } 

Вы правильно установили dt [0], dt [1] и dt [2]. Однако из-за характера вашего цикла (вы проверяете, вызываете strtok, затем вставляете в dt), вы также назначаете NULL в dt [3]. Это, вероятно, будет работать в этом тривиальном примере, но вы, вероятно, уничтожаете свой стек. Вы должны структурировать свою петлю как

result = strtok(buf," "); 
    int j=0 
    while(result != NULL) 
    { 
     dt[j]=result; 
     j++; 
     result = strtok(NULL, delims); 
    } 
0

Вы пытаетесь вернуть адрес локальной нестатической переменной; как только функция allocate() выйдет, массив buf больше не существует, поэтому указатели в вашем массиве данных больше не указывают на что-либо значимое.

Что вам нужно сделать, это сохранить копию маркера, а не просто указатель на него:

void allocate(char **dt) 
{ 
    char buf[] = "The Great Scorpion"; 
    char delim[] = " "; 
    size_t i = 0; 
    char *result = strtok(buf, delim); 
    while (result) 
    { 
    dt[i] = malloc(strlen(result) + 1); 
    if (dt[i]) 
    { 
     strcpy(dt[i++], result); 
    } 
    result = strtok(NULL, delim); 
    } 
} 

int main(void) 
{ 
    char *data[3]; 
    allocate(data); 
    ... 
} 

В качестве альтернативы, вы можете определить данные, чтобы быть 2D массив полукокса, а не просто массив указателей, но вам нужно убедиться, что он имеет размер, чтобы обрабатывать максимальную длину строки; Кроме того, тип передается выделить изменения:

#define STRING_SIZE ... /* large enough for longest string */ 
void allocate(char (*dt)[STRING_SIZE+1]) 
{ 
    char buf[] = "The Great Scorpion"; 
    char delim[] = " "; 
    size_t i = 0; 
    char *result = strtok(buf, delim); 
    while (result) 
    { 
    strcpy(dt[i++], result); 
    result = strtok(NULL, delim); 
    } 
} 

int main(void) 
{ 
    char data[3][STRING_SIZE]; 
    allocate(data); 
    ... 
} 

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

0

Чтобы не мусорить стек, цикл while должен быть защищен размером переданного параметра «char * data [3]», который в этом случае равен 3, то есть дополнительный параметр.

Но я согласен с добавлением статического значения в «static char buf [] = ....» - это самый быстрый ответ, чтобы не указывать на выделенный выделенный стек завершенной функции.

Смежные вопросы