【问题标题】:C: Convert variable length 2D array into 1d stringC:将可变长度二维数组转换为一维字符串
【发布时间】:2017-01-24 20:16:12
【问题描述】:

考虑一个 char** 类型的二维数组。这个数组的行数是有限的(子串的数量),但列的长度是可变的(子串的长度是可变的)。

我想创建一个函数,该函数将此数组和行数(子字符串)作为参数,并返回由每个有序子字符串(行)组成的单个字符串。它是一个简单的连接。这是 question 的相反行为。

我为此编写了以下代码,但它仅在每个子字符串的长度相同(恒定列长度)时才有效,因此我将最大列长度作为函数参数传递:

char* cat2dCharMat(char** A, int m, int n){

    char* temp = malloc((m*n+1));
    int length = 0;
    for(int i = 0; i < m;++i){
        memcpy(&temp[n*i], A[i],strlen(A[i]));
        length += (int)strlen(A[i]);
    }
    temp[length] = '\0';
    printf("Length of concatenated string is %d chars.\n",strlen(temp));
    return temp;
}

我怎样才能使它更通用以容纳许多列长度?我还编写了一个 main() 来配合这个函数,以获得一个完整的、最小的、可验证的示例(原谅二维数组初始化——我发现使用 array = {"hello", "world!"} 不起作用):

int main(void){
    char** array2 = (char**)malloc((3)*sizeof(char*));
    for(int i = 0; i < 3; ++i){
        array2[i] = (char*)malloc(4*sizeof(char));
        for(int j = 0; j < 3;++j){
            if(j==0 && i==0)
                array2[i][j] = '0';
            else if(j==1 && i==0)
                array2[i][j] = '8';
            else if(j==2 && i==0)
                array2[i][j] = '7';
            else if(j==0 && i==1)
                array2[i][j] = '4';
            else if(j==1 && i==1)
                array2[i][j] = '9';
            else if(j==2 && i==1)
                array2[i][j] = '5';
        }
    }
    char** array1 = (char**)malloc((3)*sizeof(char*));
    for(int i = 0; i < 3; ++i){
        if(i == 0){
            array1[i] = malloc(4);
            for(int j = 0; j < 3;++j){
                if(j==0 && i==0)
                    array1[i][j] = '0';
                else if(j==1 && i==0)
                    array1[i][j] = '8';
                else if(j==2 && i==0)
                    array1[i][j] = '7';
            }
        }else{
            array1[i] = malloc(5);
            for(int j = 0; j < 4;++j){
                if(j==0 && i==0)
                    array1[i][j] = '0';
                else if(j==1 && i==1)
                    array1[i][j] = '8';
                else if(j==2 && i==1)
                    array1[i][j] = '7';
                else if(j==3 && i==1)
                    array1[i][j] = '7';
            }
        }
    }
    array1[0][3] = '\0';
    array1[1][4] = '\0';
    char* array1cat = cat2dCharMat(array1,2,4);
    char* array2cat = cat2dCharMat(array2,2,3);
    printf("Testing cat2dCharMat()...\n\n");
    printf("Case 1: {\"087\",\"495\"}\n");
    printf("Expected Result: 087495\n");
    printf("Actual Result:   %s\n", array2cat);
    printf("Case 2:{\"087\",\"0877\"}\n");
    printf("Expected Result: 0870877\n");
    printf("Actual Result:   %s\n", array1cat);
    }

【问题讨论】:

  • char ** 之类的东西不是二维数组。 可变长度数组是完全不同的数据类型。
  • 你只有一个字符串数组。您可以对其进行一次迭代,获取每个字符串的长度并对长度求和,然后分配一个足够大的缓冲区以将它们连接在一起。顺便说一句——这是一篇有趣的博客文章,它讨论了连接大量字符串的问题:joelonsoftware.com/2001/12/11/back-to-basics(由 Stack Overflow 的联合创始人之一撰写)
  • 1) 在 else-block if(j==0 &amp;&amp; i==0) --> if(j==0 &amp;&amp; i==1) 2) memcpy(&amp;temp[n*i], A[i],strlen(A[i])); --> memcpy(&amp;temp[length], A[i],strlen(A[i]));

标签: c arrays string


【解决方案1】:

我不太了解您希望函数的第二个参数(“行数(子字符串)”),所以这是一个连接“数组”的 n 第一个字符串的想法(这不是数组,C: differences between char pointer and array)

请注意,它根本不是一个安全的函数,因为 它不会检查你给 n 的值对于你的变量来说不是很大(它会引发分段错误);在你自己的代码中实现你自己的函数时要注意这一点。

char * concatenate_these_strings (char ** my_strings ,unsigned int n){
    int i,size = 1;
    for ( i=0 ; i<n ; i++){
            size += strlen (my_strings[i]);
    }
    char * my_result = malloc (size);
    for ( i=0 ; i<n ; i++){
        strcat (my_result,my_strings[i]);
    }
    return my_result;
}

【讨论】:

  • 你没有允许最后的空字节,是吗?
  • 已编辑,感谢提醒。如果字符串从一开始就以'\0' 结尾,那应该不是问题,不是吗?
  • 别忘了strlen()的长度不包含终止的空值,所以你必须在沿线的某个地方添加一个来弥补它。
猜你喜欢
  • 2019-01-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 1970-01-01
  • 2013-03-27
  • 2016-02-22
相关资源
最近更新 更多