Может ли кто-нибудь помочь мне перевести этот код с ++ на с? - PullRequest
0 голосов
/ 29 января 2010

это генератор магических квадратов, но не знаю 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

@ Вездесущий

Могу ли я использовать что-то подобное?

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

Ответы [ 7 ]

3 голосов
/ 29 января 2010

Вы ограничены в создании проекта как проекта 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().

2 голосов
/ 29 января 2010

Для последней части вопроса, в 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 компилятора (-std = c99 в gcc):

int randominteger = 7;
int varname[randominteger];

Вы не можете иметь массивы с переменным числом элементов в C, поэтому вам придется прибегнуть к calloc или malloc и выполнить собственное управление памятью, например:

/* 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, достаточно большой, чтобы вместить ответ, чтобы вы могли уменьшить количество бит памяти, которыми вы должны управлять , Для этого я бы использовал вызов типа mat = calloc(order * order, sizeof(int)); в main, что также означает, что вам придется звонить free(mat), когда вы закончите с ним в конце main.

Я также предполагаю, что вы разворачиваете массив, чтобы у вас больше не было массива массивов. Это означает, что вам нужно будет выполнить некоторые математические операции, чтобы превратить строку, индекс столбца в линейный индекс в массиве. Что-то вроде row * order + column.

Вам придется повторить процедуру, которую я предложил для main в каждой из функций, которые создают магический квадрат, потому что каждая из них создает временные массивы для хранения вещей, которые уходят в конце функции.

2 голосов
/ 29 января 2010

Я просто отвечу на последнюю часть вопроса.

vector - это контейнер в стандартной библиотеке C ++.Это похоже на массив, который может автоматически изменять свой размер при заполнении.

A vector<vector<int> > - это vector, содержащий vector объектов, а последний содержит int.

Avector<vector<int> >& является ссылкой на то же самое.Ссылка похожа на указатель, за исключением того, что вы не используете * для доступа к фактическому содержимому.Таким образом, вы обрабатываете mat «как если бы» это был объект vector напрямую, за исключением того, что он действительно связан с другим экземпляром, поэтому любые изменения, которые вы вносите в него, будут «отражаться» и влияют на то, что видит вызывающая сторона.

Простой пример ссылок:

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

int main() {
    int num = 5;
    add1(num);
    // num is 6 here
}
0 голосов
/ 29 января 2010

Vector - это в значительной степени C ++ для массива. Существуют способы динамического изменения размеров векторов (без обращения к realloc ()), но в остальном это в значительной степени то, на что вы смотрите.

Если вы видите & в списке параметров, это означает «передать этот параметр по ссылке». В параметрах C внутри подпрограммы есть копия того, что было передано, так что если вы измените их, модификация не выйдет за пределы функции. Однако, если вы изменяете ссылочный параметр C ++, вы также изменяете переменную, используемую для этого параметра вызывающей стороной.

Таким образом, чтобы получить эквивалент <vector<vector<int>> & mat в C, вы, вероятно, передали бы этот параметр как что-то вроде int ** mat[], предполагая, что пользователь передает указатель на массив массивов int, которые вы хотите, чтобы вы работать на. Разница в том, что внутри подпрограммы ваш код C должен был бы делать *mat, чтобы получить массив массивов int, тогда как в коде C ++ они могут просто использовать mat напрямую.

0 голосов
/ 29 января 2010

Вы можете избавиться от строки #include и строки 'using namespace std'. Единственный сложный момент сейчас - твой вектор. Здесь передается двумерный массив целых чисел, который достаточно прост в Си. Сложным является изменение его размера, если вы не знаете границ с самого начала. Вот почему вектор так хорош - вам не нужно заботиться.

Для более общего преобразования C ++ в C я бы предложил вам взять книгу типа "C ++ для программистов C" и поработать с индексом. Более того, работайте от начала до конца и изучайте C ++. Вы, вероятно, обнаружите, что если программа каким-либо образом усложняется, будут некоторые вещи, которые довольно сложно сделать в C из C ++. Удачи !!

0 голосов
/ 29 января 2010

vector - это массив, размер которого изменяется автоматически. Так что vector<vector<int>> будет массивом int-массивов, эквивалентных C int*[]. &mat - это ссылка на mat , похожая на указатели (на самом деле я думаю, что C99 поддерживает ссылки). Однако в этом случае, поскольку передаваемое значение уже является указателем, оно на самом деле не нужно.

Таким образом, эквивалент в C будет

void BuildDoublyEvenMagicSquare(int*[] mat, int Order); 
0 голосов
/ 29 января 2010

Вектор C ++ подобен массиву C. Он добавляет некоторые полезные функции, такие как дополнительная проверка границ, автоматическое перераспределение, когда ему нужно увеличить размер, и т. Д.

Вектор примерно аналогичен целому [].

Вектор > похож на int * [], где каждое int * указывает на массив. Это не похоже на двумерный массив - каждый из внутренних векторов может иметь разные размеры.

Префикс переменной с & делает эту переменную ссылкой. Ссылка похожа на указатель, который вам не нужно явно разыменовывать. Передача параметров по ссылке - распространенная идиома C ++, которая используется во многих из тех же ситуаций, что и передача по указателю в C.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...