Как добавить символ в определенной позиции - PullRequest
0 голосов
/ 11 февраля 2019

Я пытаюсь добавить символ в определенной позиции.Я создал новую функцию, выделил память для еще одного символа, сохранил символы после позиции, затем добавил мой символ в определенной позиции, и теперь я не знаю, как стереть символы после этой позиции, чтобы объединить сохраненную строку.Любое решение?

Вот начало моей функции:

void appendCharact(char *source, char carac, int position) {
    source = realloc(source, strlen(source) * sizeof(char) + 1); //Get enough memory
    char *temp = source.substr(position); //Save characters after my position
    source[position] = carac; //Add the character
}

РЕДАКТИРОВАТЬ: я пытаюсь реализовать другое "варварское" решение, в режиме отладки я вижу, что япримерно моя новая строка, но, похоже, я не могу стереть старый указатель ...

void appendCharact(char *source, char carac, int position) {
    char *temp = (char *)malloc((strlen(source) + 2) * sizeof(char));
    int i;
    for(i = 0; i < position; i++) {
        temp[i] = source[i];
    }

    temp[position] = carac;
    for (i = position; i < strlen(source); i++) {
        temp[i + 1] = source[i];
    }
    temp[strlen(temp) + 1] = '\0';
    free(source);
    source = temp;
}

Ответы [ 5 ]

0 голосов
/ 11 февраля 2019

Ваше новое решение намного ближе к работающей функции, но оно все еще имеет некоторые проблемы:

  • вы не проверяете ошибку malloc().
  • вам следует избегать вычисленийдлина исходной строки несколько раз.
  • temp[strlen(temp) + 1] = '\0'; неверно, поскольку temp еще не является правильной строкой C и strlen(temp) + 1 в любом случае будет указывать за пределы выделенного блока, вы должны просто написать temp[i + 1] = '\0';
  • вновь выделенная строка должна быть возвращена вызывающей стороне, либо в качестве возвращаемого значения, либо через аргумент char **.

Вот исправленная версия:

char *insertCharact(char *source, char carac, size_t position) {
    size_t i, len;
    char *temp;

    len = source ? strlen(source) : 0;
    temp = (char *)malloc(len + 2);
    if (temp != NULL) {
        /* sanitize position */
        if (position > len)
            position = len;
        /* copy initial portion */
        for (i = 0; i < position; i++) {
            temp[i] = source[i];
        }
        /* insert new character */
        temp[i] = carac;
        /* copy remainder of the source string if any */
        for (; i < len; i++) {
            temp[i + 1] = source[i];
        }
        /* set the null terminator */
        temp[i + 1] = '\0';
        free(source);
    }
    return temp;
}
0 голосов
/ 11 февраля 2019

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

Это может выглядеть примерно так:

bool append_ch (char** str, char ch, size_t pos)
{
  size_t prev_size = strlen(*str) + 1;
  char* tmp = realloc(*str, prev_size+1);
  if(tmp == NULL)
  {
    return false;
  }

  memmove(&tmp[pos+1], &tmp[pos], prev_size-pos);
  tmp[pos] = ch;
  *str = tmp;
  return true;
}

Использование:

const char test[] = "hello word";
char* str = malloc(sizeof test);
memcpy(str, test, sizeof test);
puts(str);

bool ok = append_ch(&str, 'l', 9); 
if(!ok) 
  asm ("HCF");  // error handling here
puts(str);

free(str);
0 голосов
/ 11 февраля 2019

Попробуйте использовать что-то вроде:

 #include <string>
 void appendCharAt(std::string& src, char c , int pos)
 {
     std::string front(src.begin(), src.begin() + pos - 1 ); // use iterators
     std::string back(src.begin() + pos, src.end() );
     src = front + c + back; // concat together +-operator is overloaded for strings
 }

Не на 100% уверены, что позиции правильные.Возможно, передняя часть должна быть src.begin () + pos, а сзади src.begin () + pos + 1. Просто попробуйте.

0 голосов
/ 11 февраля 2019

Я упоминал, что могу видеть пять проблем с кодом, как показано (скопировано здесь для справки)

void appendCharact(char * source, char carac , int position)
{
    source = realloc(source, strlen(source) * sizeof(char) + 1); //Get enough memory
    char * temp = source.substr(position); //Save characters after my position
    source[position] = carac; //Add the charactere
}

Проблемы (в произвольном порядке):

  1. strlen(source) * sizeof(char) + 1 равно (strlen(source) * sizeof(char)) + 1.Это должно было быть (strlen(source) + 1) * sizeof(char).Тем не менее, это прекрасно работает, так как sizeof(char) определен в спецификации C ++, чтобы всегда было равно 1.

  2. В связи с вышеизложенным: Простой char строки действительно называются завершенными нулями байтовыми строками .Как таковые они должны заканчиваться нулевым символом ('\0').Этот нулевой символ, конечно же, требует места в выделенной строке, и он равен , а не , подсчитанному как strlen.Поэтому для добавления символа вам нужно выделить strlen(source) + 2 символов.

  3. Никогда не назначайте обратно указателю, который вы передаете, realloc.В случае сбоя realloc возвращается нулевой указатель, что приводит к потере исходной памяти, и это утечка памяти.

  4. Функция reallocтип возвращаемого значения void*.В C ++ вам нужно привести его к правильному типу указателя для присваивания.

  5. Вы передаете source на значение , то есть внутри функции у вас есть локальный копия указателя.Когда вы назначаете source, вы назначаете только локальную копию, исходный указатель, используемый в вызове, не будет изменен.


Вот некоторые другие проблемы с кодомили его возможное использование:

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

  • Если функция вызывается с source, являющимся литеральной строкой, массивом или чем-то, что не было возвращено предыдущим вызовом malloc, calloc или realloc, то вы не можете передать этоуказатель на realloc.

  • Вы используете source.substr(position), что невозможно, поскольку source не является объектом и, следовательно, не имеет функций-членов.

0 голосов
/ 11 февраля 2019
int pos = 1;
char toInsert = '-';
std::string text = "hallo";
std::stringstream buffer;
buffer << text.substr(0,pos);
buffer << toInsert;
buffer << text.substr(pos);
text = buffer.str();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...