2010-01-29 76 views
0

这是一个神奇的方形发生器,但不知道C++,我有一些困难,把这段代码转换:有人可以帮我翻译这个C++代码到C吗?

#include <vector> 
#include <iostream> 
using namespace std; 
//There two series will be on even in case of magic square 
// One of even order will be for multiple of 4 
void BuildDoublyEvenMagicSquare(vector<vector<int> > &mat, int Order); 
//Other of even order will be for multiple of 2 
void SinglyEvenMagicSquare(vector<vector<int> > &mat, int order); 
// For odd order 
void BuildOddMagicSquare(vector<vector<int> > &mat, int Order); 

// For odd order 
void BuildOddMagicSquare(vector<vector<int> > &mat, int Order) 
{ 
    int SqrOfOrder = Order * Order; 
    int start=0, mid=Order/2;  // start position 
    for (int loop=1; loop<=SqrOfOrder; ++loop) 
    { 
    mat[start--][mid++] = loop; 
    if (loop % Order == 0) 
    { 
     start += 2; 
     --mid; 
    } 
    else 
    { 
     if (mid==Order) 
     mid -= Order; 
     else if (start<0) 
     start += Order; 
    } 
    } 
} 

void BuildDoublyEvenMagicSquare(vector<vector<int> > &mat, int Order) 
{ 
    vector<vector<int> > A(Order, vector<int> (Order, 0)); 
    vector<vector<int> > B(Order, vector<int> (Order, 0)); 
    int i, j; 
    //Building of matrixes I and J 
    int index=1; 
    for (i=0; i<Order; i++) 
    for (j=0; j<Order; j++) 
    { 
     A[i][j]=((i+1)%4)/2; 
     B[j][i]=((i+1)%4)/2; 
     mat[i][j]=index; 
     index++; 
    } 
    for (i=0; i<Order; i++) 
    for (j=0; j<Order; j++) 
    { 
     if (A[i][j]==B[i][j]) 
     mat[i][j]=Order*Order+1-mat[i][j]; 
    } 
} 

void BuildSinglyEvenMagicSquare(vector<vector<int> > &mat, int order) 
{ 
    int ho=order/2; 

    vector<vector<int> > C(ho, vector<int> (ho, 0)); 

    // For Order is Odd 
    if (order%2==1) 
     BuildOddMagicSquare(C, order); 

    // For Order is Even 
    else 
    { 
    //For Order is Doubly Even Order 
    if (order % 4==0) 
     BuildDoublyEvenMagicSquare(C, order); 
    //For Order is Singly Even Order 
    else 
     BuildSinglyEvenMagicSquare(C, order); 
    } 
    int i, j, k; 
    for (i=0; i<ho; i++) 
    for (j=0; j<ho; j++) 
    { 
     mat[i][j]=C[i][j]; 
     mat[i+ho][j]=C[i][j]+3*ho*ho; 
     mat[i][j+ho]=C[i][j]+2*ho*ho; 
     mat[i+ho][j+ho]=C[i][j]+ho*ho; 
    } 
    if (order==2) 
    return; 

    vector<int> A(ho, 0); 
    vector<int> B; 

    for (i=0; i<ho; i++) 
    A[i]=i+1; 

    k=(order-2)/4; 
    for (i=1; i<=k; i++) 
    B.push_back(i); 

    for (i=order-k+2; i<=order; i++) 
    B.push_back(i); 

    int temp; 
    for (i=1; i<=ho; i++) 
    for (j=1; j<=B.size(); j++) 
    { 
     temp=mat[i-1][B[j-1]-1]; 
     mat[i-1][B[j-1]-1]=mat[i+ho-1][B[j-1]-1]; 
     mat[i+ho-1][B[j-1]-1]=temp; 
    } 
    i=k; 
    j=0; 
    temp=mat[i][j]; mat[i][j]=mat[i+ho][j]; mat[i+ho][j]=temp; 
    j=i; 
    temp=mat[i+ho][j]; mat[i+ho][j]=mat[i][j]; mat[i][j]=temp; 
} 

int main() 
{ 
    int Order; 
    cout<<"Enter the order of square which you wanna: "; 
    cin>>Order; 
    vector<vector<int> > mat(Order, vector<int> (Order, 0)); 

    // For order less than 3 is meaningless so printing error 
    if (Order<3) 
    { 
    cout<<" Order Of Square must be greater than 2"; 
    return -1; 
    } 

    // For Order is Odd 
    if (Order%2==1) 
     BuildOddMagicSquare(mat, Order); 

    // For Order is Even 
    else 
    { 
    //For Order is Doubly Even Order 
    if (Order % 4==0) 
     BuildDoublyEvenMagicSquare(mat, Order); 
    //For Order is Singly Even Order 
    else 
     BuildSinglyEvenMagicSquare(mat, Order); 
    } 


    // Display Results 

    for (int i=0; i<Order; i++) 
    { 
    for (int j=0; j<Order; j++) 
    { 
     cout<< mat[i][j]<<" " ; 
    } 
    cout<<endl; 
    } 
    return 0; 
} 

例如,我该怎么用C调用这个函数?

void BuildDoublyEvenMagicSquare(vector<vector<int> > &mat, int Order); 

vector<vector<int> > &mat是什么意思?

@Omnifarious

我可以使用类似这样的东西吗?

int **mat: 
*mat = (int **)malloc(sizeof(int*)*Order); 
for (int i=0;i<Order;i++) 
mat[i] = (int *)malloc(sizeof(int)*Order); 
+5

你为什么要转换它? – Omnifarious 2010-01-29 15:18:43

+0

我不知道C++ ...我必须与我的程序的其他部分(数独xD) – user261908 2010-01-29 15:22:32

+0

@koal:你应该学习C++。正如Omnifarious的答案所指出的那样,某些部分不容易转换为C. – 2010-01-29 15:26:27

回答

2

有关问题的最后一部分,在C是函数原型应该是这样的,如果你按照我的建议的休息:

void BuildDoublyEvenMagicSquare(int *mat, int Order); 

实际上有几种方法可以做到这一点。这里有一些事情在C中无法完成,所以你必须采取一些稍微不同的方法。最重要的是C++向量。 C++ vector就像一个C数组,但它为您完成所有内存管理。这意味着,例如,在C中只需添加资源管理头痛的数组就可以很方便地获得数组。

的C++声明:

vector<int> varname(5); 

大致相当于C的声明:

int varname[5]; 

但在C++中,你可以这样做:

int randominteger = 7; 
vector<int> varname(randominteger); 

,并用C,这是非法,除非你有一个C99兼容的编译器(在gcc -std = c99):

int randominteger = 7; 
int varname[randominteger]; 

你不能在C元素的可变数量的阵列,所以你不得不求助于callocmalloc,做你自己的内存管理,像这样:

/* Not that this is not necessary and shouldn't be done (as it's * 
* prone to memory leaks) if you have a C99 compliant compiler. */ 

int randominteger = 7; 
int *varname = calloc(randominteger, sizeof(int)); 
if (varname == NULL) { 
    /* Die horribly of running out of memory. */ 
} 

在这种情况下,我假设你要将你的数组阵列展开成一个长的C数组,这个数组足够大以容纳答案,以便减少必须管理的内存位数。为了达到这个目的,我会在main中使用mat = calloc(order * order, sizeof(int));这样的电话,这也意味着在main结束时,您必须致电free(mat)。我还假设你正在展开数组,以便不再有数组的数组。这意味着你必须要做一些数学运算来将列索引转换为数组中的线性索引。类似于row * order + column

您将不得不重复我在main建议的每个函数中建立幻方的步骤,因为它们每个都创建临时数组来容纳在函数结束时消失的东西。

+0

我认为C99增加了对长度在运行时确定的数组的支持吗? – Bill 2010-01-29 17:58:14

+0

@Bill,你是对的!那会在那里节省很多头痛。我不知道OP有一个符合C99的编译器,但是如果他做... – Omnifarious 2010-01-29 18:06:40

+0

我主要是做C++,但是找到一个不符合早期采用的标准的编译器很常见2000? – Bill 2010-01-31 16:35:15

2

我只是回答问题的最后部分。

vector是C++标准库中的一个容器。它就像一个数组,可以在满足时自动调整其大小。

A vector<vector<int> >是一个vector包含vector对象,而后者拥有int

A vector<vector<int> >&是对其的引用。引用就像一个指针,除了你不使用*来访问实际的内容。因此,您直接将mat视为“好像”这是一个vector对象,只是它实际上是另一个实例的别名,所以您对它做出的任何更改都会“反射回来”并影响调用者可以看到的内容。引用的

简单的例子:

void add1(int& n) { 
    ++n; 
} 

int main() { 
    int num = 5; 
    add1(num); 
    // num is 6 here 
} 
0

A C++矢量是像C数组。它增加了一些很好的功能,如可选边界检查,当需要增加大小时自动重新分配等等。

A vector <int>大致类似于int []。

载体<矢量<INT> >是像一个int * [],其中每个INT *指向数组。它不像二维数组 - 每个内部矢量可以有不同的大小。

使用&前缀变量使该变量成为参考。引用就像一个指针,你不必明确解引用。通过引用传递参数是一种常见的C++习惯用法,在与通过C中的指针传递许多相同的情况下使用。

0

vector是一个自动调整大小的数组。所以vector<vector<int>>将是一个int数组数组,相当于C int*[]&mat是一个参考,类似于指针(实际上我认为C99支持引用)。然而,在这种情况下,由于传入的值已经是一个指针,所以并不是真的需要。

那么在C相当于将

void BuildDoublyEvenMagicSquare(int*[] mat, int Order); 
+0

在C++ 98中,你必须在'>>'之间写一个空格,否则会出现解析错误。在C++ 0x中,空间是可选的。 – 2010-01-29 15:25:00

0

你可以去除#includes和'using namespace std'这一行。现在唯一困难的是你的载体。这里传递的是一个二维数组,它在C中很容易。如果你一开始并不知道边界,那么困难的一点就是调整它的大小。这就是为什么矢量这么好 - 你不需要关心。

对于更通用的C++ to C转换,我建议你得到一本像“C++ for C程序员”这样的书,并从索引返回。更好的是,从头到尾学习C++。你可能会发现,如果程序复杂的话,C++中会有一些非常棘手的问题。祝你好运!!

0

向量几乎是一个C++的数组。有许多方法可以动态调整矢量大小(而不是诉诸于realloc()),但除此之外,这几乎就是你所看到的。

如果您在参数列表中看到&,则表示“通过参考传递此参数”。在例程中的C参数是传入内容的副本,所以如果修改它们,那么修改不会超出函数的范围。但是,如果您修改C++引用参数,那么您还正在修改调用程序用于该参数的变量。

所以要在C中获得相当于<vector<vector<int>> & mat的值,您可能会传递该参数,如int ** mat[],假设用户正在传递一个指向他们希望处理的int数组数组的指针。不同的是,在例程内部,你的C代码必须做一个*mat来获取int数组的数组,而在C++代码中,他们可以直接使用mat

3

您是否仅限于将项目构建为C项目?如果你正在编写好的C代码(并且它不是C99),你可以毫不费力地将它编译为C++。如果您可以将其构建为C++程序,则可以按原样使用该功能。

在这种情况下,您真正​​需要知道的是您已获得vector<vector<int> > mat,并且当您调用您的函数时,它会得到您的结果。然后,您可以将预处理器指令#include <vector>放入您的使用它的文件中,并按照using std::vector进行操作,所有内容都将正常工作。特别是,你可以用mat[i][j]读出的值,就像你用int阵列以及C.

阵列

有一点需要注意的是,你在后面写vector<vector<int> >而非vector<vector<int>>,因为>>会被视为右移运算符而不是角括号分隔符。这将在C++ 0x中出现,当它出现时(x数字现在严格为十六进制),并且可能在特定的编译器中被修复。

或者,编写一个包装函数,该函数接受向量并将其更改为一个数组int的数组。为方便起见,您可以使用mat.size()mat[i].size()查找矢量中的元素数量。

+0

包装函数的方法也可能工作,如果他一心想保留他的程序的其余部分在C. – Omnifarious 2010-01-29 15:46:47

+0

@Omnifarious:当然,编译他想要的功能和包装(将被声明为“extern”C“')成一个小静态库并链接它。这应该工作正常。 – 2010-01-29 16:09:12

相关问题