簡體   English   中英

如何從用戶(這是一個列表)獲取輸入並將值存儲在 C++ 中的數組中?

[英]How to take input from user ( which is a list ) and store values in array in c++?

測試用例 1:{1、2、3、4、5}

測試用例 2:{5, 8, 9}

有沒有比這更好的解決方案來將值存儲在 C++ 中的數組中?

注意:我們不知道編譯時要創建的數組的大小。

#include<iostream>
#include<sstream>
#include<vector>
using namespace std;

int main(){
  string s;
  cin.ignore();
  getline(cin,s);
  string t;
  stringstream x(s);
  vector<int>v;
  while(getline(x,t,' ')){
      if(t[0]!='{' && t[0]!='}'&& t[0]!=','){
           v.push_back(stoi(t));
        }
   }
 int size=v.size();
 int arr[size];
 for(int i=0;i<size;i++) arr[i]=v[i];
// for(int i=0;i<size;i++) cout<<arr[i]<<" ";
}

是的,可以采用未知數量的整數。 我們可以使用std::vector

我們可以為此編寫一個函數。 在這里,我們將拆分字符串並返回一個std::vector 在 C++ 中,我們可以利用 RVO,返回值優化。 您可以在此處閱讀有關復制省略和 RVO 的信息。 基本上它說,當按值從函數返回容器時,復制字節不會有問題。 現在它甚至是推薦的方法。

因此,您可以(並且應該)從函數返回一個std::vector 編譯器會注意它以優化的方式工作。

但首先,請看下面的例子:

#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <iterator>

std::vector<int> parseInts(std::string str) {

    // Put the string into a stream
    std::istringstream iss{ str };

    // Return the vector of ints 
    return { std::istream_iterator<int>(iss), {} };
}

int main() {
    // Test data
    std::string test{ "1 2 3 4 5 6 7 8 9 10" };

    // Get the vector with the ints
    std::vector ints = parseInts(test);

    // Show output
    for (const int i : ints) 
        std::cout << i << "\n";
    return 0;
}

我們有一個名為parseInts的函數, parseInts包含 2 行代碼。

首先,我們將字符串放入std::istringstream 這樣,就可以從新流中提取 int,例如

std::istringstream iss{ str };
int i1, i2;
iss >> i1 >> i2;

提取運算符 >> 將從流(字符串)中“提取”以空格分隔的整數值。

但是,如果我們看一下,我們會看到,那么我們需要知道字符串中的整數個數,然后重復寫“>>”。 為了對相同數量的項目重復執行操作,比如整數,我們在 C++ 中有迭代器。 使用迭代器,您可以迭代容器中的相似元素。 如果你假設一個字符串是一個容器,你當然可以迭代其中的整數。 有可用的迭代器可以為我們執行此操作。

在流的情況下,我們有std::istream_iterator 這個東西將迭代輸入流中某種類型的所有空格分隔項並返回值。

這個迭代器返回的許多值最好存儲在std::vector ,因為它是一個動態增長的容器。 非常適合我們,因為我們事先不知道流中的整數數量。

如果我們查看std::vector ,我們會發現它有一個所謂的范圍構造函數。 請參閱此處:范圍構造函數(編號 5)

使用范圍構造函數,我們定義了一個std::vector類型的變量,並用“begin”和“end”迭代器初始化它。 此范圍內的值將被放入向量中。

如果我們在示例中定義std::vector類型的變量,我們可以這樣寫:

std::vector<int> intv{ std::istream_iterator<int>(iss), std::istream_iterator<int>() };

或者

std::vector<int> intv( (std::istream_iterator<int>(iss)), std::istream_iterator<int>() );

請注意第一個參數的大括號。 這對於防止最棘手的解析問題是必要的。 你不想定義一個函數,而是一個變量。

但無論如何我們都不會使用它。 因為,使用統一初始化和 {} 初始化器作為默認初始化器,我們可以使用默認值作為第二個參數。 現在我們可以寫:

std::vector<int> intv(std::istream_iterator<int>(iss), {});

所以,接下來,我們可以使用 CTAD, 類模板參數推導 基本上,編譯器從構造函數中的參數知道它將構造的容器的數據類型。 所以,沒必要寫。

現在:

std::vector intv(std::istream_iterator<int>(iss), {});

這看起來已經很不錯了,您現在可以返回變量 intv。

但還有更多。 編譯器知道函數的類型以及它應該返回什么。 因此,您可以使用花括號初始化器並返回它,編譯器知道您想要返回std::vector<int>

所以最后的聲明是:

return { std::istream_iterator<int>(iss), {} };

我希望它有幫助。

很抱歉對一行代碼進行了冗長的描述。

所以,現在,為了閱讀更多的行,你可以寫:

int main() {

    // Her we will store the data
    std::vector<std::vector<int>> data{};

    // Read lines. Stop input with CRTL Z in an empty new line
    for (std::string line{}; std::getline(std::cin, line); ) {

        // Put the string into a stream
        std::istringstream iss{ line };

        // Split the values and add the values to the vector
        data.emplace_back(std::vector{ std::istream_iterator<int>(iss), {} });
    }

    // Show output
    for (const std::vector<int>& vi : data) {
        for (const int i : vi) std::cout << i << " ";
        std::cout << "\n";
    }
}

通過在結束后的空行中鍵入 CRTL Z 來停止輸入。

請嘗試輸入:

1 2 3 4
5 6 7 8
CTRL Z

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM