首页 > 解决方案 > 在单独的函数中获取二维数组的数据?

问题描述

将数组作为函数参数传递时出错。我无法弄清楚如何在单独的函数中读取数组的元素,然后使用单独的函数打印它。这两个函数都有一个我无法纠正的错误。

#include <iostream>
using namespace std;

int m,n;

void getData(int (&arr)[m][n]){
for (int i=0;i<m;i++){
    cout<<"Enter elements of row "<<i+1<<endl;
    for (int j=0;j<n;j++){
        cin>>arr[i][j];
    }
}
}

void printArray(int arr[m][n]){
for (int i=0;i<m;i++){
    for (int j=0;j<n;j++){
        cout << arr[i][j]<<" ";
    }
    cout<<endl;
}
}

int main(){
cout << "Enter the number of rows of the array:\n";
cin >> m;
cout << "Enter the number of columns of the array:\n";
cin >> n;

int arr[m][n];

getData(arr);
printArray(arr);

return 0;
}

标签: c++arraysmatrixmultidimensional-array

解决方案


如果您仍然卡住,那么如评论中所述,您的代码最大的问题是使用可变长度数组。C++ 不提供 VLA,C 从 C99 开始提供,但从 C11 开始,编译器对它们的支持是可选的。简而言之,您不能在 C++ 中使用 VLA(非标准编译器扩展除外),对于 C 中的可移植代码,最好避免使用它们。

标准::向量

C++ 提供std::vector来创建一个包含未知数量的相似元素的容器。标题是<vector>. std::vector为您提供自动内存管理。有几种方法可以添加到向量中,一般的方法是使用.push_back()成员函数,在末尾简单地添加新元素。您声明一个简单的向量int为:

std::vector<int>

对于您的 2D 数组int,您只需使用向量的向量(很像 2D 数组只是一个或多个数组)。您将向量的向量声明int为:

std::vector<std:vector<int>>

(只是一个向量vector<int>

你的代码创建一个m x n数组

首先,您将从用户那里获得行数 ( m) 和列数 ( n):

int main (void) {
    
    int m = 0, n = 0;                               /* don't use global variables */

避免使用全局变量。在需要的范围内声明变量并作为参数传递给任何需要它们的函数。

对于所有用户输入,您必须验证每个输入。如果您从这个答案中没有得到任何其他信息,请了解您必须检查每个用户输入之后的返回(流状态)以确定输入是成功还是失败。在用户输入后盲目使用变量而不验证它是否包含有效输入将在输入失败后调用未定义行为。您可以将输入的行和列验证为:

    std::cout << "number of rows in array: ";
    if (!(std::cin >> m)) {                         /* validate EVERY input */
        std::cerr << "error: invalid integer input.\n";
        return 1;
    }
    std::cout << "number of cols in array: ";
    if (!(std::cin >> n)) {                         /* ditto */
        std::cerr << "error: invalid integer input.\n";
        return 1;
    }

如果main()用户未能为行或列提供有效的整数输入,程序将输出错误并返回EXIT_FAILURE( 1)。

您可以在开始时声明向量的向量,因为在声明时不需要指定元素的数量(您可以指定元素的数量以最小化在后台需要重新分配的次数),这里:

    // int arr[m][n];   /* VLAs are NOT part of C++, use std::vector<std::vector<int>> */
    std::vector<std::vector<int>> arr{};

你的getData()功能

由于您在 内接受输入getData(),因此它必须返回一个值,指示所有输入是成功还是失败。您可以使用该类型int并返回1/0(true/false) 或使用类型bool并返回 ( true/ false)。由于您要收集特定数量的行和特定数量的列,因此您必须将mn作为参数传递给您的函数。通过最少的错误检查,并EOF在用户按下Ctrl + d(或Ctrl + z在 Windows 上)时处理手册,您可以执行以下操作:

int getData (int m, int n, std::vector<std::vector<int>>& v)
{
    for (size_t i=0; i<(size_t)m; i++) {        /* loop m times filling temp vector */
        std::vector<int> vtmp{};                /* temp vector to fill */
        std::cout << "Enter elements of row[" << i+1 << "]: ";
        for (size_t j=0; j<(size_t)n;) {        /* loop n time adding n int to temp vect */
            int itmp;                           /* temp integer */
            if (std::cin >> itmp) {             /* you must VALIDATE EVERY USER-INPUT */
                vtmp.push_back(itmp);           /* on good input, add to temp vector */
                j++;                            /* increment loop var only on good input */
            }
            else {  /* handle error */
                if (std::cin.eof())             /* if manual EOF, user canceled */
                    return 0;                   /* return failue */
                /* otherwise display error, prompt for next input needed */
                std::cerr << "  error: invalid integer input.\n" <<
                            "arr[" << i << "][" << j << "]: ";
                std::cin.clear();               /* clear stream state */
                /* clear bad input to end-of-line */
                std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
            }
        }
        v.push_back(vtmp);      /* add temp vector to arr (vector of vectors) */
    }
    
    return 1;       /* return success */
}

请注意,上面的整数输入被读入一个临时整数变量itmp,并且一次将一行数据收集在一个vector<int>名为的临时变量中vtmp。成功将n整数添加到vtmp临时向量后,将添加到您的向量向量中v.push_back(vtmp);

你的printArray()功能

您的printArray()函数不需要mn作为参数传递,因为在您将数据添加到向量后,向量可以通过.size()成员函数报告它包含的元素数量。要输出模拟的二维数组,您可以使用基于范围的 for 循环,例如

void printArray (const std::vector<std::vector<int>>& v)
{
    for (const auto& r : v) {                   /* loop over rows */
        for (const auto& c : r)                 /* loop over cols */
            std::cout << std::setw(3) << c;     /* output col value */
        std::cout.put('\n');                    /* output newline */
    }
}

main()在打电话之前回到printArray()你将验证getData()成功,例如

    if (!getData (m, n, arr)) {                     /* validate getData succeeded */
        std::cerr << "error: getData() failued to fill arr.\n";
        return 1;
    }
    
    std::cout << "\nArray content:\n\n";            /* output array */
    printArray (arr);

总而言之,你可以这样做:

#include <iostream>
#include <iomanip>
#include <vector>
#include <limits>

int getData (int m, int n, std::vector<std::vector<int>>& v)
{
    for (size_t i=0; i<(size_t)m; i++) {        /* loop m times filling temp vector */
        std::vector<int> vtmp{};                /* temp vector to fill */
        std::cout << "Enter elements of row[" << i+1 << "]: ";
        for (size_t j=0; j<(size_t)n;) {        /* loop n time adding n int to temp vect */
            int itmp;                           /* temp integer */
            if (std::cin >> itmp) {             /* you must VALIDATE EVERY USER-INPUT */
                vtmp.push_back(itmp);           /* on good input, add to temp vector */
                j++;                            /* increment loop var only on good input */
            }
            else {  /* handle error */
                if (std::cin.eof())             /* if manual EOF, user canceled */
                    return 0;                   /* return failue */
                /* otherwise display error, prompt for next input needed */
                std::cerr << "  error: invalid integer input.\n" <<
                            "arr[" << i << "][" << j << "]: ";
                std::cin.clear();               /* clear stream state */
                /* clear bad input to end-of-line */
                std::cin.ignore (std::numeric_limits<std::streamsize>::max(), '\n');
            }
        }
        v.push_back(vtmp);      /* add temp vector to arr (vector of vectors) */
    }
    
    return 1;       /* return success */
}

void printArray (const std::vector<std::vector<int>>& v)
{
    for (const auto& r : v) {                   /* loop over rows */
        for (const auto& c : r)                 /* loop over cols */
            std::cout << std::setw(3) << c;     /* output col value */
        std::cout.put('\n');                    /* output newline */
    }
}

int main (void) {
    
    int m = 0, n = 0;                               /* don't use global variables */
    
    std::cout << "number of rows in array: ";
    if (!(std::cin >> m)) {                         /* validate EVERY input */
        std::cerr << "error: invalid integer input.\n";
        return 1;
    }
    std::cout << "number of cols in array: ";
    if (!(std::cin >> n)) {                         /* ditto */
        std::cerr << "error: invalid integer input.\n";
        return 1;
    }
    
    // int arr[m][n];   /* VLAs are NOT part of C++, use std::vector<std::vector<int>> */
    std::vector<std::vector<int>> arr{};
    
    if (!getData (m, n, arr)) {                     /* validate getData succeeded */
        std::cerr << "error: getData() failued to fill arr.\n";
        return 1;
    }
    
    std::cout << "\nArray content:\n\n";            /* output array */
    printArray (arr);
}

注意:您需要查看为什么“使用命名空间 std;”被认为是不好的做法?

示例使用/输出

$ ./bin/vla_input
number of rows in array: 3
number of cols in array: 3
Enter elements of row[1]: 1 2 3
Enter elements of row[2]: 4 5 6
Enter elements of row[3]: 7 8 9

Array content:

  1  2  3
  4  5  6
  7  8  9

故意输入错误:

$ ./bin/vla_input
number of rows in array: 3
number of cols in array: 3
Enter elements of row[1]: 1 2 3
Enter elements of row[2]: 4 bananas 6
  error: invalid integer input.
arr[1][1]: 5 6
Enter elements of row[3]: 7 8 9

Array content:

  1  2  3
  4  5  6
  7  8  9

有很多很多方法来构建输入例程。您可以让它提示并显示每个元素的提示,或者按照您的建议,并在上面完成,只需提示每行整数值。在这里,如果出错,用户会得到下一个所需元素的索引。

如果您还有其他问题,请仔细查看并告诉我。


推荐阅读