【问题标题】:C - Passing a 3D arrays of chars to a functionC - 将 3D 字符数组传递给函数
【发布时间】:2017-05-19 15:23:04
【问题描述】:

我正在尝试编写一个程序来分析用户提供的 (3 x 4) 字符串矩阵。最终,它需要输出矩阵中存在的最长字符串以及该字符串的长度。

我的程序似乎正确地读取了输入,因为它成功地回显了输入字符串,但它没有正确输出最长的单词。当我传递最长单词的值时,我确定我犯了某种与指针相关的错误,但我不知道如何解决它。

这是我的代码:

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

#define M 4
#define N 5
#define MAX_DIM 20

void findMAX(char matrice[N][M][MAX_DIM]) {
   char maxr;
   int index;
   int i, j, it;

   index = 0;
   maxr = *(*(*(matrice+0)+0)+MAX_DIM);

   for (i = 0; i < N-1; i++) {
      for (j = 0; j < M-1; j++) {
         if (index < strlen(matrice[i][j])) {
            index = strlen(matrice[i][j]);

            // I save the longer line's value            
            it = i;

            // I save the maximum's value
            maxr = *(*(*(matrice+i)+j)+MAX_DIM);
         }
      }
   }

   printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
   printf ("It is content in the: %d line, which is: \n", it);
   for (j = 0; j < N-1; j++) {
        printf("%s  ", matrice[it][j]);
   }
}

void leggi(char matrice[N][M][MAX_DIM]) {
    int i, j;

    for (i = 0; i < N-1; i++) {
        for (j = 0; j < M-1; j++) {
            printf ("Insert the element matrix [%d][%d]: ", i, j);
            scanf  ("%s", matrice[i][j]); 
            fflush(stdin);
        }
    }
}

void stampa(char matrice[N][M][MAX_DIM]) {
    int i, j;

    printf("\n(4 x 3) MATRIX\n");
    for (i = 0; i < N-1; i++) {
        for (j = 0; j < M-1; j++) {
            printf("%s ", matrice[i][j]);
        }
        printf("\n\n");
    }
}

int main(int argc, char *argv[]) {
    char matrix[N][M][MAX_DIM]; //Matrix of N*M strings, which are long MAX_DIM

    printf("************************************************\n");
    printf("**   FIND THE LINE WITH THE MAXIMUM ELEMENT   **\n");
    printf("**            IN A (4 x 3) MATRIX             **\n");
    printf("************************************************\n");

    printf ("Matrix Reading & Printing\n");
    leggi  (matrix);
    stampa (matrix);

    findMAX(matrix);

    return 0;
}

【问题讨论】:

  • C 不支持传递引用从不
  • 首先,您似乎错过了 C 没有通过引用传递。所有函数参数都按值传递。这些可能包括指针,但通过值传递指向事物的指针与通过引用传递事物本身不同。
  • @JohnBollinger 对不起,我的错误。谢谢你的解释。
  • 问题是您可能在某处反转了您的尺寸。 Also: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
  • 在所有for 循环中,您已经反转维度,最后一项应该是matrice[N - 1][M - 1],但您正试图访问matrice[M - 1][N - 1] 之类的东西.

标签: c string multidimensional-array


【解决方案1】:

首先要解决另一个答案传达的一些误解,请考虑将您的 3D 数组声明为

char matrix[N][M][MAX_DIM];

,其中NMMAX_DIM 是扩展为整数常量的宏。

  • 这是一个普通数组(不是变长数组)。
  • 如果您想将此数组传递给函数,完全可以按照声明数组的方式声明相应的函数参数,就像您所做的那样:
    void findMAX(char matrice[N][M][MAX_DIM]) 
  • 但确实实际传递的不是数组本身,而是指向其第一个元素的指针(通过它也可以访问所有其他元素。在C中,多维数组是数组的数组,所以第一个元素一个三维数组就是一个二维数组。无论如何,该函数声明等价于这两个:

    void findMAX(char (*matrice)[M][MAX_DIM]) 
    
    
    void findMAX(char matrice[][M][MAX_DIM]) 
    

    特别注意第一个维度没有被传达。在这三种等效形式中,我发现在大多数情况下,最后一种是最清晰的。

不过,在 findMAX() 函数中访问数组元素的方式很奇怪。这是您所做的典型示例:

        maxr = *(*(*(matrice+i)+j)+MAX_DIM);

但是,这是一个多么丑陋和令人困惑的表达,尤其是与这个保证等效的表达相比:

        maxr = matrice[i][j][MAX_DIM];

然而,看看你如何使用它,我发现虽然赋值是类型正确的,但你可能使用了错误的类型。 maxr 拥有一个 char。如果您的意思是以某种方式捕获整个字符串的值,那么您需要将其声明为数组(您将根据需要将字符串的内容复制到该数组中),或者您将设置为指向字符串的指针出于兴趣。后一种方法更有效,对于您的特定用途,我认为没有什么可推荐的。

因此,我想你想要

    char *maxr;

...后来...

        maxr = matrice[0][0];

...和...

        maxr = matrice[i][j];

你应该对这种用法很熟悉,例如,你的函数stampo();主要区别在于,现在您将表达式分配给变量,而不是直接将其传递给函数。

事实证明,以这种方式更改 maxr 的类型将纠正这里的真正问题,@AnttiHaapala 已经在 cmets 中指出:这个函数调用 ...

    printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);

要求第二个参数 (maxr) 是指向以 null 结尾的 char 数组的指针,以便与格式字符串中的 %s 指令相对应。之前,您只传递了一个 char,但通过此更正,您应该得到大部分预期的结果。

但是,您可能会看到至少一个额外的异常。您在该函数中的最后一个循环有错误的界限。您正在使用j 进行迭代,它用作数组第二维的索引。该维度的范围是M,但循环运行到N - 1

最后,我应该注意到,您为 5 x 4 数组(char 数组)分配空间然后忽略最后一行和最后一列是很奇怪的。但这只是浪费,没有错。

【讨论】:

    【解决方案2】:

    试试这样的:

    void findMAX(char matrice[N][M][MAX_DIM]){
    //   char maxr
       char maxr[MAX_DIM];
       int index;
       int i, j, it;
    
       index = 0;
    //   maxr = *(*(*(matrice+0)+0)+MAX_DIM);
       strncpy(maxr, *(*(matrice+0)+0), MAX_DIM);
    
       for (i = 0; i < N-1; i++)
       {
          for (j = 0; j < M-1; j++)
          {
             if (index < strlen(matrice[i][j]))
             {                   
                index = strlen(matrice[i][j]);
                it = i;
    //            maxr = *(*(*(matrice+i)+j)+MAX_DIM);
                strncpy(maxr, *(*(matrice+i)+j), MAX_DIM);
             }
          }
       }
    
       printf ("The MAX is: -/%s/- and it's long: -/%d/- \n", maxr, index);
       printf ("It is content in the: %d line, which is: \n", it);
    //   for (j = 0; j < N-1; j++){
       for (j = 0; j < M-1; j++){   
            printf("%s  ", matrice[it][j]);
       }
    }
    

    【讨论】:

    • 他为什么要这么做?它比原版有什么优势?您认为此版本解决了什么问题?
    • @miraklis 我尝试使用strncpy 函数,但我以错误的方式操作,因为你的工作顺利。 @JohnBollinger 它实际上解决了我在输出中遇到的问题。
    • @John Bollinger,我注释掉了我认为错误的部分。主要问题是 maxr 不是一个数组,我认为它应该是。
    • 不要在 cmets 中回答我,@miraklis,改进你的答案!对于它的价值,我认为将 maxr 设为一个数组是很笨拙的,但我认为你可能是对的,它的类型不适合其预期用途。将其设为char * 会更好,因为不需要复制字符串。
    【解决方案3】:

    如果在编译时知道次要维度的大小,则可以将多维数组传递给 C 函数。但是语法是不可接受的

     void foo( int (*array2d)[6] )
    

    通常数组维度在编译时是未知的,因此需要创建一个平面数组并通过以下方式访问

       array2D[y*width+x]
    

    通常,即使数组维度已知,使用此方法也会更容易。

    为了回应评论澄清,C99 允许使用更直观的语法传递可变大小的数组。但是,微软的 Visual C++ 编译器不支持该标准,这意味着您不能将其用于许多实际用途。

    【讨论】:

    • 我不确定你在这里想说什么。您提出的语法当然很好,但 OP 的语法也很好(例如,类似于void foo(int array2d[5][6]))。就个人而言,我更喜欢void foo(int array2d[][6]) 的形式。
    • 抱歉我的无知,但是,定义一个像char matrix[N][M][MAX_DIM]这样的3D数组是错误的吗?
    • 不,@PierpaoloDV,这不是错误。这里的微妙之处在于,当该形式用于声明函数参数时,它实际上声明了一个char (*)[M][MAX_DIM] 类型的指针。但这正是接收由类型为 char[N][M][MAX_DIM] 的表达式给出的实际参数的正确类型,所以一切都如您天真地期望的那样。
    • 这与变长数组无关。 OP 的NMMAX_DIM 是扩展为整数常量的。这里没有 VLA,MSVC 不应以此为基础拒绝 OP 的代码。
    • @JohnBollinger 所以我应该定义 maxr 不像 char maxr 而是 char (*maxr)[M][MAX_DIM] ?而且我只想说我的编码水平很低,我的老师也不是很乐于助人。你所说的一切对我很有帮助。
    猜你喜欢
    • 2012-01-12
    • 2015-09-09
    • 2013-06-27
    • 2016-08-30
    • 2014-10-27
    • 1970-01-01
    • 1970-01-01
    • 2017-06-29
    • 2017-04-05
    相关资源
    最近更新 更多