0

I have a text file that contains keys and values like this:

keyOne=1
keyTwo=734
keyThree=22.3
keyFour=5

The keys are just lower-case and upper-case letters like in my example. The values are either integers or floats. Each key and value is separated by an equals sign (=). Now I want to read the values into variables I have in my program.

This is the code I have tried to read the values: (I omitted the part where I store the values in my program's variables, and just print them out now for demonstration.)

std::fstream file(optionsFile, std::fstream::in);

if (file.good()) {
  int begin;
  int end;
  std::string line;

  while(std::getline(file, line)) {

    // find the position of the value in the line
    for (unsigned int i = 0; i < line.length(); i++) {
      if (line.at(i) == '=') {
        begin = i + 1;
        end = line.length();
        break;
      }
    }

    // build the string... it starts at <begin> and ends at <end>
    const char *string = "";
    for (int i = begin; i < end; i++) {
      string += line.at(i);
    }

    // only gibberish is printed in the following line :(
    std::cout << "string=" << string << std::endl;
  }
}

I don't understand why it won't print the value.. instead only weird stuff or even nothing is printed

Please help this broke my spirit so hard :(

2
  • 1
    Please write a self-contained snippet with a main function that people can take an experiment with. Commented Aug 24, 2013 at 15:44
  • What do you mean by: "Check if the key is a certain key (to check if the user messed with it)"? Commented Aug 24, 2013 at 15:49

2 Answers 2

1

You are using C-style strings (char arrays) without properly allocated memory, and you are just manipulating with the pointer, so you are not appending characters into your string:

   // build the string... it starts at <begin> and ends at <end>
const char *string = "";
for (int i = begin; i < end; i++) {
  string += line.at(i);
}

Use std::string instead:

/// build the string... it starts at <begin> and ends at <end>
std::string str;
for (int i = begin; i < end; i++) {
  str += line.at(i);
}

Or allocate memory by hand, use the proper indexing, terminate the string with '\0' character and don't forget to delete the string after you don't need it anymore:

char *string = new char[end - begin + 1];
int j = 0;
for (int i = begin;  i < end; i++) {
  string[j++] = line.at(i);
}

// Don't forget to end the string!
string[j] = '\0';

// Don't forget to delete string afterwards!
delete [] string;

So, just use std::string.

Edit Why did you mix C strings and std::string in the first place?

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you my friend that did the trick.. I don't know why I did such a stupid thing ^^ I used std::string at the very beginning but the compiler said I had to use const char or something I don't remember so I changed it. But I did something wrong but now it's all good
1

As was already mentioned, native string types in c/c++ do not support straightforward concatenation since they are essentially pointers to some preallocated memory. You should always use std::string when a string is supposed to be mutable.

Btw, think about the following refactoring:

void process_option (const std::string& a_key, const std::string& a_value)
{
    std::cout << a_key << " <-- " << a_value << std::endl;
}

void read_options (std::istream& a_in, const char* a_source)
{
    int line_n = 0;
    std::string line;
    while (std::getline(a_in, line))
    {
        ++ line_n;
        std::string::size_type p = line. find('=');
        if (p == line. npos)
        {
        //  invalid_entry(a_source, line_n);
            continue;
        }

        process_option(
            line. substr(0, p), // key
            line. substr(p + 1, line. find_first_of("\t\r\n", p + 1)) // value
        );
    }
}

void read_options (const char* a_filename)
{
    std::ifstream file(a_filename);
    if (! file)
    {
    //  read_error(a_filename);
        return;
    }
    read_options(file, a_filename);
    file. close();
}

void read_options (const std::string& a_filename)
{
    read_options(a_filename. c_str());
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.