C 根据条件移动矩阵柱

C 根据条件移动矩阵柱,c,function,C,Function,我正在尝试用C编写一个函数,它将一个NxM矩阵作为输入,如果它找到空列,则根据用户的选择将非空列移动到矩阵的左侧或右侧。空列可以是1、2或更多 举个例子。假设以下矩阵: 矩阵元素为: 1 2 3 4 5 6 7 8 ------------------ 1| 1 6 0 0 0 1 0 8 2| 1 3 0 3 0 1 0 0 3| 3 0 0 0 0 8 0 0 4| 0 0 0 2 6 0 0 4 1 2 3 4 5 6 7 8 ------------------ 1| 1

我正在尝试用C编写一个函数,它将一个NxM矩阵作为输入,如果它找到空列,则根据用户的选择将非空列移动到矩阵的左侧或右侧。空列可以是1、2或更多

举个例子。假设以下矩阵:

矩阵元素为:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 0 1 0 8
2| 1 3 0 3 0 1 0 0
3| 3 0 0 0 0 8 0 0
4| 0 0 0 2 6 0 0 4
   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 1 8 0 0
2| 1 3 3 0 1 0 0 0
3| 3 0 0 0 8 0 0 0
4| 0 0 2 6 0 4 0 0
   1 2 3 4 5 6 7 8
------------------
1| 0 0 1 6 0 0 1 8 
2| 0 0 1 3 3 0 1 0 
3| 0 0 3 0 0 0 8 0 
4| 0 0 0 0 2 6 0 4 
如您所见,只有第3列和第7列完全为空(均为0)。我想要一个函数,如果用户选择l(左),它会将非空列移动到左边。因此,它将返回:

矩阵元素为:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 0 1 0 8
2| 1 3 0 3 0 1 0 0
3| 3 0 0 0 0 8 0 0
4| 0 0 0 2 6 0 0 4
   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 1 8 0 0
2| 1 3 3 0 1 0 0 0
3| 3 0 0 0 8 0 0 0
4| 0 0 2 6 0 4 0 0
   1 2 3 4 5 6 7 8
------------------
1| 0 0 1 6 0 0 1 8 
2| 0 0 1 3 3 0 1 0 
3| 0 0 3 0 0 0 8 0 
4| 0 0 0 0 2 6 0 4 
如果用户选择r(表示右侧),它将向右移动非空列。因此函数将返回:

矩阵元素为:

   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 0 1 0 8
2| 1 3 0 3 0 1 0 0
3| 3 0 0 0 0 8 0 0
4| 0 0 0 2 6 0 0 4
   1 2 3 4 5 6 7 8
------------------
1| 1 6 0 0 1 8 0 0
2| 1 3 3 0 1 0 0 0
3| 3 0 0 0 8 0 0 0
4| 0 0 2 6 0 4 0 0
   1 2 3 4 5 6 7 8
------------------
1| 0 0 1 6 0 0 1 8 
2| 0 0 1 3 3 0 1 0 
3| 0 0 3 0 0 0 8 0 
4| 0 0 0 0 2 6 0 4 
这是我的第一次演讲:

   void PushL(int (*arr), int rows, int cols){ //function to move columns to left 
    for(int i = 0; i < rows; i++)
        for(int j = 0;j < cols; j++){
                if(arr[i*cols+j] == 0)
                    for(int k = j + 1; k < cols; k++){
                        if(arr[i*cols+k] != 0){
                            arr[i*cols+j] = arr[i*cols+k];
                            arr[i*cols+k] = 0;
                            break;
                         }

                     }

           }
void PushL(int(*arr),int行,int列){//函数将列向左移动
对于(int i=0;i

}

这可能不是唯一的问题,但原始帖子中显示的两个代码段都缺少对假定意图至关重要的
{}
符号。(请参见此处的
//)

void PushR(int(*arr)、int行、int列){
对于(int i=行;i>0;i--)
对于(int j=cols;j>0;j--){
如果(arr[i*cols+j]==0)
对于(int k=j+1;k
(C中的缩进仅用于可读性,不控制执行流。)

为了使代码对将来维护它的人来说更具可读性,最好消除关于意图的所有歧义:(包括意图不明确的大括号)

void PushR(int(*arr)、int行、int列){
对于(inti=rows;i>0;i--){///添加到此处
对于(int j=cols;j>0;j--){
如果(arr[i*cols+j]==0){///加在这里
对于(int k=j+1;k<>代码> 关于丢失{}的程序不起作用,因为您只考虑单元格的值0或不依赖于同一列中的其他单元格。

在决定是否移动它之前,您需要知道所有列是否只包含0

为此:

int onlyZero(int (*arr), int col, int rows, int cols)
{
  const int sup = cols*rows;

  for (int i = 0; i != sup; i += cols) {
    if (arr[i + col] != 0)
      return 0;
  }

  return 1;
}
如果列col仅包含0,则返回1,否则返回0

要复制其他列中的列,请执行以下操作:

void copyColumn(int (*arr), int fromCol, int toCol, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + toCol] = arr[i + fromCol];
}
要重置列,请执行以下操作:

void resetColumn(int (*arr), int col, int rows, int cols)
{
  int sup = cols*rows;

  for (int i = 0; i != sup; i += cols)
    arr[i + col] = 0;
}
使用这些功能,即使这不是更快的方法:

void PushL(int (*arr), int rows, int cols)
{
  int receiver = 0;

  for (int col = 0; col != cols; ++col) {
    if (!onlyZero(arr, col, rows, cols)) {
      if (receiver != col)
        copyColumn(arr, col, receiver, rows, cols);
      receiver += 1;
    }
  }

  while (receiver != cols)
    resetColumn(arr, receiver++, rows, cols);
}
添加

void pr(int (*arr), int rows, int cols)
{
  for (int row = 0; row != rows; ++row) {
    for (int col = 0; col != cols; ++col) {
      printf("%d ", arr[row*cols + col]);
    }
    putchar('\n');
  }
  putchar('\n');
}

int main()
{
  int a[] = { 
    1, 6, 0, 0, 0, 1, 0, 8,
    1, 3, 0, 3, 0, 1, 0, 0,
    3, 0, 0, 0, 0, 8, 0, 0,
    0, 0, 0, 2, 6, 0, 0, 4
  };

  pr(a, 4, 8);
  PushL(a, 4, 8);
  pr(a, 4, 8);
}
汇编和执行:

pi@raspberrypi:/tmp $ gcc -pedantic -Wextra -Wall m.c
pi@raspberrypi:/tmp $ ./a.out
1 6 0 0 0 1 0 8 
1 3 0 3 0 1 0 0 
3 0 0 0 0 8 0 0 
0 0 0 2 6 0 0 4 

1 6 0 0 1 8 0 0 
1 3 3 0 1 0 0 0 
3 0 0 0 8 0 0 0 
0 0 2 6 0 4 0 0 
我让你做PushR,这和PushL非常接近

PushR是PushL的对称值:

void测试()
{
INTP[4][9]={
1 , 1, 6, 0, 0, 0, 1, 0, 8,
2 , 1, 3, 0, 3, 0, 1, 0, 0,
3 , 3, 0, 0, 0, 0, 8, 0, 0,
4 , 0, 0, 0, 2, 6, 0, 0, 4 };
int pp[4][9]={};
int-say=0;
对于(int i=0;i<9;i++)
{ 
bool ok=false;
对于(int j=0;j<4;j++)
{
如果(p[j][i]!=0)
ok=正确;
}
如果(确定)
{ 
对于(int j=0;j<4;j++)
pp[j][say]=p[j][i];
说++;
}
}
对于(int j=0;j<4;j++)
对于(int i=0;i<9;i++)
{
printf(“%d”,pp[j][i]);
如果(i==8)printf(“\n”);
}
}

你能改进这个问题吗。目前还不清楚问题是什么。当前代码(至少)缺少对问题的描述。你应该编辑问题并添加它。也就是说,在我看来,代码从不检查列是否完全为空……你错过了最里面的
if
后面语句的
{}
,因此只有第一个语句在
if
中,其他语句只是意图错误。“可能不是唯一的问题”呵呵,是的,这不是唯一的问题,在决定是否移动列之前,检查列的OP missed仅包含0或不包含0。在主题之外,emot是你的飞机?@bruno-图标是一个目标:)我最近卖了一个小塞斯纳,我现在没有飞机了!!!有没有办法将所有这些“连接”到一个函数?对于pushR,我在pushR中改变了从最后一列到第一列的顺序。错误在哪里void PushR(int(*arr),int rows,int cols){int receiver=0;for(int col=cols-1;col>0;--col){if(!onlyZero(arr,col,rows,cols)){if(receiver!=col)copyColumn(arr,col,receiver,rows,cols);receiver+=1;}while(receiver!=cols)resetColumn(arr,receiver++,rows,cols);}@Mike,正如你所看到的,工作函数是独立的,在PushL上只调用一次,所以是的,你可以将它们的主体直接放在PushL中,但是这样做会使代码变得不那么清晰,你必须在PushR中重复同样的操作,所以对我来说这样做是个坏主意。代码越清晰/易读越好。@Mike您的PushR中有两个错误,一个与接收器有关,另一个与限制有关