Создание рабочей копии массива char неизвестной длины - PullRequest
0 голосов
/ 07 апреля 2020

Использование MPLABX 5.35 с XC16 v1.36 для PIC24FJ128GB204. Ограниченный c фон, но обучение.

Я пытаюсь написать функцию, которая берет (указатель на) строку в массиве символов (неизвестного размера) и редактирует ее на месте вправо. Выровняйте его и добавьте к нему символы, пока они не получат требуемую длину. Поскольку я хотел бы сохранить эту функцию и для других проектов, размер исходного массива будет неизвестен, но пользователь (я) должен оставить targetLength меньше, чем размер массива.

Так что представьте массив:

char example[20] = "test";

Я хочу иметь возможность передать его в функцию с желаемой длиной (скажем, 10 символов, включая нулевое завершение) и символом заполнения '#', и он должен редактировать массив в место для "##### TEST"

Код, который я придумал (который работает только для в некоторых случаях , поэтому его нельзя использовать):

uint16_t fillStringRight(char * source, 
                    uint16_t targetLength, 
                    char filler)
{
    uint16_t sourceLength = strlen(source) + 1;

    if (sourceLength > targetLength){ 
        // source length is already longer than requested
        return 0;
    }

    uint16_t reqFiller = targetLength - sourceLength;

    strcpy(&source[reqFiller], source);
    memset(source, filler, reqFiller -1);
    return 1;
}

Однако в этом случае:

char source[20] = "test";
fillStringRight(source, 6, ' ');

Это не работает. Если я правильно понимаю, источник и результат перекрываются, поэтому strcpy перезапишет нулевой терминатор и, таким образом, будет продолжать записывать все дальше и дальше в память, пока сторожевой таймер не перезапустит PI C.

Первый вопрос: есть мое понимание верно?

Полагаю, мне следует сделать копию исходной строки, а не редактировать ее на месте. Однако я не знаю длину строки, поэтому я не могу определить размер массива char, который будет использоваться для копии (если я не сделаю его смехотворно большим). Я читал о mallo c, чтобы создать переменную в куче с размером, который определяется во время выполнения, но также и с использованием mallo c на микроконтроллере. Я пока не понимаю, почему, поэтому предпочитаю держаться от него подальше, пока не пойму лучше.

Второй вопрос: как правильно сделать это? Я мог бы написать функцию, которая работает в обратном направлении (начинать с нулевого терминатора в последней позиции, затем работать в обратном направлении), но это кажется чрезмерной нагрузкой. Разве нет лучшего способа?

1 Ответ

1 голос
/ 07 апреля 2020

С man memmove (3) :

Области памяти могут перекрываться: копирование происходит так, как будто байты в sr c сначала копируются во временный массив это не перекрывает sr c или dest, и байты затем копируются из временного массива в dest.

Другими словами, есть функция для того, что вы хотите:)
Try memmove(&source[reqFiller], source, sourceLength); Эквивалент псевдокода:

char *tmp = duplicate_string(source);
copy tmp to &source[reqFiller]; 

Не связано, но, к вашему сведению:
1) strlen() возвращает size_t, а не uint16_t
2) &a[b] == &*(a +b) == (a + b), поэтому &source[reqFiller] == source + reqFiller

...