如何从 C 中的二维数组中删除一行?

How to delete a row from a 2D array in C?

如何从矩阵中删除特定行,并保持相同的顺序? 示例:

1 1 1
2 2 2
3 3 3

假设我需要删除包含所有偶数元素的行,因此删除后它应该如下所示:

1 1 1
3 3 3

我尝试自己编写代码,(条件与我上面提到的不一样!)但实际上并不能正常工作:

for (i = 0 ; i < no_of_rows ; i++) { 
    if (abs(prosjeci[i] - prosjek) < 0.1) { /* condition */
        for (k = i ; k < no_of_rows - 1 ; k++) {
            for (j = 0 ; j < no_of_columns ; j++) {
                matrica[k][j] = matrica[k+1][j];
            }
        }
       i--;
       no_of_rows--;
    }
}

我没有发现您的代码有任何问题。

在评论中,有人要你post一个"Minimal, Complete, and Verifiable example"。这是什么意思。我充实了你的程序,添加了 matrica 数组和其他变量的声明和初始化,更改条件以匹配你的示例,并在最后打印出数组。我最终得到了这个:

#include <stdio.h>

int matrica[][3] = {
    {1, 1, 1},
    {2, 2, 2},
    {3, 3, 3}
};

int no_of_columns = 3;
int no_of_rows = 3;

int main()
{
    int i, j, k;

    for (i = 0 ; i < no_of_rows ; i++) { 
        if (matrica[i][0] % 2 == 0) { /* even row */
            for (k = i ; k < no_of_rows - 1 ; k++) {
                for (j = 0 ; j < no_of_columns ; j++) {
                    matrica[k][j] = matrica[k+1][j];
                }
            }
           i--;
           no_of_rows--;
        }
    }

    for (i = 0 ; i < no_of_rows ; i++) { 
        for (j = 0 ; j < no_of_columns ; j++) {
            printf("%d ", matrica[i][j]);
        }
        printf("\n");
    }
}

因此,如果您首先 post 编辑了类似的内容,那就更好了。

但是当我编译并 运行 这个程序时,它工作得很好。 (我并不感到惊讶——正如我所说,我没有发现任何问题。)

因此,无论您的问题是什么,都是您没有向我们展示过的东西。你说 "it doesn't actually work properly" 是什么意思?您期望看到什么,而您看到的是什么?

[P.S。你的问题还有一个问题。在你问得更好之前,我什至不应该回答它。我的这个回答实际上被否决了,以提醒我这个事实。我没有抱怨;我预料到了。但是,下次请问一个更完整、更容易回答的问题。]

我试着按照你的意思去做..

main(){
    int matrica[3][3] = { { 1,2,3 },
                          { 4,4,4 },
                          { 7,8,9 } };
    double no_of_rows = 3;
    int line_removed = 0;
    for (int i = 0; i < no_of_rows; i++) {
        double sum = 0;
        for (int j = 0; j < no_of_rows; j++)
        {
            sum = sum + matrica[i][j];
        }
        for (int j = 0; j < no_of_rows; j++)
        {
            int checker = 0.1 + (sum / no_of_rows);
            if ( checker > matrica[i][j] || checker < matrica[i][j])
            {
                break;
            }
            if (j = (no_of_rows-1))
            {
                for ( int k = i ; k < no_of_rows; k++)
                {
                    for ( j = 0; j < no_of_rows; j++)
                    {
                        matrica[k][j] = matrica[k + 1][j];
                    }
                }
                line_removed++;
            }
        }
    }

    for (int i = 0; i < (no_of_rows-line_removed); i++)
    {
        for (int j = 0; j < no_of_rows; j++)
        {
            printf("%d ", matrica[i][j]);
        }
        printf("\n");
    }
    printf("\n");
    return 0;
}

您的方法不起作用,因为您就地修改了矩阵,相应地更新了 i 索引和行数 no_of_rows,但未能更新单独的数组 prosjeci .每当一行与过滤器匹配时,矩阵中的所有后续行都会被删除。

您可以通过为矩阵和过滤器数组使用单独的索引来解决此问题:

int ii;  // index into the prosjeci array.

for (i = ii = 0; i < no_of_rows ; i++, ii++) { 
    if (abs(prosjeci[ii] - prosjek) < 0.1) { /* condition */
        for (k = i; k < no_of_rows - 1; k++) {
            for (j = 0; j < no_of_columns; j++) {
                matrica[k][j] = matrica[k+1][j];
            }
        }
        i--;
        no_of_rows--;
    }
}

或者,如果您可以更新过滤数组,您可以这样做:

for (i = 0; i < no_of_rows ; i++) { 
    if (abs(prosjeci[i] - prosjek) < 0.1) { /* condition */
        for (k = i; k < no_of_rows - 1; k++) {
            for (j = 0; j < no_of_columns; j++) {
                matrica[k][j] = matrica[k+1][j];
            }
            prosjeci[k] = prosjeci[k+1];
        }
        i--;
        no_of_rows--;
    }
}

首先,实际上您不能在不创建数组的新副本的情况下从数组中删除元素。你只能用一些其他的值覆盖它们,并保留数组中实际使用的元素的数量。

这是一个演示程序,展示了它是如何完成的。名称为n的变量用于保存数组中实际使用的元素行数。

#include <stdio.h>

#define N   10

int all_of_even( const int *row, size_t n ) 
{ 
    size_t i = 0;

    while ( i < n && row[i] % 2 == 0 ) i++;

    return i == n;
}   

int main(void) 
{
    int a[][N] =
    {
        { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
        { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 },
        { 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 },
        { 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
        { 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
        { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5 },
        { 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
        { 7, 7, 7, 7, 7, 7, 7, 7, 7, 7 },
        { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 },
        { 9, 9, 9, 9, 9, 9, 9, 9, 9, 9 }
    };

    const size_t M = sizeof( a ) / sizeof( * a );

    size_t n = M;

    for ( size_t i = 0; i < n; i++ )
    {
        for ( size_t j = 0; j < N; j++ ) printf( "%d ", a[i][j] );
        printf( "\n" );
    }
    printf( "\n" );

    n = 0;

    for ( size_t i = 0; i < M; i++ )
    {
        if ( !all_of_even( a[i], N ) )
        {
            if ( n != i )
            {
                for ( size_t j = 0; j < N; j++ ) a[n][j] = a[i][j];
            }               
            ++n;
        }
    }

    for ( size_t i = 0; i < n; i++ )
    {
        for ( size_t j = 0; j < N; j++ ) printf( "%d ", a[i][j] );
        printf( "\n" );
    }
    printf( "\n" );
    return 0;
}

程序输出为

0 0 0 0 0 0 0 0 0 0 
1 1 1 1 1 1 1 1 1 1 
2 2 2 2 2 2 2 2 2 2 
3 3 3 3 3 3 3 3 3 3 
4 4 4 4 4 4 4 4 4 4 
5 5 5 5 5 5 5 5 5 5 
6 6 6 6 6 6 6 6 6 6 
7 7 7 7 7 7 7 7 7 7 
8 8 8 8 8 8 8 8 8 8 
9 9 9 9 9 9 9 9 9 9 

1 1 1 1 1 1 1 1 1 1 
3 3 3 3 3 3 3 3 3 3 
5 5 5 5 5 5 5 5 5 5 
7 7 7 7 7 7 7 7 7 7 
9 9 9 9 9 9 9 9 9 9 

至于你的方法,那么它是低效的,因为对于检查条件的每次迭代,你都会在给定行之后复制数组的所有行,而不是只复制一行。

同时更改 for 循环主体和 for 语句本身的控制变量也是一种不好的做法。这使得代码难以阅读。