Question

I have been looking for an error in a code that I am using for finite element methods. The point is that I have to get some data from a file to identify the material of a cell. The type of this material_id is unsigned char , and here is the problem.

When reading the data from the file, different ways to assign the value to a unsigned char variable gives different result. I have fixed the problem, but I am still wondering why it is working in a different way. Here you have a sample code reproducing the different behavior:

#include <map>
#include <sstream>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <stdlib.h>

namespace types
{
//typedef unsigned int material_id;
typedef unsigned char  material_id;
}

namespace Utilities
{
  int string_to_int(const std::string & str)
  {
    return atoi(str.c_str());
  }
}

template<typename Number>
void parseVector_1(std::ifstream & myfile,
                   std::vector<Number> & mat_id)
{
  Number num;
  std::string line, bin;

  if (myfile.is_open())
  {
    getline (myfile,line);
    std::istringstream iss(line);
    while ( iss.good() )
    {
      iss >> bin;                            // option 1
      num = Utilities::string_to_int(bin);   // option 1
      mat_id.push_back(num);
    }
  }
  else std::cout << "Unable to open file"; 
}

template<typename Number>
void parseVector_2(std::ifstream & myfile,
                   std::vector<Number> & mat_id)
{
  Number num;
  std::string line, bin;

  if (myfile.is_open())
  {
    getline (myfile,line);
    std::istringstream iss(line);
    while ( iss.good() )
    {
      iss >> num; // option 2
      mat_id.push_back(num);
    }
  }
  else std::cout << "Unable to open file"; 
}

int main()
{
  unsigned int n_mat;

  std::vector<types::material_id> mat_id_1;
  std::vector<types::material_id> mat_id_2;
  std::map<types::material_id, double> D1v;

  D1v[0] = 0.0;
  D1v[1] = 1.0;
  D1v[2] = 2.0;
  D1v[3] = 3.0;
  D1v[4] = 4.0;

  std::ifstream myfile1 ("materials.dat");
  parseVector_1(myfile1, mat_id_1);
  myfile1.close();


  std::ifstream myfile2 ("materials.dat");
  parseVector_2(myfile2, mat_id_2);
  myfile2.close();

  n_mat = mat_id_1.size();
  std::cout << "option 1: ";
  for (unsigned int i = 0; i < n_mat; ++i)
    std::cout << "mat["<<i<<"]=" << D1v[mat_id_1[i]] << " ";
  std::cout << std::endl;

  n_mat = mat_id_2.size();
  std::cout << "option 2: ";
  for (unsigned int i = 0; i < n_mat; ++i)
    std::cout << "mat["<<i<<"]=" << D1v[mat_id_2[i]] << " ";
  std::cout << std::endl;

  return 0;

}

The content of the "materials.dat" file is the following line:

0 1 2 3 4

And here is the output of the execution:

$ unsignedchar_problem.exe 
option 1: mat[0]=0 mat[1]=1 mat[2]=2 mat[3]=3 mat[4]=4  
option 2: mat[0]=0 mat[1]=0 mat[2]=0 mat[3]=0 mat[4]=0 mat[5]=0

Can anyone give some insight why option 1 is working fine, but option 2 is not? Is it dependent on the compiler/platform of it is always like that?

As an additional information, the problem was because the material_id type was defined as unsigned int by the other user in his computer, so it was working without any problem.

Was it helpful?

Solution

Extracting unsigned char from an istream reads a single character and stores that character's numeric value into the destination variable. So mat_id_2[0] will contain the numeric value of '0', which is probably 48 (if your system is ASCII).

Extracting a non-chararacter integral type will read an integer and store the value of that integer, as you were expecting.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top