0

我有一个包含多行数据的 csv 文件。我的函数将 lineNum 作为参数传递。因此,当用户输入 4 作为 lineNum 时,我想读取 csv 文件中的第 4 行。我认为解决此问题的一个好方法是查找 \n 并计算它们,当计数为 lineNum-1 时停止,然后继续阅读下一行。我认为这是一种不错的方法,但是我对实现完全感到困惑。希望得到一些帮助这是我的代码

void ReadCsv( int lineNum){
    ifstream inFile ("/media/LOGGING/darsv1.csv");
    string line;
    string dataArray[226900];
    int i = 0;
    int endofline =0;
    int a, b, c, d, e;
    while (getline (inFile, line)) {
        //printf(line.c_str());
        istringstream linestream(line);
        string item ="";
        int itemnum = 0;
        if (lineNum==1) {
            printf(" line number is 1. ");
            while (getline (linestream, item, ',')) {
            itemnum++;
            dataArray[i]=item;
            i++;
            }
        }
        else {
            while (getline (linestream, item,'\n')) {
                endofline=endofline+1;
                cout<<"  went through line number  "<<endofline<<" ";
                printf(" inside inner while, looking for line. ");
                if (endofline == lineNum-1) {
                    printf(" found the correct line. ");
                    while (getline (linestream, item, ',')) {
                        itemnum++;
                        dataArray[i]=item;
                        i++;
                        printf(" found the correct data in the line. ");
                    }
                }
            }printf(" out of inner while. ");
        }printf(" out of outer if. ");
   }
   printf(" out of all while loops. ");
}
4

5 回答 5

1

如果您只需要读取 CSV 中的某一行,然后从该行读取逗号分隔的项目,那么这可能会有所帮助。我同意@sanjaya-r 的观点,你应该保持简单。

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
using namespace std;

int main (int argc, const char * argv[]) {
    string line, csvItem;
    ifstream myfile ("/tmp/file.csv");
    int lineNumber = 0;
    int lineNumberSought = 3;  // you may get it as argument
    if (myfile.is_open()) {
        while (getline(myfile,line)) {
            lineNumber++;
            if(lineNumber == lineNumberSought) {
                cout << line << endl; ;
                istringstream myline(line);
                while(getline(myline, csvItem, ',')) {
                    cout << csvItem << endl;
                }
            }
        }
        myfile.close();
    }
    return 0;
}
于 2013-08-09T22:41:59.910 回答
0

有一个 SO question and answer on a way to go a specific line in a text file where you can find Xeo's answer as my favorite one. Xeo 使用istream::ignore,足够的功能所以它是干净和快速的解决方案。

这是基于上述答案的完整示例(带有一些装饰):

#include <fstream>
#include <limits>
#include <string>
#include <iostream>

using namespace std;



fstream& Go2Line(fstream& file, unsigned int num)
{
    file.seekg(ios::beg);
    for(unsigned int i=0; i < num - 1; ++i)
        file.ignore(numeric_limits<streamsize>::max(),'\n');

    return file;
}



int main()
{
    fstream file("/media/LOGGING/darsv1.csv",ios_base::in);
    if (!file)
        cout << "Unable to open file /media/LOGGING/darsv1.csv\n";
    else 
    {
        int Number2Go = 4;
        Go2Line(file, Number2Go);

        if (!file)
            cout << "Unable to reach line " << Number2Go << ".\n";
        else
        {
            string line;
            getline(file,line);
            cout << "Line " << Number2Go << "reached successfully. It is:\n" << line;
        }
    }

    return 0;
}
于 2013-08-09T22:43:39.083 回答
0

这是不可编译的。

这是你的错误吗?

if (endofline = lineNum-1)

分配 lineNum - 1endofline. 用于==比较。

于 2013-08-09T20:55:51.590 回答
0

保持简单。让一个 getline 循环完成所有工作。第一行不需要特殊情况。

// ...
linesToGo = linesNum - 1;
string line;  
while(getline(infile,line) && (linesToGo > 0)) {
    linesToGo--;
}
if (linesToGo == 0) {
    cout << "found line:," << line << endl;
    // process here.
} else {
    count << "not enough lines in file." << endl;
}

另外,不要混合使用 cout 和 printf。

于 2013-08-09T22:00:44.097 回答
0

我创建了以下程序,因为我正在练习 C++ 算法。尽管该解决方案似乎有效,但请持保留态度(即,有些人可能认为它太复杂了)。另一方面,它可以帮助您理解迭代器、流和算法的某些方面。

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

/**
   @brief A trick proposed by Jerry Coffin / Manuel (SO users) to
         create a line-by-line iterator. This makes an `std::istream`
         yield lines as opposed to chars.
 */
struct Line
    : std::string { 
  friend std::istream & operator>>(std::istream& is, Line& line) {   
    return std::getline(is, line);
  }
};

/**
   @brief This predicate contains an internal count of the lines read
   so far. Its `operator()(std::string)` will evaluate to `true` when
   the current line read equals the target line (provided during
   construction).

 */
struct LineNumberMatcher {
  unsigned int target_line;
  unsigned int current_line;

  LineNumberMatcher(unsigned int target_line)
      : target_line(target_line),
        current_line(0) { }

  bool operator()(const std::string& line) {
    return ++current_line == target_line;
  }
};

int main(int argc, char* argv[]) {
  if(argc != 3) {
    std::cout<<"usage: "<<argv[0]<<" filename line"<<std::endl;
    return 0;
  }

  std::string filename(argv[1]);
  unsigned int target = std::stoi(argv[2]);

  // Build the LineNumberMatcher
  LineNumberMatcher match(target);

  // Provide a scope after which the file will be automatically closed
  {
    // Open the file
    std::ifstream fp(filename);

    // Copy the line to standard output if the LineNumberMatcher
    // evaluates to true (that is, when the line read equals the target
    // line)
    std::copy_if(std::istream_iterator<Line>(fp),
                 std::istream_iterator<Line>(),
                 std::ostream_iterator<std::string>(std::cout, "\n"),
                 match);
  }

  return 0;  
}

使用 C++11 支持进行编译(在我的情况下g++ spitline.cpp -std=c++111,使用 GCC 4.7.2)。样本输出:

$ /a.out spitline.cpp 7 
  @brief A trick proposed by Jerry Coffin / Manuel (SO users) to

这确实是我的源代码中的第 7 行。

于 2013-08-09T23:10:39.420 回答