【问题标题】:Get data for 2-d array in a separate function?在单独的函数中获取二维数组的数据?
【发布时间】:2021-03-24 17:12:49
【问题描述】:

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

#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;
}

【问题讨论】:

  • 我将如何从 main 内部调用这个函数?
  • 你不能。 C++ 不提供 VLA(可变长度数组)。 int arr[m][n]; 是 2D VLA。在 C 中,您可以使用 VLA(但编译器支持从 C11 开始是可选的)。您应该使用std::vector&lt;std::vector&lt;int&gt;&gt; 输入未知数量的行和列。见std::vector
  • 请注意,g++ 确实允许在 C++ 中使用 VLA,但它绝对是对标准 C++ 的扩展。

标签: c++ arrays matrix multidimensional-array


【解决方案1】:

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

std::vector

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

std::vector<int>

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

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

(只是vector&lt;int&gt;的一个向量)

您的代码创建 m x n 数组

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

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

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

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

    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 作为参数传递给您的函数。如果用户按下 Ctrl + d(或 Windows 上的 Ctrl + z),只需进行最少的错误检查并手动处理 EOF,您可以这样做:

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,并且一次一行数据被收集在一个名为vtmp的临时vector&lt;int&gt;中。成功将 n 整数添加到 vtmp 后,临时向量将添加到带有 v.push_back(vtmp); 的向量中。

您的printArray() 功能

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

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 */
    }
}

在调用printArray() 之前返回main(),您将验证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);
}

注意:您需要查看Why is “using namespace std;” considered bad practice?

使用/输出示例

$ ./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

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

检查一下,如果您还有其他问题,请告诉我。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-11-18
    • 1970-01-01
    • 1970-01-01
    • 2012-04-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多