Разделить текст с помощью разделителя? - PullRequest
0 голосов
/ 08 апреля 2020

Я хотел создать функцию, которая будет разбивать строку разделителем. Я знаю, что уже есть функция, которая делает это, но я хотел сделать это самостоятельно. Но она не работает так, как должна.

char** Engine::splitString(const char* text, char delimiter)
{

  char** splitted;  
  splitted = (char**)malloc(50 * sizeof(char*));
  for (int y = 0; y < 50; y++)
    splitted[y] = (char*)malloc((strlen(text) + 2) * sizeof(char));

  int delimiterPosition[50];
  int arrayLength = 0;
  int f = 0;
  int g = 0;
  for (int x = 0; x < strlen(text); x++)    
  {
    if (text[x] == delimiter)
    {
        delimiterPosition[f] = x;
        f++;
    }
  }

  for (int x = 0; x < 50; x++)
    if (delimiterPosition[x] > 0 )
        arrayLength++;


  while (g < arrayLength) {
     if (g == 0) {
        for (int y = 0; y < delimiterPosition[0]; y++)
        {
            splitted[g][y] = text[y];
        }
    }
    else if(g > 0)
    {
        for (int y = delimiterPosition[g - 1]; y < delimiterPosition[g] - delimiterPosition[g - 1]; y++)
        {
            splitted[g][y] = text[y];
        }
    }
    g++;
}
return splitted;
}

Прежде всего, я объявил двумерный массив символов -> split. Это была переменная, в которой я должен хранить свои результаты. Затем я выделил память для этого .. Я хотел, чтобы максимум 50 слов. После этого я создал массив целых чисел .. он служил хранилищем для позиций разделителей. Я также определил некоторые переменные под ним для моего кода. Затем я перебрал текст, чтобы увидеть, есть ли какой-либо разделитель. Если да, я хотел сохранить его положение в определенной позиции в массиве, начиная с 0. Я перебрал массив delimiterPosition до того, сколько позиций я сохранил. Затем я сделал простой l oop, используя while, чтобы перевести все символы в положение разделителя и сохранить их в splitted [g] [y] .. g представляет целое слово .. y представляет символ в этом слове. Если g был больше нуля, я помечал предыдущую позицию разделителя, а затем вычитал ток из предыдущего .. и это дало мне расстояние между первым разделителем и следующим ..

Основная проблема здесь в том, что первое слово написано правильно, второе не работает, но за ним стоят какие-то странные символы, когда я пытаюсь его назвать .. текст каким-то образом протекает? второй вообще не сохраняется?:

    char** strings = en.splitString("Hello;boy", ';');
    printf("%s", strings[1]);

Первое слово: enter image description here

Второе: enter image description here

Какие-нибудь решения, ребята? :) Спасибо за любой комментарий.

1 Ответ

2 голосов
/ 08 апреля 2020

Это не инициализирует память:

 int delimiterPosition[50];

Таким образом, его содержимое потенциально случайное (и его неопределенное значение для чтения, если вы не инициализируете его сначала). Итак, здесь:

 if (delimiterPosition[x] > 0 ) // Is potentially invalid if x >= f

Легко решается с помощью:

 int delimiterPosition[50] = {0};

Потенциал для переполнения здесь:

        delimiterPosition[f] = x;
        f++;

Вы не подтвердите это f остается в правильном диапазоне (менее 50). Еще одно простое решение:

  size_t stringLen = strlen(text); // Don't need to recalculate this each time!
  for (int x = 0; f < 50 && x < stringLen; x++)    
  {
    if (text[x] == delimiter)
    {
        delimiterPosition[f] = x;
        f++;
    }
  }

Вот проблема, на которую вы жалуетесь:


    for (int y = 0; y < delimiterPosition[0]; y++)
    {
        splitted[g][y] = text[y];
    }

Вы копируете строку.
Но вы этого не делаете добавить терминатор к строке. Поэтому, когда вы попытаетесь распечатать его, вы увидите все дополнительные символы в конце.

    for (int y = 0; y < delimiterPosition[0]; y++)
    {
        splitted[g][y] = text[y];
    }
    splitted[g][y] = '\0';  // Add string terminator.

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

        // After the first string the value of y in an offset into text only
        // So when used with `splitted[g]` you are offset from the beginning
        // if the string.
        splitted[g][y] = text[y];

Также ваш тест на конец строки неверен:

Помните, что вы начинаете с:

int y = delimiterPosition[g - 1]

Итак, у - это смещение в строке. Поэтому при увеличении его всегда будет смещение, а не длина.

// So this test is wrong (you are using a length not an offset.
y < delimiterPosition[g] - delimiterPosition[g - 1]

Позволяет исправить оба значения одновременно:

    int dstIndex = 0;
    for (int y = delimiterPosition[g - 1]; y < delimiterPosition[g]; y++, dstIndex++)
    {
        splitted[g][dstIndex] = text[y];
    }
    splitted[g][dstIndex] = '\0';
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...