Task: Read a configuration file


C++: #include "stdafx.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/case_conv.hpp>
using namespace std;
using namespace boost;

typedef boost::tokenizer<boost::char_separator<char> > Tokenizer;
static const char_separator<char> sep(" ","#;,");


struct configs{
	string fullname;
	string favoritefruit;
	bool needspelling;
	bool seedsremoved;
	vector<string> otherfamily;
} conf;

void parseLine(const string &line, configs &conf)
{
	if (line[0] == '#' || line.empty())
		return;
	Tokenizer tokenizer(line, sep);
	vector<string> tokens;
	for (Tokenizer::iterator iter = tokenizer.begin(); iter != tokenizer.end(); iter++)
		tokens.push_back(*iter);
	if (tokens[0] == ";"){
		algorithm::to_lower(tokens[1]);
		if (tokens[1] == "needspeeling")
			conf.needspelling = false;
		if (tokens[1] == "seedsremoved")
			conf.seedsremoved = false;
	}
	algorithm::to_lower(tokens[0]);
	if (tokens[0] == "needspeeling")
		conf.needspelling = true;
	if (tokens[0] == "seedsremoved")
		conf.seedsremoved = true;
	if (tokens[0] == "fullname"){
		for (unsigned int i=1; i<tokens.size(); i++)
			conf.fullname += tokens[i] + " ";
		conf.fullname.erase(conf.fullname.size() -1, 1);
	}
	if (tokens[0] == "favouritefruit") 
		for (unsigned int i=1; i<tokens.size(); i++)
			conf.favoritefruit += tokens[i];
	if (tokens[0] == "otherfamily"){
		unsigned int i=1;
		string tmp;
		while (i<=tokens.size()){		
			if ( i == tokens.size() || tokens[i] ==","){
				tmp.erase(tmp.size()-1, 1);
				conf.otherfamily.push_back(tmp);
				tmp = "";
				i++;
			}
			else{
				tmp += tokens[i];
				tmp += " ";
				i++;
			}
		}
	}
}

int _tmain(int argc, TCHAR* argv[])
{
	if (argc != 2)
	{
		wstring tmp = argv[0];
		wcout << L"Usage: " << tmp << L" <configfile.ini>" << endl;
		return -1;
	}
	ifstream file (argv[1]);
	
	if (file.is_open())
		while(file.good())
		{
			char line[255];
			file.getline(line, 255);
			string linestring(line);
			parseLine(linestring, conf);
		}
	else
	{
		cout << "Unable to open the file" << endl;
		return -2;
	}

	cout << "Fullname= " << conf.fullname << endl;
	cout << "Favorite Fruit= " << conf.favoritefruit << endl;
	cout << "Need Spelling= " << (conf.needspelling?"True":"False") << endl;
	cout << "Seed Removed= " << (conf.seedsremoved?"True":"False") << endl;
	string otherFamily;
	for (unsigned int i = 0; i < conf.otherfamily.size(); i++)
		otherFamily += conf.otherfamily[i] + ", ";
	otherFamily.erase(otherFamily.size()-2, 2);
	cout << "Other Family= " << otherFamily << endl;

	return 0;
}









Fortran: program readconfig
  implicit none
  integer, parameter    :: strlen = 100
  logical               :: needspeeling = .false., seedsremoved =.false.
  character(len=strlen) :: favouritefruit = "", fullname = "", fst, snd
  character(len=strlen), allocatable :: otherfamily(:), tmp(:)
  character(len=1000)   :: line
  integer               :: lun, stat,  j, j0, j1, ii = 1, z
  integer, parameter    :: state_begin=1, state_in_fst=2, state_in_sep=3

  open(newunit=lun, file="config.ini", status="old")
  
  do 
    read(lun, "(a)", iostat=stat) line
    if (stat<0) exit
    if ((line(1:1) == "#") .or. &
        (line(1:1) == ";") .or. &
        (len_trim(line)==0)) then
      cycle
    end if
    z = state_begin
    do j = 1, len_trim(line)
      if (z == state_begin) then
        if (line(j:j)/=" ") then
          j0 = j
          z = state_in_fst
        end if
      elseif (z == state_in_fst) then
        if (index("= ",line(j:j))>0) then
          fst = lower(line(j0:j-1))
          z = state_in_sep
        end if
      elseif (z == state_in_sep) then
        if (index(" =",line(j:j)) == 0) then
          snd = line(j:)
          exit
        end if
      else
         stop "not possible to be here"
      end if
    end do
    if (z == state_in_fst) then
      fst = lower(line(j0:))
    elseif (z == state_begin) then
      cycle
    end if

    if (fst=="fullname") then
      read(snd,"(a)") fullname
    elseif (fst=="favouritefruit") then
      read(snd,"(a)") favouritefruit
    elseif (fst=="seedsremoved") then
      seedsremoved = .true.
    elseif (fst=="needspeeling") then
      needspeeling = .true.
    elseif (fst=="otherfamily") then
      j = 1; ii = 1
      do while (len_trim(snd(j:)) >0)
        j1  = index(snd(j:),",")
        if (j1==0) then
          j1 = len_trim(snd)
        else
          j1 = j + j1 - 2
        end if
        do 
          if (j>len_trim(snd)) exit
          if (snd(j:j) /= " ") exit
          j = j +1
        end do
        allocate(tmp(ii)) 
        tmp(1:ii-1) = otherfamily
        call move_alloc(tmp, otherfamily)
        read(snd(j:j1),"(a)"), otherfamily(ii)
        j = j1 + 2 
        ii = ii + 1
      end do
    else 
      print *, "unknown option '"//trim(fst)//"'"; stop
    end if
  end do
  close(lun)

  print "(a,a)","fullname = ",       trim(fullname)
  print "(a,a)","favouritefruit = ", trim(favouritefruit)
  print "(a,l)","needspeeling = ",   needspeeling
  print "(a,l)","seedsremoved = ",   seedsremoved
  print "(a,*(a,:,', '))", "otherfamily = ", &
         (trim(otherfamily(j)), j=1,size(otherfamily))

contains

pure function lower (str) result (string)
    implicit none
    character(*), intent(In) :: str
    character(len(str))      :: string
    Integer :: ic, i

    character(26), parameter :: cap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    character(26), parameter :: low = 'abcdefghijklmnopqrstuvwxyz'

    string = str
    do i = 1, len_trim(str)
        ic = index(cap, str(i:i))
        if (ic > 0) string(i:i) = low(ic:ic)
    end do
end function 

end program