2015-05-21 35 views
1

对于我的编程类,我们必须创建一个调用子函数的程序(保存为.h)。 我能够用简单的函数做到这一点,但是当传递2维数组(更高)时,它变得很难。 我已经尝试了多次,并没有运气。如何将矩阵传递给.h函数并返回浮点数?

这里是我的主函数调用段:

switch (selection) 
{ 
     case 1: 
      determinant = det(m[0],n[0],Mat_1); 
      printf("\nDeterminant of Matrix 1 is: %f\n",determinant); 
      break; 

,这里是我的.h文件中找到一个2×2矩阵的行列式:

float det(int a, int b, float Mat[a][b]) 
{ 
    printf("%f\n%f\n%f\n%f\n",Mat[0][0],Mat[0][1],Mat[1][0],Mat[1][1]); 
    float det; 
    det = ((Mat[0][0]*Mat[1][1])-(Mat[0][1]*Mat[1][0])); 
    return det; 
} 

基本上我是聚集子函数(det.h)似乎没有收到2维数组。

我知道这有点冗长,但这里是我的整个代码.c(主)文件。

非常感谢您的时间。

最亲切的问候, 汤姆

#include <stdio.h> 
#include "det.h" 

int main(void) 
{ 

    int m[3],n[3],number,i,j,selection; 
    float determinant; 


    printf("Enter number of matrices you wish to deal with:"); 
    scanf("%d",&number); 
    while ((number<1.0)||(number>2)) 
    { 
      printf("1 or 2 matrices only please.\n"); 
      scanf("%d",&number); 
    } 

    for (i=0;i<number;i++) 
    { 
     printf("Enter dimensions (m x n) of Matrix [%d]:\n",i+1); 
     scanf("%d %d",&m[i],&n[i]); 
    } 

    float Mat_1[m[0]][n[0]],Mat_2[m[1]][n[1]]; 

    for (i=0;i<m[0];i++) 
    { 
     for (j=0;j<n[0];j++) 
     { 
      printf("Enter Data for Matrix 1 [%d][%d]:",i+1,j+1); 
      scanf("%d",&Mat_1[i][j]); 
     } 
    } 

    if (number=2) 
    for (i=0;i<m[1];i++) 
    { 
     for (j=0;j<n[1];j++) 
     { 
      printf("Enter Data for Matrix 2 [%d][%d]:",i+1,j+1); 
      scanf("%d",&Mat_2[i][j]); 
     } 
    }  

    printf("\nSELECT ONE OF THE FOLLOWING:\n1. Determinant\n2. Addition\n3. Subtraction\n4. Multiply\n5. Transpose\n6. Scale\n7. Print"); 
    scanf("%d",&selection); 
    while ((selection<1)||(selection>7)) 
    { 
      printf("Invalid selectoin, try again (1-7):"); 
      scanf("%d",&selection); 
    } 

    switch (selection) 
    { 
      case 1: 
       determinant = det(m[0],n[0],Mat_1); 
       printf("\nDeterminant of Matrix 1 is: %f\n",determinant); 
       break; 
      default: 
       printf("\nAn Error has occured.\n"); 
    } 


    system("pause"); 
    return 0; 
} 
+4

OMG,你在'.h'中有函数_definition_?迟早你会遇到一些麻烦。 –

+0

我应该如何存储单独的功能? 我们打算将它们保存为单独的文件并对它们进行调用。 –

+0

你创建单独的源文件'.c'并编译并链接在一起。那是最好的出路。 –

回答

2

首先,你应该把在.c文件的定义,并声明在.h文件中。这意味着det函数的主体不应位于.h文件中。

其次,您需要检查您的编译器是否支持variable length arrays。否则,可以将指针或固定大小(编译时已知的维数)数组或数组未赋值的数组传递给函数,然后将数组边界作为单独的参数传递。

使用静态分配的数组,它看起来是这样的:

  1. 你有一个matrices.h文件,它包含的声明,其目的是通过其他编译单位包括在内。还应该确保你不包括两次从任何地方:

    // matrices.h 
    #ifndef _MATRICES_H_ 
    #define _MATRICES_H_ 
    
    #define MAXROWS 10 
    #define MAXCOLS 20 
    
    // calculates the determinant 
    float det(float array[MAXROWS][MAXCOLS], int rows, int cols); 
    
    #endif 
    
  2. 然后创建一个单独的.c文件(matrices.c),其中将包括报头,并提供实际实现(可任选包含私人功能和字段):

    // matrices.c 
    #include "matrices.h" 
    
    float det(float array[MAXROWS][MAXCOLS], int rows, int cols) 
    { 
        int i; 
        for (i=0; i < rows; i++) 
        { 
         int j; 
         for (j=0; j < cols; j++) 
         { 
          // do stuff with array[i][j] 
         } 
        } 
    } 
    
  3. main.c只需要包含头文件。这将使编译器从matrices翻译单元单独编译maintranslation unit,只需知道的det签名:

    // main.c 
    #include "matrices.h" 
    
    void main(void) 
    { 
        ... 
    } 
    

更新

在.H你可以地方职能文件,也许你的老师真的有这个想法,但它不是放置它们的正确位置。

C构建应用程序的方式是编译每个应用程序。c文件分开,然后将中间文件链接到最终的可执行文件中。这个概念对新手程序员来说通常是不清楚的,但是如果你打算在C中编写一个家庭作业,除了编写任务之外,了解这个过程是非常重要的。我也假定你知道声明一个函数(写它的签名),并定义它(编写它的实现,即body)。声明的要点是当某个函数调用另一个函数(在别处定义,或者甚至低于该调用者函数)时,为编译器准备好方法签名(即使它们在不同的.c文件中)。对于编译器,这些声明是一个承诺这些功能存在于某个地方,并且链接器将能够提供一次翻译单元编译他们的确切位置。

还要注意,报关单独自在最终的可执行文件没有“权重”。如果您包含一个包含数百个声明的大型头文件(例如标准头文件),并且只使用一个函数,则只有被引用函数的代码才会包含在最终可执行文件中(以及该函数运行所需的任何代码,当然)。

所以编译器首先需要一个单独的.c文件,并运行它通过预处理器。预处理是非常愚蠢的:它只是替换所有#includes实际.h文件(插入他们的文本内容),代替#defines与他们的价值观,并删除那些#ifdef S的计算结果为假,直到起始.c文件变成一个单一的。 c文件(文本),它没有标记并准备编译。因此,如上所述,在编译这个单一的.c文件(现在已经增长)的同时,编译器对所有使用该.c文件引用的函数进行签名(声明),但驻留在其他编译单元中。这是头文件的目的,以避免必须在每个.c文件中声明所有这些外部签名。在某种程度上,它们是其他翻译单元的“公共接口”,因为其他.c文件只会通过包含头文件了解它们所获得的功能。

在这一点上,你可能会注意到两两件事:

  1. 如果.c文件包含几个头文件,其中还包括其他的头文件,它很容易卡住在递归的预处理器,或者符号最终被定义多次。这就是为什么所有头文件(通常)都以#ifndef (some-unique-symbol)开头,接着是#define (some-unique-symbol),因为它确保了只要这个唯一符号第一次被定义,预处理器将在下一次包含尝试时跳过它。一个非标准的(但广泛支持的)指令以更简单的方式完成同样的事情是pragma once(意思是“每个编译单元只包含一次这个头文件”)。请记住:编译再次包含头文件启动编制下.c文件时 - 这意味着所有#defines只“活”的一个翻译单元内。

  2. 如果一个函数的定义(没有宣布,但实际上定义,其整个身体)一个头文件(而不是.c文件)里,然后每个翻译单元得到整个的自己独立的副本函数,只要它包含该头文件 - 意味着代码在最终的可执行文件中被物理地复制。这可能不是你想要的 - 功能的点是提取公共功能到一个地方,减少重复。唯一一次你真的想在一个头文件中放置一个函数的时候,就是当你想定义一个函数时 - 一个函数应该(为了性能的原因)被优化和插入到位(类似于预处理器应该做的一个宏的定义) - 在这种情况下,很明显你确实需要每个.c文件都需要以获得它自己的副本。

翻译单元之间的实际链接发生在最后,当所有的单元被编译成中间文件。在最后阶段,链接器将用函数的实际地址替换每个函数调用到一个承诺的(声明的,外部的)函数(或者如果它不能解决它,则抛出一个错误)。因此,每个编译单元(一个带有相应头文件的.c文件)都可以作为C中的一种模块。你可以在这个头文件中定义某些结构/数据类型,声明对它们进行操作的函数,并且他们将他们的实现写入.c文件。这个.c文件通常会包含它自己的头文件(只是为了获得它自己函数的声明)以及它需要完成它的工作的任何头文件。

有关您的问题的有趣之处在于,如果您只有一个main.c(仅包含每个头文件一次),那么这些函数实际上不会在其他任何地方复制。在这种情况下,它可以毫无问题地工作,但这是错误的 - 正确的选择并不复杂:只需将这些函数移动到.c文件中,然后回到“正确执行”。

或者,您甚至不需要.h文件。您可以声明main.c中的所有函数,并在其他.c文件中定义它们的定义。这将是一个更正确的方式做到这一点:

// main.c 

#include <stdio.h> 

// no need to include any headers, because you will write 
// declarations here: 
// (extern keyword can be omitted, it just makes it more 
// obvious that this function is defined elsewhere) 
extern float def(float[R][C] x, int rows, int cols); 

void main(void) 
{ 
    // you can now call def, as long as it is defined 
    // in a single .c file included in this project 
} 

在实际项目中,您将创建一个矩阵模块,类似于头:

// matrix.h 

    // In an actual library, you would use dynamic 
    // allocation (since statically preallocating a large 
    // matrix is a waste of space)   
    struct Matrix 
    { 
     float **Cells; 
     int Rows; 
     int Cols; 
    }; 

    // allocation/freeing 
    Matrix Matrix_create(int numRows, int numCols); 
    void Matrix_free(Matrix m); 

    // actual operators 
    Matrix Matrix_add(Matrix a, Matrix b); 
    Matrix Matrix_mul(Matrix a, Matrix b); 

    // this is a good place for this declaration also 
    float Matrix_det(Matrix m); 

然后.c文件将提供实际的实现:

// matrix.c 

    // include whatever headers you need 
    #include "matrix.h" 
    #include <math.h> 

    // actual implementatinos 
    float Matrix_det(Matrix m) 
    { 
     // calculate the determinant 
    } 

然后你会包括matrix.h你需要的地方进行矩阵计算。

您只需将<stdio.h>包含在与用户交互的文件中(在您的案例中为main.c文件)。

+0

非常感谢您的帮助! 我正在努力通过它,因为我们说:) 我知道我是这样的初学者,但我确实花了至少2小时的研究,试验和错误,然后才诉诸问。非常感谢=) –

+0

首先,我以为我只需要两个文件。一个main.c和一个子(.h)用于每个子函数。 有一个main.c和一个matrices.c有点让我难以理解。我把哪一个放入#include 以及所有爵士乐? 其次是什么#ifndef _MATRICES_H_和#endif? 我们之前没有学过这样的东西。 最后,我在哪里把代码计算行列式,我需要返回它? 非常感谢:) 我们的导师不会说多少英语,并相信与否,但我是教我们班的大多数孩子的人:/ –

+0

@Thomas:我会更新答案和试着解释一下,但是你应该通过一个关于C基础知识的详细教程,因为这些问题是相当宽泛的。 – Groo