Can't get my basic i/o program to work

Hi, I am trying to make a program that reads a text file and outputs certain information. the text file looks like this (There are about 3000 parts all together):

PartID: 94119
NumAvailable: 1413
ExpectedDate: 1/1/2005 12:00:00 AM
< other lines
< otherlines
<
<
<
< blah blah blah
<
<
<
<
<
PartID: 36466
NumAvailable: 0
ExpectedDate: 1/1/2005 12:00:00 AM
<
<
< more lines
<
<
< more lines
<
<
<
<
<

Here is my program:

#include <iostream>
#include <fstream>
#include <string>
using namespace std;



int main()
{
string filename;
ifstream inp;
inp.open("combined.txt");
ofstream outp;
outp.open("output.txt");

string temp;
int numofparts;
cout << "How many parts: ";
cin >> numofparts;

for(int i=0; i<(numofparts*14); i++)
{
getline(inp,temp);
if(temp[0]=='P' || temp[0]=='N')
{
outp << temp << '\t';
}
else if(temp[0]=='E')
{
outp << temp << '\n';
}
}
inp.close();

cout << "Done. Close window.";
int end;
cin >> end;
return 0;
}


If I replace "outp" with cout... it works fine. Otherwise, it only lists the first 2900 parts (sometimes 2950,2943,etc.. it varies)... I don't understand why it does this, can somebody please give me suggestions? Thank you!!
This was to be my original response. I had been called away to put the kids and the chickens to bed...

Your "combined.txt" file is corrupted, or there is more to your program than listed. Are you testing on the exact same file each time? How is it generated? Are you sure that each record has exactly 14 lines? Are you sure that the header for each line always starts with a capital P, N, or E? You aren't using seekg() or anything like that on your file?

Here is a revised response. It works over the standard streams and formats the output the same way you would like it, excepting using spaces instead of tabs to separate the information. (I assumed that the output is meant to be primarily human-readable, as opposed to machine-readable/tab-delimited.) The code itself is complicated only slightly by some error checking -- which is fine, since it is much less error-prone than the original.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <algorithm>
#include <cctype>
#include <iomanip>
#include <iostream>
#include <string>
using namespace std;

//----------------------------------------------------------------------------
bool ci_equal( char a, char b )
  {
  return tolower( a ) == tolower( b );
  }

bool ci_begins( const string& pattern, const string& s )
  {
  return (pattern.length() <= s.length())
      && equal( pattern.begin(), pattern.end(), s.begin(), ci_equal );
  }

//----------------------------------------------------------------------------
#ifdef __WIN32__
  #include <windows.h>
  bool cin_is_a_human()
    {
    DWORD mode;
    return GetConsoleMode( GetStdHandle( STD_INPUT_HANDLE ), &mode );
    }
#else
  #include <unistd.h>
  bool cin_is_a_human()
    {
    return isatty( 0 );
    }
#endif

//----------------------------------------------------------------------------
string substr( const string& s, string::size_type pos )
  {
  string result = s.substr( pos );
  result.erase( 0, result.find_first_not_of( " \n" ) );
  return result;
  }

//----------------------------------------------------------------------------
int main( int argc, char** argv )
  {
  if (cin_is_a_human())
    {
    cerr << "usage:\n"
            "  " << argv[ 0 ] << " < combined.txt > output.txt\n\n";
    return 1;
    }

  cout << left;

  string s;
  while (getline( cin, s ))
    {
    if (ci_begins( "PartID:", s ))
      try
        {
        cout << "PartID: " << setw( 7 ) << substr( s, 7 ) << " ";

        getline( cin, s );
        if (!ci_begins( "NumAvailable:", s )) throw 0;
        cout << "NumAvailable: " << setw( 9 ) << substr( s, 13 ) << " ";

        getline( cin, s );
        if (!ci_begins( "ExpectedDate:", s )) throw 0;
        cout << "ExpectedDate: " << substr( s, 13 ) << "\n";
        }
      catch (...)
        {
        cout << "...incomplete record\n";
        }
    }

  return 0;
  }

You will notice that it checks that the file is indeed properly-formatted (lines 65 and 69), and that it does not require user-input to indicate the number of records in the input file. Missing field data is ignored (though checks for that could be added).

Use it thus:
foo.exe < combined.txt > output.txt

Enjoy.
Topic archived. No new replies allowed.