Управление динамически размещенными двумерными массивами символов в C - PullRequest
0 голосов
/ 18 февраля 2019

У меня проблемы с попыткой манипулирования 2d динамическими массивами в C. Что я хочу сделать, это сохранить строку char в каждой строке массива 2d, а затем выполнить проверку, чтобы увидеть, содержит ли строка определенный символ, если это так, удалите все вхождения, затем сдвиньте пустые позиции.На самом деле я получаю exit status 1.

Подробнее о проблеме, например, если у меня есть

Enter string 1: testing
Enter string 2: apple
Enter string 3: banana

, я бы хотел, чтобы результат стал

What letter? a // ask what character to search for and remove all occurences
testing
pple
bnn

Вот мой полный код:

  #include <stdio.h>
  #include <stdlib.h>


  void removeOccurences2(char** letters, int strs, int size, char letter){
    // Get size of array
    // Shift amount says how many of the letter that we have removed so far.
    int shiftAmt = 0;
    // Shift array says how much we should shift each element at the end
    int shiftArray[strs][size];

    // The first loop to remove letters and put things the shift amount in the array
    int i,j;
    for(i=0;i < strs; i++){
        for(j = 0; j < size - 1; j++) {

              if (letters[i][j] == '\0'){
                  break;
              }

              else {
              // If the letter matches

              if(letter == letters[i][j]){

              // Set to null terminator
              letters[i][j] = '\0';
              // Increase Shift amount
              shiftAmt++;
              // Set shift amount for this position to be 0
              shiftArray[i][j] = 0;
              }else{
              // Set the shift amount for this letter to be equal to the current shift amount
              shiftArray[i][j] = shiftAmt;
              }
              }
        }
      }  

    // Loop back through and shift each index the required amount
    for(i = 0; i < strs; i++){
        for(j = 0; j < size - 1; j++) {
          // If the shift amount for this index is 0 don't do anything


          if(shiftArray[i][j] == 0) continue;
          // Otherwise swap
          letters[i][j - shiftArray[i][j]] = letters[i][j];
          letters[i][j] = '\0';

        }

        //now print the new string
        printf("%s", letters[i]);
    }
    return;
  }

  int main() {
      int strs;
      char** array2;
      int size;
      int cnt;
      int c;
      char letter;
      printf("How many strings do you want to enter?\n");
      scanf("%d", &strs);
      printf("What is the max size of the strings?\n");
      scanf("%d", &size);
      array2 = malloc(sizeof(char*)*strs);
      cnt = 0;
      while (cnt < strs) {
          c = 0;
          printf("Enter string    %d:\n", cnt + 1);
          array2[cnt] = malloc(sizeof(char)*size);
          scanf("%s", array2[cnt]);
          cnt += 1;
      }

        printf("What letter?\n");
      scanf(" %c", &letter);
      removeOccurences2(array2,strs,size,letter);

  }

Заранее спасибо!

Ответы [ 3 ]

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

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

Код может быть просто:

void removeOccurences2(char** letters, int strs, int size, char letter){
    int i,j,k;
    // loop over the array of strings
    for(i=0;i < strs; i++){
        // loop per string
        for(j = 0, k=0; j < size; j++) {
              // stop on the first null character
              if (letters[i][j] == '\0'){
                  letters[i][k] = 0;
                  break;
              }
              // If the letter does not match, keep the letter
              if(letter != letters[i][j]){
                  letters[i][k++] = letters[i][j];
              }
        }
        //now print the new string
        printf("%s\n", letters[i]);
    }
    return;
  }

Но вы должны освободить все выделенные массивыперед возвратом в среду и явно вернуть 0 в конце main.

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

Что ж, у вашей программы есть несколько проблем, в основном вы получаете ошибку segmentation fault, потому что вы обращаетесь к недействительной памяти, которая не выделена вашей программой.Вот некоторые проблемы, которые я обнаружил:

  1. shiftAmt не сбрасывается после обработки / проверки каждой строки, что приводит к неправильному значению shiftArray.
  2. Значения shiftArrayустанавливается только как ожидается для длины строки, но после этого (значения от длины каждой строки до size) являются случайными числами.
  3. Логика для удаления символа вхождения неверна - вам нужно сдвинуть всю строкупосле вхождения символа слева не просто манипулирование одним символом, как то, что вы делаете.

1 & 2 вызывает ошибку ошибки сегментации (сбой программы), потому что это вызывает доступ к этой строке letters[i][j - shiftArray[i][j]] = letters[i][j];неожиданной памяти.Вы можете взглянуть на мою отредактированную версию вашего removeOccurences2 метода для справки:

int removeOccurences2(char* string, char letter) {
    if(!string) return -1;
    int i = 0;

    while (*(string+i) != '\0') {
        if (*(string+i) == letter) {
            memmove(string + i, string + i + 1, strlen(string + i + 1));
            string[strlen(string) - 1] = '\0'; // delete last character
        }
        i++;
    }
    return 0;
}

Это всего лишь пример, и в его логике все еще есть некоторый недостаток, ожидающий вашего завершения.Подсказка: попробуйте случай: "bananaaaa123"

Удачного кодирования!

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

"... если строка содержит определенный символ, если это так, удалите все вхождения, затем сдвиньте пустые позиции."

Исходную строку можно редактировать на месте, увеличиваядва указателя, изначально содержащие одинаковое содержимое.Следующее иллюстрирует:

void remove_all_chars(char* str, char c) 
{
    char *pr = str://pointer read
    char *pw = str;//pointer write
    while(*pr) 
    {
        *pw = *pr++;     
        pw += (*pw != c);//increment pw only if current position == c
    }
    *pw = '\0';//terminate to mark last position of modified string
}

Это самая чистая и простая форма, которую я видел для выполнения этой задачи. Кредит идет на этот ответ .

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