简体   繁体   English

在 C 中操作动态分配的二维字符数组

[英]Manipulating dynamically allocated 2D char arrays in C

I'm having trouble with trying to manipulate 2d dynamic arrays in C. What I want to do is to store a char string in every row of the the 2d array then perform a check to see if the string contains a certain character, if so remove all occurrences then shift over the empty positions.我在尝试在 C 中操作二维动态数组时遇到问题。我想要做的是在二维数组的每一行中存储一个字符字符串,然后执行检查以查看字符串是否包含某个字符,如果是这样删除所有事件,然后转移到空位置。 What's actually happening is I get an exit status 1 .实际发生的是我得到exit status 1

More about the problem, for example if I have有关问题的更多信息,例如,如果我有

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

I would want the output to become我希望输出变成

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

Here is my full code:这是我的完整代码:

  #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);

  }

Thanks in advance!提前致谢!

You can remove letters from a string in place, because you can only shorten the string.您可以就地从字符串中删除字母,因为您只能缩短字符串。

The code could simply be:代码可以简单地是:

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;
  }

But you should free all the allocated arrays before returning to environment, and explicitely return 0 at the end of main .但是你应该在返回环境之前释放所有分配的数组,并在main的末尾明确返回 0 。

"...if the string contains a certain character, if so remove all occurrences then shift over the empty positions." “...如果字符串包含某个字符,则删除所有出现的字符,然后移至空位置。”

The original string can be edited in place by incrementing two pointers initially containing the same content.可以通过增加最初包含相同内容的两个指针来就地编辑原始字符串。 The following illustrates.:下面举例说明:

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
}

This is the cleanest, simplest form I have seen for doing this task.这是我见过的最干净、最简单的形式来完成这项任务。 Credit goes to this answer .归功于这个答案

Well, there are several issues on your program, basically you are getting segmentation fault error because you are accessing invalid memory which isn't allocated by your program.好吧,您的程序存在几个问题,基本上您会收到segmentation fault错误,因为您正在访问不是由您的程序分配的无效内存。 Here are some issues I found:以下是我发现的一些问题:

  1. shiftAmt isn't reset after processing/checking each string which lead to incorrect value of shiftArray . shiftAmt在处理/检查每个导致shiftArray值不正确的字符串后不会重置。
  2. Values of shiftArray only set as expected for length of string but after that (values from from length of each string to size ) are random numbers. shiftArray值仅按预期的字符串长度设置,但之后(从每个字符串的长度到size )是随机数。
  3. The logic to delete occurrence character is incorrect - you need to shift the whole string after the occurrence character to the left not just manipulating a single character like what you are doing.删除出现字符的逻辑不正确 - 您需要将出现字符后的整个字符串向左移动,而不仅仅是像您正在做的那样操作单个字符。

1 & 2 cause the segmentation fault error (crash the program) because it causes this line letters[i][j - shiftArray[i][j]] = letters[i][j]; 1 & 2 导致分段错误错误(程序崩溃),因为它导致这行letters[i][j - shiftArray[i][j]] = letters[i][j]; access to unexpected memory.访问意外的内存。 You can take a look at my edited version of your removeOccurences2 method for reference:您可以查看我编辑过的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;
}

It's just an example and there is still some flaw in its logics waiting for you to complete.这只是一个例子,它的逻辑还有一些缺陷等待你完成。 Hint: try the case: "bananaaaa123"提示:试试这个案例:“bananaaaa123”

Happy coding!快乐编码!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM