B2105 矩阵乘法

B2105 矩阵乘法

cpp 复制代码
#include <iostream>
using namespace std;
int main(){
  int n,m,k;
  cin>>n>>m>>k;
  int arr1[n][m];
  int arr2[m][k];
  for(auto & line:arr1){
    for(auto & x: line){
        cin>>x;
    }
  }
   for(auto & line:arr2){
    for(auto & x: line){
        cin>>x;
    }
  }
  int arr3[n][k] = {};
  for(int i =0;i<n;i++){
    for(int j = 0;j < k; j++){
      for(int l =0;l<m;l++){
      arr3[i][j]+=  arr1[i][l] * arr2[l][j];
      }  
    }
  }
  // for(int i =0;i<n;i++){
  //   for(auto j =0;j<k;j++){
  //     cout<<arr3[i][j]<<" ";
  //   }
  //    cout<<endl;
  // }
  for(auto & lin :arr3){
    for(auto & x :lin){
      cout<<x<<" ";
    }
    cout<<endl;
  }


}

在你当前的代码中,问题出在以下几个方面:

  1. **`arr3` 初始化为 `{0}`**:你使用了 `int arr3[n][k] = {0};`,这在一些编译器中可能会导致问题。直接这样初始化并不适用于所有编译器,因此你可以使用一个普通的循环来初始化数组。

  2. **输出的 `auto` 用法**:虽然你想简化输出使用 `for (auto & lin : arr3)`,但是当你使用了自定义大小的数组(如 `arr3[n][k]`),有时编译器无法正确推断类型,特别是编译器未能识别动态分配的多维数组。这里应使用传统的索引来进行输出。

  3. **矩阵乘法逻辑是正确的**,所以核心问题集中在输入输出部分。

修正后的代码:

```cpp

#include <iostream>

using namespace std;

int main() {

int n, m, k;

cin >> n >> m >> k;

// 定义矩阵

int arr1[n][m];

int arr2[m][k];

int arr3[n][k]; // 结果矩阵

// 输入第一个矩阵 arr1

for (int i = 0; i < n; i++) {

for (int j = 0; j < m; j++) {

cin >> arr1[i][j];

}

}

// 输入第二个矩阵 arr2

for (int i = 0; i < m; i++) {

for (int j = 0; j < k; j++) {

cin >> arr2[i][j];

}

}

// 初始化结果矩阵 arr3 为 0

for (int i = 0; i < n; i++) {

for (int j = 0; j < k; j++) {

arr3[i][j] = 0;

}

}

// 矩阵乘法

for (int i = 0; i < n; i++) {

for (int j = 0; j < k; j++) {

for (int l = 0; l < m; l++) {

arr3[i][j] += arr1[i][l] * arr2[l][j];

}

}

}

// 输出结果矩阵

for (int i = 0; i < n; i++) {

for (int j = 0; j < k; j++) {

cout << arr3[i][j] << " ";

}

cout << endl;

}

return 0;

}

```

解释:

  1. **矩阵输入部分**:使用标准的 `for` 循环输入矩阵 `arr1` 和 `arr2`,这里你之前的代码逻辑是对的,保持不变。

  2. **矩阵初始化**:将 `arr3` 初始化为 0。你之前使用了 `= {0}` 初始化可能导致问题,因此这里改用 `for` 循环手动将每个元素设置为 0。

  3. **矩阵乘法**:逻辑正确,使用三重循环来计算矩阵的乘法。

  4. **输出部分**:使用传统的 `for` 循环遍历并输出 `arr3`,避免使用 `auto` 来输出动态大小的二维数组,以确保兼容性。

输出部分的原因:

虽然 C++11 引入了 `auto` 来简化循环中的类型推断,但在涉及到动态大小的二维数组时,编译器有时可能无法推断类型,特别是在编译器的标准库实现不完全时。因此,使用传统的循环和显式索引是最兼容和清晰的方式。

示例输入:

```

2 3 2

1 2 3

4 5 6

7 8

9 10

11 12

```

输出:

```

58 64

139 154

在 C++ 中,使用 `int arr3[n][k] = {};` 初始化数组会将数组中的所有元素设置为 0。这是一种简便的初始化方式,可以用于静态大小的数组。

为什么 `int arr3[n][k] = {};` 可以将数组的所有元素初始化为 0?

  • 当你使用 `= {}` 初始化数组时,编译器会将数组的第一个元素初始化为 0,并且会自动将剩余的所有元素也初始化为 0。这是 C++ 标准中对于数组初始化的一个特点。

  • 实际上,`int arr3[n][k] = {};` 是一个更通用的初始化方式,效果和 `= {0}` 是一样的,它会初始化数组中的所有元素为 0。

重要限制:

  • **静态数组**:当数组大小是编译时常量时,比如 `int arr3[5][5] = {};`,这会被编译器正确地识别并将所有元素初始化为 0。

```cpp

int arr3[5][5] = {}; // 可以正确初始化,所有元素设为 0

```

  • **动态数组**:当数组大小由变量 `n` 和 `k` 决定时,比如 `int arr3[n][k] = {};`,它在部分编译器中可能不会工作。C++ 标准不支持动态大小的数组,因此这种初始化方式可能会在某些编译器中导致问题,特别是在使用动态内存管理的场合。

在 C++11 及更高版本中,标准数组需要大小是编译时常量。如果你想处理动态大小的数组,你可以使用标准库中的 `std::vector` 或动态内存分配。

对于动态数组,如何初始化?

如果你使用的是动态大小的数组(例如大小由输入决定),你需要手动初始化数组。可以通过以下方法来初始化二维数组:

  1. **使用 `std::vector`**:
  • `std::vector` 是一种动态数组,可以很好地处理动态大小的二维数组。

```cpp

int n = 3, k = 3;

vector<vector<int>> arr3(n, vector<int>(k, 0)); // 初始化为 0 的 n x k 矩阵

```

  1. **手动初始化动态大小的数组**:
  • 如果你坚持使用原始的 C++ 数组,可以使用 `for` 循环手动初始化:

```cpp

int n = 3, k = 3;

int arr3[n][k];

// 手动将所有元素初始化为 0

for (int i = 0; i < n; i++) {

for (int j = 0; j < k; j++) {

arr3[i][j] = 0;

}

}

```

总结:

  • `int arr3[n][k] = {};` 是可以初始化为 0 的一种方法,但它在动态数组情况下可能不会在所有编译器中工作。

  • 如果你使用动态大小的数组,最好使用 `std::vector` 或手动初始化数组的元素。

相关推荐
Lenyiin20 分钟前
3354. 使数组元素等于零
c++·算法·leetcode·周赛
爱打APEX的小李1 小时前
拷贝构造和赋值运算符重载
c++
霁月风1 小时前
设计模式——工厂方法模式
c++·设计模式·工厂方法模式
夜阳朔1 小时前
《C++ Primer》第三章知识点
c++·编程语言
sjyioo2 小时前
【C++】类和对象.1
c++
原装穿山乙思密达2 小时前
如何利用矩阵化简平面上的二次型曲线
线性代数·矩阵·高等代数·解析几何
煤泥做不到的!3 小时前
挑战一个月基本掌握C++(第六天)了解函数,数字,数组,字符串
开发语言·c++
智能与优化3 小时前
C++打造局域网聊天室第十一课: 程序关闭及线程的结束
开发语言·c++
小王爱吃月亮糖3 小时前
C++进阶-1-单继承、多继承、虚继承
开发语言·c++·笔记·学习·visual studio
Am心若依旧4094 小时前
[c++进阶(三)]单例模式及特殊类的设计
java·c++·单例模式