homer512 icon

CSV cpp

homer512 | PRO | 11/02/17 07:56:37 PM UTC | 0 ⭐ | 612 👁️ | Never ⏰ | []
C++ |

2.1 KB

|

None

|

0 👍

/

0 👎

#include <fstream>
#include <string>
#include <iostream>
 
 
namespace {
 
  void replace_col(const char* inpath, const char* outpath, const char* label,
                   const char* replacement)
  {
    std::ifstream infile(inpath);
    if(! infile.good())
      throw std::ios::failure("Cannot open input");
    infile.exceptions(std::ios::badbit);
    std::ofstream outfile(outpath);
    if(! outfile.good())
      throw std::ios::failure("Cannot create output");
    outfile.exceptions(std::ios::badbit | std::ios::failbit);
    std::string buf;
    if(! std::getline(infile, buf))
      return; // empty file
    // Handle header. Look for column index
    int replacecol = 0;
    bool found;
    // we stop when we haven't found a separator in the last iteration
    for(std::size_t offset = 0, cursep = 0; cursep != std::string::npos;
        ++replacecol, offset = cursep + 1) {
      cursep = buf.find(',', offset);
      if((found = ! buf.compare(offset, cursep - offset, label)))
        break;
    }
    if(! found)
      throw std::ios::failure("Column not found");
    outfile << buf << '\n'; // save header unchanged
    while(std::getline(infile, buf)) {
      std::size_t offset, cursep;
      int curcol;
      for(offset = 0, cursep = 0, curcol = 0; cursep != std::string::npos;
          ++curcol, offset = cursep + 1) {
        cursep = buf.find(',', offset);
        if(offset) // add separator to previous column
          outfile << ',';
        /*
         * one loop before the replacement and one after it would be more
         * efficient but let's keep it simple
         */
        if(curcol == replacecol)
          outfile << replacement;
        else
          outfile << buf.substr(offset, cursep - offset);
      }
      outfile << '\n';
    }
    // don't rely on dtor so that we can catch IO errors
    outfile.close();
  }
}
 
int main(int argc, char** argv)
{
  if(argc != 5) {
    std::cerr << "Usage: " << argv[0]
              << " INPUT.csv COLUMN REPLACEMENT OUTPUT.csv\n";
    return 1;
  }
  replace_col(argv[1], argv[4], argv[2], argv[3]);
}

Comments