0

Here's a code i wrote...pretty basic as I'm a beginner.....

The source file looks like:

Integers:
1 2 3 4 56 ...

String:
This is a string......
...(text).....

The code should read the text depending on the keywords it encounters at the beginning,,,

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

int main ()
{
    int i;
    string STRING;
    char *inname = "source.txt";
    ifstream infile(inname);

    if (!infile) 
    {
        cout << "There was a problem opening file "<< inname<< " for reading."<< endl;
        return 0;
    };
    while (STRING != "Integer:")
        {
            getline(infile,STRING); // Saves the line in STRING.

            cout<<STRING<<endl; // Prints our STRING.
        };

    };
    cout << "Opened " << inname << " for reading." << endl<<endl<<"Integers:";
    while (infile >> i) {
        cout<<endl<<i<<endl;
    infile.close();
    return 0;
    }
}

Thanks a lot!

WhozCraig
  • 65,258
  • 11
  • 75
  • 141
  • 2
    For starters, I think looking for the line that *starts* with "Integers:" rather then *equals* "Integer:" may have tremendous benefit. Learning about string streams will probably bode well for you also. Of course, you could also have the question formatted so it *looks* like `Integers:` and the numbers that follow are on the same line, when in fact they are not; likewise for `String:`. – WhozCraig Jan 21 '13 at 03:57
  • thnx...btw source file has 'Integer:'in it.... – Manoj Kumar V Jan 21 '13 at 04:17
  • Yeah,, its different in your code and in the question; likely what threw me off. sorry about that. – WhozCraig Jan 21 '13 at 04:32
  • Yeah....btw can string compare be used for the purpose? – Manoj Kumar V Jan 21 '13 at 04:37
  • Honestly, your input is super simple. I'd probably read it line by line, check the lead token for your "Integer:", "String:", skip it if it is either, and depending on which it was, feed the rest of the line to a stringstream that busts it into either `int`s or `std::string`s. if the next line starts with neither, then just keep reading what you were before, only switching when a new line starts with a different token. Something like that. you know your problem-space better than we do, so go with whatever truly works for you. – WhozCraig Jan 21 '13 at 04:54
  • Is it *just* one "Integer:" and one "String:" section, or is it possible to have multiple similar sections, and also, by your sample, is it guaranteed a *blank* line will separate sections? These are all things that you should be considering when approaching this problem if you're breaking it apart like this – WhozCraig Jan 21 '13 at 04:59
  • Thanks man....hope dat helps – Manoj Kumar V Jan 21 '13 at 05:22

2 Answers2

0

You need to tokenize the words found in the line. There are many ways of doing this, you can use stringstream, boost tokenizer, or even write your own code.

Assuming you create a rule where each word (token) is separated by spaces, and you've managed to tokenize the lines, then you can just write a code checking the first token in the line and action appropriately

gerrytan
  • 40,313
  • 9
  • 84
  • 99
0

IMHO you are missing some state in your parser, some check if the file is still valid and parsing the integers.

Here is a proof of concept:

#include <fstream>
#include <iostream>
#include <vector>

namespace {

  void parse_integers(std::vector<int> & vi, std::string const & line) {
    // Using strtol here - other tokenizers are possible.
    char const * ip { line.c_str() };
    char * ep;

    do {
      long int const v { strtol( ip, &ep, 10 ) };
      vi.push_back( v );
      ip = ep;
    } while( *ep != '\0' );

  }
}

int main() {

  std::string   inname { "source.txt" };
  std::ifstream infile { inname };

  if( ! infile ) {
    std::cout << "There was a problem opening file "
          << inname << " for reading." << std::endl;
        return 0;
  };

  enum class ParseState {
    outer, found_integers, found_string
  };

  ParseState ps { ParseState::outer };

  std::vector<int> s_integers;
  std::string      s_string;

  while( infile ) {
    std::string line;
    getline( infile, line );

    // Skip empty lines
    if( line.size() == 0 ) {
      continue;
    }

    if( line == "Integers:" ) {
      ps = ParseState::found_integers;
      continue;
    } else if( line == "String:" ) {
      ps = ParseState::found_string;
      continue;
    }

    // Hope that a section was already found....
    if( ps == ParseState::outer ) {
      std::cerr << "Line with data but without a section found ["
        << line << "]" << std::endl;
      continue;
    }

    switch( ps ) {
    case ParseState::found_integers:
      parse_integers(s_integers, line);
      break;

    case ParseState::found_string:
      s_string += line + "\n";
      break;

    case ParseState::outer:
      // Cannot happen
      abort();
    }
  }

  std::cout << "Dump file contents" << std::endl;
  std::cout << "Strings: [" << s_string << "]" << std::endl;
  std::cout << "Integers: ";
  for(int i : s_integers) {
    std::cout << "[" << i << "] ";
  }
  std::cout << std::endl;

  return 0;
}

Input:

Integers:
1 2 3 4 56 111 761 777

String:
This is a string......
...(text).....

Output:

Dump file contents
Strings: [This is a string......
...(text).....
]
Integers: [1] [2] [3] [4] [56] [111] [761] [777] 
Andreas Florath
  • 4,418
  • 22
  • 32