We help IT Professionals succeed at work.

Input files

jschmuff asked
Last Modified: 2010-04-01
I dont exactly know what the problem is my program runs but wont output to the console the 1st and 3rd letters . I believe it is reading from the input code fine because if I delete the numbers portion of the code and just leave the words it will do it correctly what is going on with this I dont understand how it wont do it when it is all together

here is my code:

#include <iostream>
#include <string>
#include <fstream>

using namespace std;

int main()

        ifstream inFile;
        ofstream outFile;

      int numbers[5];
      int counter;
      string words[5];


        cout << "Processing information from numbers file...." << endl;

      for(counter=0; counter < 5; counter++)
            inFile >> numbers[counter];
        cout << "\nInformation stored successfully! "<<endl;

      for(counter = 4; counter >= 0; counter--)
            outFile << numbers[counter] << endl;
        cout << "\nProcessing five words already input from file...." << endl;



      for(counter = 0; counter < 5; counter++)
            inFile >> words[counter];
        words[counter] = "end_of_array";

      counter = 0;

            cout << words[counter].substr(0,1) << words[counter].substr(2,1) << endl;

        while(words[counter]!= "end_of_array");

        return 0;
Watch Question

Unlock this solution and get a sample of our free trial.
(No credit card required)

One problem is here:

      for(counter = 0; counter < 5; counter++)
            inFile >> words[counter];
        words[counter] = "end_of_array";

When control exits the for loop, counter will be 5 and the next statement will try to assign to words[counter], which will be words[5].  But words was declared to be an array of 5 strings, so valid subscripts are 0 through 4, so there is no words[5].

Try fixing that and see if it still doesn't work.
Some remarks on your prog:

>>>> ifstream inFile;
>>>> ofstream outFile;

You can 'open' the files with the constructor:

     ifstream inFile("input.txt");
     ifstream inFile("output.txt");

There is no advantage in using a separate open statement as the return type of basic_ifstream::open is void.

>>>> int numbers[5];
>>>> string words[5];

Instead of fixed-sized arrays you should consider of using std::vector:

    vector<int> numbers(5);
    vector<string> words(5);

These two statements would create an array of 5 elements same as your definiitions. In case of 'numbers' the items were initiallized with 0. std::vector has the advantage that it will grow dynamically and that you don't have to care for allocation or array boundaries.

    vector<int> numbers;
    vector<string> words;

I would suggest to have empty arrays at begin and let grow them dynamically when reading the values.

>>>> for(counter=0; counter < 5; counter++)

When reading from a file, you should avoid reading a fixed number or items. Better read all items to a dynamically growing array like std::vector *or* read up to a maximum of entries. In any case you should check for read errors and end-of-file.

    const unsigned int maxread = 5;
    counter = 0;
    int num;
    while (number.size() < maxread && inFile >> num)
            numbers.push_back(num);   // add num to vector
    counter = (int)numbers.size();

With that you would only read if the inFile is still valid. Note, the condition 'inFile >> num' tests on the stream status. In case of inFile.eof() and inFile.fail() the condition is false.

If using std::vector you can omit the 'counter' variable cause with numbers.size() you alway can retrieve the count.

>>>> for(counter = 4; counter >= 0; counter--)
That would turn to

    for(counter = (int)numbers.size()-1; counter >= 0; counter--)

>>>> inFile.open("words.txt");

There is no problem in (re)opening a orderly closed inputfile, though I also would choose a second ifstream as avatar-e suggested.

>>>>       for(counter = 0; counter < 5; counter++)

Same thing: when using vector it would turn to

      string word;
      while (words.size() < maxread && inFile >>  word)

Note, the 'inFile >> word' would stop 'streaming' if the word contains a space or tab character. If you would like to read a 'line' rather than a 'word', you'll better would use std::getline.

      string line;
      while (words.size() < maxread && getline(inFile, line))

>>>> words[counter] = "end_of_array";
As both avatar-e and efn already explained, you are writing beyond the array size of 5 items. But even if you increase the size to 6, it is dangerous to trust that the previous loop has set the counter variable correctly. Assume, you would have got an error with the first read and would have checked for the error and broke the loop at the first entry. Then counter == 0 and string[0] == "end_of_array" but the following do-while never would break cause counter is 1 or higher when checking for the "end_of_array".  If you would have made

   string words[6];
   words[sizeof(words)/sizeof(words[0]) - 1] = "end_of_array";

you would have been safe, and you could increase the array-size without needing to change all loop-boundaries. Far better would be using vector<string> as the statement simply would be


Note, terminating an array with some kind of 'terminator' is not state-of-the-art. Normally only char arrays were terminated with a zero char and all other arrays were managed by size rather than by terminator. If using string instead char arrays, the internal char arrays still have zero termination but that is for providing a const char pointer via string::c_str() only. The string class manages its char array by size as you should do with all other arrays as well.

>>>>      do { ... } while (...);

A do-while has the advantage/disadvantage that the body of the loop was processed at least one time. In your code it is a disadvantage cause it makes no sense to check the loop-size boundary at end of the loop. Then you already might have accessed the arrays with an index that is beyond or equal to the upper boundary. Worse, you might check for a condition that is never true if the initializing

   string[counter] = "end_of_array";

was dropped somehow or if counter was 0 for any reason. Then you'll get an infinite loop! While conditions were dangerous and you should make them absolute safe. Better use for loops or while loops which check for an upper boundary

   while (counter < maxread && ...
It even makes sense to increment the loop counter in the while condition to absolutely make sure that the 'counter' was incremented:

   while (++counter <= maxread && ...)   // note the <=

However, you should consider using a for loop in that case cause normally it is better to have the loop counter run from 0 to maxread-1 rather than from 1 to maxread as it would be with the above while.

Regards, Alex

Gain unlimited access to on-demand training courses with an Experts Exchange subscription.

Get Access
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant
Empower Your Career
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE

Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Unlock the solution to this question.
Thanks for using Experts Exchange.

Please provide your email to receive a sample view!

*This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.


Please enter a first name

Please enter a last name

8+ characters (letters, numbers, and a symbol)

By clicking, you agree to the Terms of Use and Privacy Policy.