0

I am building a map from a text file using the std::unordered_map data structure, using the pair < uint64_t id, BaseDevice device >. BaseDevice is a structure, containing a 64-bit id and a string:

struct BaseDevice
{
public:
    uint64_t id;
    string ipAddress;
}

I read a file (assuming that it is correctly written) and build the map as follows:

char buffer[1024];
ifstream fin(myfile.c_str());

while(fin.eof() == false)
{
  fin.getline(buffer, 1023);
  StringTokenizer st(buffer, " ");

  //Parse ID and address
  unsigned int id = atoi(st.nextToken().c_str()); //get ID
  string ipAddress = st.nextToken();  //get IP address

  //Create the local structure and add to the map
  BaseDevice dev;
  dev.id = id;
  dev.ipAddress = ipAddress;
  myMap[id] = dev;

  break;
}

The strange thing is that when I traverse my map, the ipAddress string seems to be (null), while both length() and size() are not.

unordered_map< string, BaseDevice >::const_iterator itr1;
for(itr1 = myMap.begin(); itr1 != myMap.end(); itr1++)
{
  const BaseDevice& device = itr1->second;
  fprintf(stdout, "id %lu ipAddress %s \n", myMap->first, device.ipAddress);
  printf("Length is %d \n", device.ipAddress.length());
  printf("Size is %d \n", device.ipAddress.size());

  /*
  OUTPUT:

  id 2 ipAddress (null)
  Length is 8  
  Size is 8
  */
}

I would like to ask you: how is this possible? Am I doing something wrong? Thanks.

theleos
  • 113
  • 7
  • 1
    `fprintf()` gives undefined behaviour if the format specifier is inconsistent with the type of the corresponding argument. `%s` assumes a C-style string (represented as an array of `char`, terminated with a zero value). A `std::string` is not a C style string. Why are you using C++ iostreams in some code, and `fprintf()` in other code? That is a prime recipe for confusion. – Peter Jun 14 '16 at 16:05
  • 2
    `eof()` is [not a good condition](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) for your loop. You should instead be making sure that `getline` succeeds instead of blindly assuming it does. Also note that all major compilers currently warn on mismatched `printf` types. Turn up your compiler warnings. – chris Jun 14 '16 at 16:16
  • @Peter, you are right, I am mixing few things. I am used to C syntax, and quite new to the C++ environment. – theleos Jun 14 '16 at 16:30
  • @chris I think that I will change the loop condition. – theleos Jun 14 '16 at 16:31

1 Answers1

3

You're printing device.ipAddress as if it was a C-string (with %s format specifier), which is incorrect, so fprintf may go nuts while trying to print it. You should do:

fprintf(stdout, "...%s...", device.ipAddress.c_str());

You can also do the same with std::cout:

std::cout << device.ipAddress << '\n';
ForceBru
  • 36,993
  • 10
  • 54
  • 78