C++ 目瞪口呆地寻找一个可以工作的c&;c++;删除回车符的方法(读取.csv文件)

C++ 目瞪口呆地寻找一个可以工作的c&;c++;删除回车符的方法(读取.csv文件),c++,c,carriage-return,C++,C,Carriage Return,我通过以下方式读取.csv文件行: vector <string> vec_str; char line[40]; while (1) { memset (line, 0, 40 * sizeof (char)); if (fgets (line, 0, f_str_csv) == NULL) { break; } //and then making strings out of NL trimmed line, and storing

我通过以下方式读取.csv文件行:

vector <string> vec_str;
char line[40];
while (1) {
    memset (line, 0, 40 * sizeof (char));
    if (fgets (line, 0, f_str_csv) == NULL) {
        break;
    }
    //and then making strings out of NL trimmed line, and storing them in vec_str as
    vec_str.push_back (string (line, strlen (line)).substr (0, strlen (line) - 1));
}
给我一个输出:

[10]
[20]
[James K.
]
对于输入
10,20,James K.
,这是我从csv文件中读取的行

这里怎么了

编辑: 同样对于以后的文件,如果一个较小的名称出现在行的末尾,如
11,31,Wu S.
James K.
行之后,我会在
buffer
中得到剩余的
James K.
,这在第二次迭代后从结果中可以明显看出:

[11]
[31]
[Wu S.
K.
]

有人请告诉我如何避免这种回车错误行为。

以下是使用std::getline和std::ifstream的方法:

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

class line {
public:
  operator std::string() const {
    return data_;
  }

  friend std::ostream& operator<<(std::ostream& out, const line& self) {
    out << self.data_ << std::endl;
    return out;
  }

  friend std::istream& operator>>(std::istream& in, line& self) {
    std::getline(in, self.data_);
    return in;
  }

private:
  std::string data_;
};

class csv_part {
public:
  operator std::string() const {
    return data_;
  }

  friend std::ostream& operator<<(std::ostream& out, const csv_part& self) {
    out << self.data_;
    return out;
  }

  friend std::istream& operator>>(std::istream& in, csv_part& self) {
    std::getline(in, self.data_, ',');
    return in;
  }

private:
  std::string data_;
};

int main() {
  std::ifstream f_str_csv("myfile.csv");
  if(f_str_csv.is_open()) {
    std::vector<std::string> vec_str;
    // Read all lines from file
    std::copy(std::istream_iterator<line>(f_str_csv),
              std::istream_iterator<line>(),
              std::back_inserter(vec_str));
    // loop through all lines read
    for(std::vector<std::string>::const_iterator it = vec_str.begin();
        it != vec_str.end();
        ++it) {
      std::istringstream is(*it);
      // Print every part of the line (separated with a comma),
      // separated with a pipe symbol (|)
      std::copy(std::istream_iterator<csv_part>(is),
                std::istream_iterator<csv_part>(),
                std::ostream_iterator<csv_part>(std::cout, "|"));
      std::cout << std::endl;
    }
  } else {
    std::cerr << "Could not open input file" << std::endl;
  }
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
班级线{
公众:
运算符std::string()常量{
返回数据;
}

friend std::ostream&operator以下是使用和时的简单程度:

#include <string>
#include <vector>
#include <fstream>
#include <iostream>
#include <boost/algorithm/string.hpp>

int main(int argc, const char *argv[])
{
    std::fstream file;  
    file.open("input.txt"); 

    std::vector<std::vector<std::string>> lines;

    while (!file.eof()) { 

        std::string line; 

        // Read a line in the file to replace your C code. 
        std::getline(file, line); 

        std::vector<std::string> words; 

        // Split the words in the line - "\t ," defines the set of delimiters.
        boost::split(words, line, boost::is_any_of("\t ,"));

        lines.push_back(words); 
    }

    // Oputput each word, you can also replace the range based loops if you don't 
    // use C++11.  
    for (const auto& line : lines)
    {
        for (const auto& word : line)
        {
            std::cout << word << " "; 
        }
        std::cout << std::endl; 
    }

    file.close(); 

    return 0;
}
使用
g++-std=c++11 main.cpp-o main编译程序并执行它将导致:

11 31 James K. 
11 31 Wu S. 

CSV的某些行读取可能包含\r和/或\n使用C/文件的行尾:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

int main()
{
    FILE* f_str_csv = stdin;
    std::vector<std::string> vec_str;
    const unsigned Length = 4096;
    char line[Length];
    while (std::fgets(line, Length, f_str_csv) != NULL) {
        std::size_t n = std::strlen(line);
        if(n) {
            if(n + 1 == Length) {
                // Overflow
                throw std::overflow_error("Overflow");
            }
            switch(line[n-1]) {
                case '\n':
                case '\r':
                if(--n) {
                    switch(line[n-1]) {
                        case '\n':
                        case '\r':
                        --n;
                    }
                }
            }
            if(n) {
                char* ln = line;
                switch(ln[0]) {
                    case '\n':
                    case '\r':
                    ++ln;
                    --n;
                }
                if(n) {
                    vec_str.push_back (std::string (ln, ln + n));
                }
            }
        }
    }
    for(unsigned i = 0; i < vec_str.size(); ++i)
        std::cout << vec_str[i] << '\n';
}
#包括
#包括
#包括
#包括
#包括
#包括
int main()
{
文件*f_str_csv=stdin;
std::vec_str;
常量无符号长度=4096;
字符行[长度];
while(std::fgets(行、长度、f_str_csv)!=NULL){
std::size\u t n=std::strlen(行);
如果(n){
如果(n+1==长度){
//溢出
抛出std::溢出_错误(“溢出”);
}
开关(线路[n-1]){
案例“\n”:
案例'\r':
如果(--n){
开关(线路[n-1]){
案例“\n”:
案例'\r':
--n;
}
}
}
如果(n){
char*ln=行;
开关(ln[0]){
案例“\n”:
案例'\r':
++ln;
--n;
}
如果(n){
向量str.push_back(std::string(ln,ln+n));
}
}
}
}
for(无符号i=0;istd::cout由于您已经在使用std::vector和std::string(都是C++),请看我读取的csv文件读取filestream
FILE*f_csv;
?也就是说,因为
istream
应该是
iostream
的一个子类,而
ifstream
是我正在使用的。为什么你不能使用std::ifstream?顺便说一句,我不确定boost是否是我唯一可以使用的方法。感谢面向boost的解决方案,@t奥米斯拉夫·马里奇
11 31 James K. 
11 31 Wu S. 
#include <cstdio>
#include <cstring>
#include <iostream>
#include <stdexcept>
#include <string>
#include <vector>

int main()
{
    FILE* f_str_csv = stdin;
    std::vector<std::string> vec_str;
    const unsigned Length = 4096;
    char line[Length];
    while (std::fgets(line, Length, f_str_csv) != NULL) {
        std::size_t n = std::strlen(line);
        if(n) {
            if(n + 1 == Length) {
                // Overflow
                throw std::overflow_error("Overflow");
            }
            switch(line[n-1]) {
                case '\n':
                case '\r':
                if(--n) {
                    switch(line[n-1]) {
                        case '\n':
                        case '\r':
                        --n;
                    }
                }
            }
            if(n) {
                char* ln = line;
                switch(ln[0]) {
                    case '\n':
                    case '\r':
                    ++ln;
                    --n;
                }
                if(n) {
                    vec_str.push_back (std::string (ln, ln + n));
                }
            }
        }
    }
    for(unsigned i = 0; i < vec_str.size(); ++i)
        std::cout << vec_str[i] << '\n';
}