#c #multidimensional-array #printf #pointer-arithmetic #function-definition
#c #многомерный массив #printf #указатель-арифметика #функция-определение
Вопрос:
Я написал следующую функцию:
void negate_row(const int n, const int r, int *a)
{
if (r == 0)
{
printf("Matrix with negated row: ");
printf("n");
for (int y = 0; y < 3; y )
{
*(a 3 * r y) = *(a 3 * r y) *(-1);
printf("%d ", *(a 3 * r y));
}
printf("n");
for (int y = 0; y < 3; y )
{
*(a 3 * r y) = *(a 3 * r y) *(-1);
printf("%d ", *(a 3 * (r 1) y));
}
printf("n");
for (int y = 0; y < 3; y )
{
*(a 3 * r y) = *(a 3 * r y) *(-1);
printf("%d ", *(a 3 * (r 2) y));
}
printf("n");
}
Итак, в основном, что здесь происходит, так это то, что моя функция принимает матрицу n X 3 и отрицает определенную строку, используя арифметику указателей. Я смог добиться этого, я также смог выяснить, как напечатать ту же самую матрицу с отрицаемой строкой. Просто то, как я это делаю, совсем неэффективно. Мне пришлось бы написать оператор if для каждой строки, например, если r == 0,1,2,3,4 и т.д. … есть ли какой-нибудь способ сделать это более эффективно?
Некоторые пояснения: const int n
определяет размер матрицы (n x 3), const int r
решает, какая строка отрицается ( 0
<= r
< n
).
Ответ №1:
Второй цикл поможет. Обычно я нахожу код указателя немного сложнее для чтения. В частности, при работе с матрицей вам может быть лучше использовать синтаксис массива вместо синтаксиса указателя.
for (int y = 0; y < 3; y )
{
for (int x = 0; x < 3; x )
{
printf("%d ", *(a 3 * (r x) y));
}
printf("n");
}
Комментарии:
1. у него есть
n
столбцы, так что этоx < n
2.
x
Цикл должен быть внешним циклом.3. ДА. Вы, ребята, правы. Я просто обращаюсь к вопросу о том, как уменьшить дублирующийся код в его одном цикле. Похоже, в этом и заключается вопрос.
4. Спасибо за этот ответ, и он действительно работает. Но есть проблема, с которой я столкнулся, и почему я сделал то решение, которое я сделал. В зависимости от того, какая строка вводится для отрицания, эта строка будет напечатана как первая строка матрицы. Теперь так и должно быть, выбранная строка должна оставаться в исходном месте. Например, если выбрана строка 2, она не должна становиться строкой 0, она должна оставаться на своем месте в строке 2.
Ответ №2:
Частный случай (3 строки):
int mul = 1, y = 0;
for (int x = 0; x < n; x ) {
mul = x == r ? -1 : 1;
y = (a 3 * x);
printf("%d ", (*y) * mul);
printf("%d ", (*y 1) * mul);
printf("%d ", (*y 2) * mul);
printf("n");
}
Более общий ( m
строки):
int mul = 1;
for (int x = 0; x < n; x ) {
mul = x == r ? -1 : 1;
for (int y = 0; y < m; y ) {
printf("%d ", ((*(a m * x y)) * mul);
}
printf("n");
}
Примечание: В новых компиляторах также нет разницы в скорости между синтаксисом массива или указателя.
Ответ №3:
Вы могли бы написать функцию, которая принимает одномерный массив (строку вашей матрицы), а затем, используя эту функцию, вы могли бы в цикле выводить все ее строки или выводить выбранную строку.
Вот демонстрационная программа.
#include <stdio.h>
void negate_row( const int *a, size_t n, int width )
{
if ( width < 1 ) width = 1;
for ( const int *p = a; p != a n; p )
{
printf( "%*d ", width, -*p );
}
putchar( 'n' );
}
int main(void)
{
enum { M = 3, N = 4 };
int matrix[M][N] =
{
{ 0, 1, 2, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
for ( int ( *p )[N] = matrix; p != matrix M; p )
{
negate_row( *p, N, 3 );
}
return 0;
}
Вывод программы
0 -1 -2 -4
-5 -6 -7 -8
-9 -10 -11 -12
Поскольку вы показали код, в котором вы используете указатели для вывода элементов массива, то в этой демонстрационной программе я также использую указатели везде для доступа к элементам массива.
Третий параметр функции задает ширину поля для выводимого значения.
Для вывода матрицы в обратном порядке строк вы можете использовать цикл, показанный в программе blow.
#include <stdio.h>
void negate_row( const int *a, size_t n, int width )
{
if ( width < 1 ) width = 1;
for ( const int *p = a; p != a n; p )
{
printf( "%*d ", width, -*p );
}
putchar( 'n' );
}
int main(void)
{
enum { M = 3, N = 4 };
int matrix[M][N] =
{
{ 0, 1, 2, 4 },
{ 5, 6, 7, 8 },
{ 9, 10, 11, 12 }
};
for ( int ( *p )[N] = matrix M; p != matrix; )
{
negate_row( *--p, N, 3 );
}
return 0;
}
Вывод программы
-9 -10 -11 -12
-5 -6 -7 -8
0 -1 -2 -4
Ответ №4:
Вы можете легко обобщить функцию: пока строка находится внутри матрицы, ваш код работает для любой строки. Также обратите внимание, что для печати матрицы лучше использовать отдельную функцию.
#include <stdio.h>
void negate_row(const int n, const int r, int *a) {
if (r >= 0 amp;amp; r < n) {
// negate row r
for (int col = 0; col < 3; col ) {
*(a 3 * r col) *= -1;
}
}
}
void print_matrix(const int n, int *a, const char *title) {
if (title) {
printf("%s:n", title);
}
for (int row = 0; row < n; row ) {
for (int col = 0; col < 3; col ) {
printf("%d ", *(a 3 * row col));
}
printf("n");
}
printf("n");
}
int main() {
int matrix[5 * 3] = {
0, 1, 2,
3, 4, 5,
6, 7, 8,
9, 10, 11,
12, 13, 14,
};
print_matrix(5, matrix, "Matrix");
negate_row(5, 0, matrix);
print_matrix(5, matrix, "Matrix with negated row");
negate_row(5, 3, matrix);
print_matrix(5, matrix, "Matrix with two negated rows");
negate_row(5, 0, matrix);
negate_row(5, 3, matrix);
print_matrix(5, matrix, "Matrix back to origin");
return 0;
}
Вывод:
Матрица: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 Матрица с отрицаемой строкой: 0 -1 -2 3 4 5 6 7 8 9 10 11 12 13 14 Матрица с двумя отрицаемыми строками: 0 -1 -2 3 4 5 6 7 8 -9 -10 -11 12 13 14 Матрица обратно в исходное положение: 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14