C ++读取CSV文本文件作为整数向量

问题描述

我是一名初学者程序员,致力于解决C ++中的2019年代码问世挑战。

我整理的最后一个难题是实际上使程序读取input.txt文件,该文件本质上是一长串字符串,格式为'10,20,40,23“等。在一行上。

在上一个难题中,我使用了线条

int inputvalue;
std::ifstream file("input.txt");

while(file >> inputvalue){
    //
}

可以从文件中抓取行,但是它被格式化为文本文件,并且没有逗号分隔。

即:

10
20
40
23

我该怎么做才能使用逗号分隔来读取文件,特别是如何将这些值读取为整数而不是字符串或char并将其存储到向量中?

解决方法

您可以选择。我认为,最直接的方法是只读取一个字符串,然后转换为整数。您可以使用std::getline的附加“定界符”参数在遇到逗号时停止:

std::string value;
while (std::getline(file,value,',')) {
    int ival = std::stoi(value);
    std::cout << ival << std::endl;
}

一种常见的替代方法是读取单个字符,并期望它是逗号:

int ival;
while (file >> ival) {
    std::cout << ival << std::endl;

    // Skip comma (we hope)
    char we_sure_hope_this_is_a_comma;
    file >> we_sure_hope_this_is_a_comma;
}

如果也可能存在空格,则可能需要一种不太“希望”的技术来跳过逗号:

    // Skip characters up to (and including) next comma
    for (char c; file >> c && c != ',';);

或者简单地:

    // Skip characters up to (and including) next comma
    while (file && file.get() != ',');

或者确实,如果您期望仅 空格逗号,则可以执行以下操作:

    // Skip comma and any leading whitespace
    (file >> std::ws).get();

当然,以上所有方法都是这样做的笨拙方式:

    // Skip characters up to (and including) next comma on next read
    file.ignore(std::numeric_limits<std::streamsize>::max(),');

所有这些方法均假定输入为一行。如果您希望输入的行有逗号分隔的值,则还需要处理行末 而不会遇到逗号。否则,您可能会错过下一行的第一个输入。除了“有希望的”方法,该方法可以工作,但仅在技术上有效。

出于鲁棒性,我通常建议您使用std::getline将基于行的输入作为整个字符串读取,然后使用std::istringstream从该行中读取各个值。

,

虽然编写一个例程以从逗号分隔的文件中仅读取一行是很奇怪的,而不是编写一个通用例程以读取所有行(如果只想要一行,则只取第一行),这很奇怪–取出将多行读入std::vector<std::vector<int>>的部分,仅将一行读入std::vector<int> -尽管它只保存了几行代码。

一般方法是使用getline(file,line)读取整行文本,然后创建一个std::stringstream (line),然后可以使用>>读取每个整数,然后是{{ 1}}来读取分隔符。

除了要读取的文件外,您还可以使用第二个参数,因此可以将定界符作为第二个参数的第一个字符传递-这样,就没有理由重新编译代码来处理{ {1}}或getline (file,tmpstr,')或任何其他单个字符。

您可以将一小段代码放在一起,以执行以下操作:

';'

注意:将所有行读入向量vector所需的更改相对较少,更值得注意的是将','替换为#include <iostream> #include <fstream> #include <sstream> #include <string> #include <vector> int main (int argc,char **argv) { if (argc < 2) { /* validate at least 1 argument given */ std::cerr << "error: insufficient number of arguments.\n" "usage: " << argv[0] << " <filename>\n"; return 1; } std::vector<int> v {}; /* vector<int> */ std::string line {}; /* string to hold each line */ std::ifstream f (argv[1]); /* open file-stream with 1st argument */ const char delim = argc > 2 ? *argv[2] : ','; /* delim is 1st char in */ /* 2nd arg (default ',') */ if (!f.good()) { /* validate file open for reading */ std::cerr << "errro: file open failed '" << argv[1] << "'.\n"; return 1; } if (getline (f,line)) { /* read line of input into line */ int itmp; /* temporary integer to fill */ std::stringstream ss (line); /* create stringstream from line */ while (ss >> itmp) { /* read integer value from ss */ std::string stmp {}; /* temporary string to hold delim */ v.push_back(itmp); /* add to vector */ getline (ss,stmp,delim); /* read delimiter */ } } for (auto col : v) /* loop over each integer */ std::cout << " " << col; /* output col value */ std::cout << '\n'; /* tidy up with newline */ } ,然后填充一个临时向量,如果非空,则将其推回到向量集合中

示例输入文件

在名为if(getline...)的文件中,用逗号分隔的整数集,例如

while(getline..)

使用/输出示例

您使用的结果将是:

dat/int-1-10-1-line.txt

当然,您可以将输出格式更改为所需的格式。仔细研究一下,如果您还有其他问题,请告诉我。

,

这是另一个使用迭代器的紧凑型解决方案。

#include <iostream>
#include <vector>
#include <string>
#include <iterator>
#include <fstream>
#include <algorithm>


template <char D>
struct WordDelimiter : public std::string
{};

template <char D>
std::istream &
operator>>(std::istream & is,WordDelimiter<D> & output)
{
  // Output gets every comma-separated token
  std::getline(is,output,D);
  return is;
}

int main() {
  // Open a test file with comma-separated tokens
  std::ifstream f{"test.txt"};
  
  // every token is appended in the vector
  std::vector<std::string> vec{ std::istream_iterator<WordDelimiter<','>>{ f },std::istream_iterator<WordDelimiter<','>>{} };

  // Transform str vector to int vector
  // WARNING: no error checking made here
  std::vector<int> vecint;
  std::transform(std::begin(vec),std::end(vec),std::back_inserter(vecint),[](const auto& s) { return std::stoi(s); });

  for (auto val : vecint) {
    std::cout << val << std::endl;
  }

  return 0;
}

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...