2017-04-03 62 views
0

我试图实现两个2×2矩阵的strassens算法,以便制作一个递归矩阵乘法算法,但是实现不编译给我这样的错误:在范围中定义的函数,但编译器抱怨它超出范围

“STRASSEN在此范围内未声明” 和 “不合格-ID”

下面的代码:

#include <iostream> 
#include <cstdlib> 

using namespace std; 

int[][] strassen(int A[][2], int B[][2]) 
{ 
    int s1 = B[0][1] - B[1][1]; 
    int s2 = A[0][0] + A[0][1]; 
    int s3 = A[1][0] + A[1][1]; 
    int s4 = B[1][0] - B[0][0]; 
    int s5 = A[0][0] + A[1][1]; 
    int s6 = B[0][0] + B[1][1]; 
    int s7 = A[0][1] - A[1][1]; 
    int s8 = B[1][0] + B[1][1]; 
    int s9 = A[0][0] - A[1][0]; 
    int s10 = B[0][0] + B[0][1]; 

    int p1 = A[0][0] * s1; 
    int p2 = s2 * B[1][1]; 
    int p3 = s3 * B[0][0]; 
    int p4 = A[1][1] * s4; 
    int p5 = s5 * s6; 
    int p6 = s7 * s8; 
    int p7 = s9 * s10; 

int C[2][2]; 

C[0][0] = p5 + p4 - p2 + p6; 
C[0][1] = p1 + p2; 
C[1][0] = p3 + p4; 
C[1][1] = p5 + p1 - p3 - p7; 

return C[][]; 
} 

int main() 
{ 
    int A[2][2] = {{1,3},{7,5}}; 
    int B[2][2] = {{6,8},{4,2}}; 
    int C[][2] = strassen(A,B); 
    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl; 
    return 0; 
} 

你能告诉我为什么我得到编译时错误。 我还需要知道如何为一个二维数组创建空间,因为当我的当前实现C将在函数退出返回垃圾值时立即超出范围。

+2

你应该*总是*发布你的编译器/链接器错误*逐字*。 –

+3

“return C [] [];” - 你打算通过这个获得什么? –

+3

忘记'malloc'的东西!不要在C++中使用它! – datell

回答

0

有几个原因让你的代码无法编译: 由于函数strassen没有编译,而且它没有编译,因为你正在返回一个在内部声明的数组功能。

一个好的经验法则是永远不会返回数组,也不会将它们作为参数传递,而是使用引用,它可以节省内存和时间。

继承人是不使用动态内存(虽然我认为这将是比较容易做到这样)

#include <iostream> 

using namespace std; 

void strassen(int (&A)[2][2], int (&B)[2][2], int (&C)[2][2]) 
{ 
    int s1 = B[0][1] - B[1][1]; 
    int s2 = A[0][0] + A[0][1]; 
    int s3 = A[1][0] + A[1][1]; 
    int s4 = B[1][0] - B[0][0]; 
    int s5 = A[0][0] + A[1][1]; 
    int s6 = B[0][0] + B[1][1]; 
    int s7 = A[0][1] - A[1][1]; 
    int s8 = B[1][0] + B[1][1]; 
    int s9 = A[0][0] - A[1][0]; 
    int s10 = B[0][0] + B[0][1]; 

    int p1 = A[0][0] * s1; 
    int p2 = s2 * B[1][1]; 
    int p3 = s3 * B[0][0]; 
    int p4 = A[1][1] * s4; 
    int p5 = s5 * s6; 
    int p6 = s7 * s8; 
    int p7 = s9 * s10; 

    C[0][0] = p5 + p4 - p2 + p6; 
    C[0][1] = p1 + p2; 
    C[1][0] = p3 + p4; 
    C[1][1] = p5 + p1 - p3 - p7; 

} 

int main() 
{ 
    int A[2][2] = {{1,3},{7,5}}; 
    int B[2][2] = {{6,8},{4,2}}; 
    int C[2][2]; 

    strassen(A,B,C); 

    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl; 

    return 0; 
} 

注意要传递C作为参考功能,所以变化的解决方案,你功能里面也会影响它的功能

+0

当我们将整数传递给一个函数但在声明中使用“&”时,这意味着什么。像你一样,传递给A,B,C是参数,但是当你定义了你使用的函数(&A),(&B),(&C)。他们为什么在括号里。 – zaidjan1295

+0

该符号意味着您没有复制参数,而是向它们发送引用,函数中的变量将引用与您作为参数传递的变量完全相同的内存空间。它们在括号中以指定您不是发送引用数组,而是引用数组。 – Sacha

+0

如果您是发送参考资料(即地址),为什么当您完成所有相应的数学运算后,您是否解除A,B,C的引用? – zaidjan1295

0

正如许多评论中提到的,你的解决方案是典型的C风格这可能会产生很多问题(特别是当你是初学者时)。 C++为C语言变得复杂的许多情况提供了强大的内存保存和易于使用的解决方法。

不要误解我的意思:C是一门很棒的语言,但是当您决定使用C++时,请使用它!

对于您的情况,std::array是完美的,因为您使用明确定义大小的数组。它的工作原理是这样的:用std::array<type,size>来定义其内容的大小和类型。

下面的代码实现使用std::array您尝试:

#include <iostream> 
// #include <cstdlib> // use C libraries only when really needed 
#include <array> 

using namespace std; 

array<array<int,2>,2> strassen(array<array<int,2>,2> A, array<array<int,2>,2> B){ 
    int s1 = B[0][1] - B[1][1]; 
    int s2 = A[0][0] + A[0][1]; 
    int s3 = A[1][0] + A[1][1]; 
    int s4 = B[1][0] - B[0][0]; 
    int s5 = A[0][0] + A[1][1]; 
    int s6 = B[0][0] + B[1][1]; 
    int s7 = A[0][1] - A[1][1]; 
    int s8 = B[1][0] + B[1][1]; 
    int s9 = A[0][0] - A[1][0]; 
    int s10 = B[0][0] + B[0][1]; 

    int p1 = A[0][0] * s1; 
    int p2 = s2 * B[1][1]; 
    int p3 = s3 * B[0][0]; 
    int p4 = A[1][1] * s4; 
    int p5 = s5 * s6; 
    int p6 = s7 * s8; 
    int p7 = s9 * s10; 

    array<array<int,2>,2> C; 

    C[0][0] = p5 + p4 - p2 + p6; 
    C[0][1] = p1 + p2; 
    C[1][0] = p3 + p4; 
    C[1][1] = p5 + p1 - p3 - p7; 

    return C; 
} 

int main(){ 
    array<array<int,2>,2> A {{{{1,3}},{{7,5}}}}; 
    array<array<int,2>,2> B {{{{6,8}},{{4,2}}}}; 
    array<array<int,2>,2> C = strassen(A,B); 
    cout<<C[0][0]<<endl<<C[0][1]<<endl<<C[1][0]<<endl<<C[1][1]<<endl; 
} 

当你使用C风格的数组一样,二维arrrays因此std::array<std::array<T,size>,size>>实现为数组的数组。

对于在初始化AB时看起来奇怪的大括号,请参阅Why can't simple initialize (with braces) 2D std::array? [duplicate]的顶部答案。

请注意,我初始化main()中的数组的方式需要-std=c++11编译器标志。编译类似gcc -std=c++11 -o strassen strassen.c