Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C语言中处理动态分配的2D字符数组_C_Arrays_Memory Management - Fatal编程技术网

在C语言中处理动态分配的2D字符数组

在C语言中处理动态分配的2D字符数组,c,arrays,memory-management,C,Arrays,Memory Management,我在C语言中操作2d动态数组时遇到问题。我想做的是在2d数组的每一行中存储一个字符字符串,然后执行检查以查看该字符串是否包含某个字符,若包含,请删除所有出现的字符,然后移过空位置。实际发生的是我得到了退出状态1 更多关于这个问题的信息,例如,如果我有 Enter string 1: testing Enter string 2: apple Enter string 3: banana 我希望输出成为 What letter? a // ask what character to search

我在C语言中操作2d动态数组时遇到问题。我想做的是在2d数组的每一行中存储一个字符字符串,然后执行检查以查看该字符串是否包含某个字符,若包含,请删除所有出现的字符,然后移过空位置。实际发生的是我得到了退出状态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);

  }
提前谢谢

…如果字符串包含某个字符,则删除所有出现的字符,然后在空位置上移动

通过增加最初包含相同内容的两个指针,可以就地编辑原始字符串。以下说明:

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
}
这是我见过的完成这项任务的最干净、最简单的形式

…如果字符串包含某个字符,则删除所有出现的字符,然后在空位置上移动

通过增加最初包含相同内容的两个指针,可以就地编辑原始字符串。以下说明:

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
}

这是我见过的完成这项任务的最干净、最简单的形式

您可以在适当的位置删除字符串中的字母,因为您只能缩短字符串

代码可以是:

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

但是,在返回到环境之前,您应该释放所有分配的数组,并在main的末尾显式返回0。

您可以在适当的位置删除字符串中的字母,因为您只能缩短字符串

代码可以是:

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

但是,在返回到环境之前,您应该释放所有分配的数组,并在main的末尾显式返回0。

好吧,您的程序有几个问题,基本上您会遇到分段错误,因为您访问的是无效内存,而该内存不是由您的程序分配的。以下是我发现的一些问题:

在处理/检查导致移位数组值不正确的每个字符串后,移位数组不会重置。 shiftArray的值仅设置为字符串长度的预期值,但在此之后,从每个字符串的长度到大小的值都是随机数。 删除出现字符的逻辑不正确-您需要将出现字符后的整个字符串向左移动,而不是像现在这样操作单个字符。 1和2导致分割错误导致程序崩溃,因为它导致此行字母[i][j-shiftArray[i][j]=letters[i][j];访问意外内存。您可以查看我编辑的RemoveOccurnces2方法版本,以供参考:

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;
}
这只是一个示例,它的逻辑中仍然有一些缺陷等待您完成。提示:尝试案例:Bananaaa123


快乐编码

好吧,你的程序有几个问题,基本上你会遇到分段错误,因为你正在访问无效的内存,而这些内存不是你的程序分配的。以下是我发现的一些问题:

在处理/检查导致移位数组值不正确的每个字符串后,移位数组不会重置。 shiftArray的值仅设置为字符串长度的预期值,但在此之后,从每个字符串的长度到大小的值都是随机数。 删除出现字符的逻辑不正确-您需要将出现字符后的整个字符串向左移动,而不是像现在这样操作单个字符。 1和2导致分割错误导致程序崩溃,因为它导致此行字母[i][j-shiftArray[i][j]=letters[i][j];访问意外内存。您可以查看我编辑的RemoveOccurnces2方法版本,以供参考:

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;
}
这只是一个示例,它的逻辑中仍然有一些缺陷等待您完成。提示:尝试案例:Bananaaa123


快乐编码

从字符串中删除字母的正确方法只是在字符串上保留两个索引:一个读取索引在每一步递增一个,一个写入索引仅在字母与要删除的字母不匹配时递增。更简单只意味着更健壮。OT:关于如下语句:array2[cnt]=mallocsizeofchar*size;1表达式:sizeofchar在C标准中定义为1。乘以1没有效果。建议在调用任何堆分配函数时删除表达式2:malloc calloc realloc,始终选中=NULL返回值以确保操作成功。如果未成功,则调用perror以输出错误消息和系统认为发生错误的文本原因。OT:调用任何scanf系列函数时;1始终检查返回值而不是参数值,以确保在这种情况下操作成功。如果返回值不等于1,则函数失败。2使用输入格式说明符“%s”和/或“%[…]”时,始终包含一个最大值c
小于输入缓冲区长度1的字符修饰符,因为这些说明符总是附加NUl字节。这也避免了缓冲区溢出和由此产生的未定义行为的任何可能性;和int c;?它们对发布的代码不起任何作用,并且会导致编译器输出一条关于已设置变量但未使用的消息。点:为了便于可读性和理解:1请始终缩进代码。在每个左大括号“{”之后缩进。在每个右大括号“}”之前取消缩进。建议每个缩进级别为4个空格2请遵循公理:每行只有一条语句,每条语句最多一个变量声明。从字符串中删除字母的正确方法是在字符串上保留两个索引:一个读取索引,每一步递增一个,一个写入索引,仅当字母与要删除的字母不匹配时才递增。更简单只意味着更健壮。OT:关于如下语句:array2[cnt]=mallocsizeofchar*size;1表达式:sizeofchar在C标准中定义为1。乘以1没有效果。建议在调用任何堆分配函数时删除表达式2:malloc calloc realloc,始终选中=NULL返回值以确保操作成功。如果未成功,则调用perror以输出错误消息和系统认为发生错误的文本原因。OT:调用任何scanf系列函数时;1始终检查返回值而不是参数值,以确保在这种情况下操作成功。如果返回值不等于1,则函数失败。2在使用输入格式说明符“%s”和/或“%[…]”时,始终包含比输入缓冲区长度小1的最大字符修饰符,因为这些说明符始终附加NUl字节。这也避免了缓冲区溢出和由此产生的未定义行为的任何可能性;和int c;?它们对发布的代码不起任何作用,并且会导致编译器输出一条关于已设置变量但未使用的消息。点:为了便于可读性和理解:1请始终缩进代码。在每个左大括号“{”之后缩进。在每个右大括号“}”之前取消缩进。建议每个缩进级别为4个空格2请遵循公理:每行只有一条语句,每条语句最多有一个变量声明。在现代c中,除非另有明确说明,否则main的返回值假定为0。在现代c中,除非另有明确说明,否则main的返回值假定为0