Можно ли сделать следующее проще или эффективнее? - PullRequest
3 голосов
/ 28 ноября 2010

Я пытаюсь преобразовать некоторый код из языка с динамической типизацией в C. Пожалуйста, потерпите меня, поскольку у меня пока нет практического опыта работы с C.

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

void output_dispatcher(char *str, int strlen, int flag) {
    char output[501];
    char *result;

    switch (flag) {
        /* No conversion */
        case 0:
            result = str;
            break;
        case 1:
            result = convert_type1(output, str, strlen);
            len = strlen(result);
            break;
        /* ... */
    }
    /* do something with result */
}

В настоящее время у меня есть 5 различных выходных преобразователей, и они все (даже будущие) гарантированно будут производить только 300-500 символов.Из моего прочтения предпочтительнее использовать переменную кучи, чем динамически выделять место в стеке, если это возможно.Объявление функции для одного выглядит следующим образом:

static char * convert_type1(char *out, const char *in, int inlen);

Я хочу избежать strlen в диспетчере, так как нет необходимости пересчитывать размер вывода, потому что выходные преобразователи знают это, когда они конструируют вывод.Кроме того, поскольку я передаю указатель на выходную переменную, мне не нужно возвращать указатель результата, верно?Поэтому я изменяю его следующим образом, но получаю ошибку компиляции «несовместимого типа».

void output_dispatcher(char *str, int strlen, int flag) {
    char output[501];

    switch (flag) {
        /* No conversion */
        case 0:
            output = str;  /* ERROR: incompatible type */
            break;
        case 1:
            strlen = convert_type1(output, str, strlen);
            break;
        /* ... */
    }
    /* do something with result */
}

Может ли этот подход работать или есть лучший путь?

Ответы [ 5 ]

1 голос
/ 28 ноября 2010

Чтобы избежать пересчета, ваши выходные преобразователи должны иметь такой прототип, как этот:

static char * convert_type1(char *out, const char *in, int *len);

называется так:

result = convert_type1(output, str, &strlen);

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

Что касается кучи против стека, вам действительно нужно использовать кучу, поскольку переменные, расположенные в стеке, исчезнут, как только функция завершится.

0 голосов
/ 28 ноября 2010

C не позволяет изменять массивы прямым присваиванием - вы должны индивидуально изменять элементы массива. Таким образом, если вы хотите скопировать строку, указанную str, в массив output, вы должны использовать:

strcpy(output, str);

или, возможно,

memcpy(output, str, strlen + 1);

(В обоих случаях после первой проверки strlen < sizeof output).

Обратите внимание, что присвоение имени локальной переменной strlen, таким образом, затеняет стандартную функцию с таким именем, может привести в замешательство кого-то, кто позже взглянет на ваш код. Я бы выбрал другое имя.

0 голосов
/ 28 ноября 2010

Ошибка в этом случае имеет смысл. output - это буфер, в котором будут храниться данные типа char, а str - указатель на некоторую другую область в памяти. Вы не хотите назначать адрес того, что str указывает на вывод, верно? Если вы хотите использовать этот подход, я думаю, что просто скопируйте данные, на которые указывает str, в вывод. Еще лучше, просто используйте str, если конверсия не требуется.

0 голосов
/ 28 ноября 2010

символьный выход [501];выход = стр .;/ * ОШИБКА: несовместимый тип * /

=>

strncpy (output, str, sizeof (output));

Обратите внимание, следует проверить, является ли 'output'достаточно большой, чтобы вместить 'str'

0 голосов
/ 28 ноября 2010

Строка:

output = str;

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

«output» - это массив, а неуказатель.

str = output;

будет работать, потому что char ptr очень похож на переменную массива.

Но обратное не так, потому что переменная «output» - это не просто указатель на массив, но сам массив.

Например, если у вас было:

char output[501];
char output1[501];

и вы сделали:

output1 = output;

Это было бы нормально, и C скопировал бысодержимое выходного массива в массиве output1.

Итак, вас немного смущают массивы и ptrs.

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