Массив char * в C - PullRequest
       10

Массив char * в C

2 голосов
/ 23 января 2012

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

Вот фрагмент кода, который я пытаюсь заставить его работать правильно:

typedef char* String;
String* split(char* cmd)
{
    char* param;
    char tmp[128];
    String* result = (String*) malloc(10*sizeof(String));
    memset(result,NULL,10);

    strcpy(tmp,cmd);

    param = strtok(tmp," ");

    int index = 0;
    while(param && index < sizeof(result) / sizeof(*result))
    {

        result[index] = (char*) malloc(strlen(param));
        strcpy(result[index],param);

        param = strtok(NULL," ");
        index++;
    }

}

Где cmd - строка, которую я токенизирую, а result - массив, который будет содержать каждый токен..

Этот фрагмент кода вызывает ошибки при попытке перебрать возвращаемый результат с помощью простого цикла for (возникает ошибка сегментации)

String* splittedCmd = split(command);

int i;
for(i=0;i<10;i++)
{
    if(splittedCmd[i] != NULL)
        printf("%s\n",splittedCmd[i]);
}

Ответы [ 3 ]

2 голосов
/ 23 января 2012

Здесь есть несколько неправильных вещей.

Первое и самое очевидное, вы возвращаете result, который является массивом (но распадается на указатель на массив), который расположен в стеке в функциипоэтому он возвращается, когда функция возвращается.Вам необходимо динамически распределить массив (и полагаться на вызывающего * free it):

String *result = malloc(10 * sizeof(String));

Кроме того, ваше условие для остановки цикла while:

if(index == sizeof(result))

Выпустит цикл до тех пор, пока index не станет 40 (если char* равно 4 байтам на вашей платформе), потому что sizeof возвращает размер операнда в байтах, а не элементов массива, поэтому sizeof(result) есть (опять же,зависит от платформы) 40. Это, очевидно, выходит за пределы массива.

Если бы вы все еще использовали локальный массив вместо malloc, вы могли бы изменить его на

if (index == sizeof(result) / sizeof(*result))

ОднакоВы не можете сделать это сейчас, потому что result является только указателем вместо массива, а sizeof(result) всегда будет размером указателя на вашей платформе.

Вы можете просто удалить это ifполностью и измените условие while на

while (param && index < 10)

, что гарантирует, что param не NULL, а также что index меньше 10. Вы должны рассмотреть вопрос о #define илиconst int или что-то для размера массива и используйте его вместо магиичисло.

Вам также нужно изменить

memset(result,NULL,10);

на

memset(result,NULL, sizeof(String) * 10);

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

1 голос
/ 23 января 2012

Просто подсказка - почему бы вам не попробовать использовать strtok ?Это сильно упростит ситуацию.

0 голосов
/ 23 января 2012

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

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