如何通过读取文件将不同数据类型的数据推入向量?

时间:2012-12-05 02:15:39

标签: c++ c file vector scanf

我想使用下面的代码将下面的数据推送到一个向量中。但是我的代码只适用于整数。如何对下面的数据执行此操作?谢谢。

我的数据:

    M,0.455,0.365,0.095,0.514,0.2245,0.101,0.15,15
    M,0.35,0.265,0.09,0.2255,0.0995,0.0485,0.07,7
    F,0.53,0.42,0.135,0.677,0.2565,0.1415,0.21,9
    M,0.44,0.365,0.125,0.516,0.2155,0.114,0.155,10
    I,0.33,0.255,0.08,0.205,0.0895,0.0395,0.055,7
    I,0.425,0.3,0.095,0.3515,0.141,0.0775,0.12,8
    F,0.53,0.415,0.15,0.7775,0.237,0.1415,0.33,20
    F,0.545,0.425,0.125,0.768,0.294,0.1495,0.26,16
    M,0.475,0.37,0.125,0.5095,0.2165,0.1125,0.165,9
    F,0.55,0.44,0.15,0.8945,0.3145,0.151,0.32,19

我的代码:

      fp = fopen(argv[1], "r"); //Opening the input file in read mode.
      if(!fp)
      {
          printf("open data source file failed!\n");
          goto MAINEXIT;
      }

      int ivalue;
      //extract data from files
      while(fscanf(fp,"%d,",&ivalue)!=EOF)
      {
          printf("Counter-%d\n",counter++);
          srcdata.push_back(ivalue); //Pushing value by value into the vector with "," delimiter.
      }

      if(fp)
      fclose(fp);

2 个答案:

答案 0 :(得分:2)

%d用于整数。将其更改为%lf double,并相应更改其他部分,例如,将ivalue更改为double


根据你在问题中的评论,我认为你可能需要像

这样的东西
while(fscanf(fp,"%s", str)!=EOF)
{
    char* pch = strtok(str, ",");
    pch = strtok(NULL, ","); // skip first
    while (pch != NULL)
    {
        double d = atof(pch);
        printf("Counter-%d\n",counter++);
        srcdata.push_back(d);
        pch = strtok (NULL, ",");
    }
}

答案 1 :(得分:0)

由于您使用的是C ++ STL容器(vector),因此您应该使用C ++ I / O(iostream)而不是C I / O(stdio)。它更安全,更灵活,最终可以为您节省一些胃灼热。

这是一个快速的脏样本,展示了如何将数据读入矢量:

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

/**
 * Create a struct type to represent each record,
 * with one char member (which I'm calling "gender"
 * based on the 'M' and 'F', but that's just a guess),
 * 7 doubles (which I've gathered into a fixed-size
 * array), and one integer.
 *
 * I've also overloaded the stream << and >> operators
 * to read and write the struct as a single entity.
 */
struct record {
  char gender;
  double dvar[7];
  int ivar;

  record() { }
  virtual ~record() { }

  std::ostream& operator<<(std::ostream& s)
  {
    s << gender << " ";
    for (int i = 0; i < 7; i++)
      s << std::fixed << std::setw(8) << std::setprecision(4) << dvar[i] << " ";
    s << std::setw(3) << ivar;
    return s;
  }

  std::istream& operator>>(std::istream& s)
  {
    char delim;
    s >> gender >> delim;
    for (int i = 0; i < 7; i++)
      s >> dvar[i] >> delim;
    s >> ivar;
    return s;
  }
};

/**
 * Overload the << and >> operators outside of the struct
 * definition; this is necessary for the istream and ostream
 * iterators to function properly.  Each operator simply
 * calls the overloaded operator in the struct definition
 */
std::ostream& operator<<(std::ostream& s, const record& r)
{
  const_cast<record&>(r).operator<<(s);
  return s;
}

std::istream& operator>>(std::istream& s, record& r)
{
  r.operator>>(s);
  return s;
}

/**
 * For the purpose of this example I'm reading from a string
 * stream local to main; however, you can swap out the string
 * stream with a C++ file stream (ifstream) and use it in the
 * copy method *exactly* as you use the string stream:
 *
 *    std::ifstream infile(filename);
 *    ...
 *    std::copy(std::istream_iterator<record>(infile),
 *              std::istream_iterator<record>(),
 *              std::back_inserter(myRec));
 */
int main(void)
{
  std::vector<record> myRec;

  /**
   * We're using a local string and string stream for the purpose of
   * this example, but the handling of a string stream and a file
   * stream would be exactly the same.
   */
  std::string data = "M,0.455,0.365,0.095,0.514,0.2245,0.101,0.15,15"
                   "M,0.35,0.265,0.09,0.2255,0.0995,0.0485,0.07,7"
                   "F,0.53,0.42,0.135,0.677,0.2565,0.1415,0.21,9"
                   "M,0.44,0.365,0.125,0.516,0.2155,0.114,0.155,10"
                   "I,0.33,0.255,0.08,0.205,0.0895,0.0395,0.055,7"
                   "I,0.425,0.3,0.095,0.3515,0.141,0.0775,0.12,8"
                   "F,0.53,0.415,0.15,0.7775,0.237,0.1415,0.33,20"
                   "F,0.545,0.425,0.125,0.768,0.294,0.1495,0.26,16"
                   "M,0.475,0.37,0.125,0.5095,0.2165,0.1125,0.165,9"
                   "F,0.55,0.44,0.15,0.8945,0.3145,0.151,0.32,19";

  std::stringstream dataStream;
  /**
   * Write the contents of the string to the string stream
   */
  dataStream << data;
  /**
   * Read the contents of the string stream into the vector
   */
  std::copy(std::istream_iterator<record>(dataStream),
            std::istream_iterator<record>(),
            std::back_inserter(myRec));

  std::cout << "Read " << myRec.size() << " records" << std::endl;

  /**
   * Write the contents of the vector to standard output.
   */
  std::copy(myRec.begin(), 
            myRec.end(), 
            std::ostream_iterator<record>(std::cout, "\n"));

  return 0;
}

这非常简单;没有任何错误处理或处理格式错误的输入的方法。但是,我认为它很好地说明了C ++ I / O例程的强大功能。

但是,如果您坚持使用C I / O,则可以执行以下操作:

struct record {
  char gender;
  double dvar[7];
  int ivar;
};

int getRecord(FILE *stream, struct record *r)
{
  char line[80]; // assuming each line is less than 80 characters long

  if (fgets(line, sizeof line, stream))
  {
    int count = sscanf(line, "%c,%f,%f,%f,%f,%f,%f,%f,%d",
                  &r->gender,
                  &r->dvar[0],
                  &r->dvar[1],
                  &r->dvar[2],
                  &r->dvar[3],
                  &r->dvar[4],
                  &r->dvar[5],
                  &r->dvar[6],
                  &r->ivar);
    if (count < 8)
    {
      fprintf(stderr, "Input line \"%s\" is malformed\n", line);
      return 0;
    }
  }
  else
  {
    if (feof(stream))
    {
      fprintf(stderr, "Reached end of file\n");
    }
    else
    {
      perror("Error on read");
    }
    return 0;
  }
  return 1;
}

int main(void)
{
   std::vector<record> myRec;
   FILE *input = fopen("myfile.dat", "r");
   record r;

   while(getRecord(input, &r))
     myRec.push_back(r);
   ...
}    

强烈建议使用C ++ I / O例程;将C I / O与C ++混合是胃灼热的一种方法。