简体   繁体   中英

Reading floats/words/symbols from a file and ONLY storing the floats in an array C++

I have a C++ programming question that I'm asked to read from a file that contains several floats, words and symbols (eg # ! % ). From this file I must take only the floats and store it into an array.

The text file may look like this

11
hello
1.00
16.0
1.999

I know how to open the file; it's just grabbing ONLY the floats I'm struggling with.

You have to use fscanf() . Read the documentation for information how to use it.

As long as you don't mind treating integral numbers as floats, such as 11 in your post, you can use the following strategy.

  1. Read one token at a time that are separated by whitespaces into a string.
  2. Extract a floating point number from the string using one of several methods.
  3. If the extraction was successful, process the floating point number. Otherwise, move on to the next token.

Something along the lines of the code below should work.

std::string token;
std::ifstream is(filename); // Use the appropriate file name.
while ( is >> token )
{
   std::istringstream str(is);
   float f;
   if ( str >> f )
   {
      // Extraction was successful.
      // Check whether there is more data in the token.
      // You don't want to treat 11.05abcd as a token that represents a
      // float.
      char c;
      if ( str >> c )
      {
         // Ignore this token.
      }
      else
      {
         // Process the float.
      }
   }
}
// reading a text file and storing only float values
#include <iostream>
#include <fstream>
#include <string>
#include <sstream>

using namespace std;

int main () {
  string line;
  ifstream myfile ("example.txt");
  std::vector<float> collection;

  if (myfile.is_open())
  {
    while ( getline (myfile,line) )
    {
      if(checkIfFloatType(line))
      {
         collection.push_back(std::stof (line));
      }
    }
    myfile.close();
  }

  else cout << "Unable to open file"; 

  return 0;
}

bool checkIfFloatType( string str ) {
    std::istringstream iss(str);
    float f;
    iss >> noskipws >> f;
    return iss.eof() && !iss.fail(); 
}

I'd use a ctype facet that classifies everything except for digits as being white space:

struct digits_only : std::ctype<char>
{
    digits_only() : std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        static std::vector<std::ctype_base::mask>
            rc(std::ctype<char>::table_size, std::ctype_base::space);

        if (rc['0'] == std::ctype_base::space)
            std::fill_n(&rc['0'], 9, std::ctype_base::mask());
        return &rc[0];
    }
};

Then imbue the stream with a locale using that facet, and just read your numbers:

int main() {
    std::istringstream input(R"(
11

hello

1.00

16.0

1.999)");

    input.imbue(std::locale(std::locale(), new digits_only));

    std::copy(std::istream_iterator<float>(input), std::istream_iterator<float>(),
        std::ostream_iterator<float>(std::cout, "\t"));
}

Result:

11      1       16      1.999

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM