How to decide when to end my while loop when it runs 1 too long

My code is supposed to read a text doc and organize the string chunks, then run an error checker and print out everything in a specific way. Currently all works except for timestamp. Sometimes, in the .txt file, there will be no timestamp in a line (it will just be missing)


Previously, my variable would just remain the same as the prior value and it would cause errors so I reset my time stamp at the beginning of every string stream declaration for it.

This is what's causing the actual issue. Now that it's zero, it will pass the test again and my program ends up printing 1 additional "Error parsing" line.

I need some way to end the while loop earlier or maybe a way to clear a variable to a null value? I'm not sure.. any help would be appreciated.


Ps. This will not run on here, it needs a .txt file




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
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
  

************************************************************************/

#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
using namespace std;
#include <stdlib.h>
//#include <regex>



/**********************************************************************
* This is the struct skeleton
***********************************************************************/
struct AccessRecord
{
   string username;
   string filename;
   long timestamp;
};

/**********************************************************************
* 
***********************************************************************/
void getFileName(string &fileName)
{
   cout << "Enter the access record file: ";
   getline(cin, fileName);



}

void getTimeStamp(long &startTime, long &endTime)
{
   cout << "\nEnter the start time: ";
   cin >> startTime;
   cout << "Enter the end time: ";
   cin >> endTime;
}




bool isValidFilename(string fileName)
{

   if (fileName.find(".") == string::npos)
   {
      
      return false;
   }
   else
   {
     
      return true;
   }









}

bool isValidUsername(string username)
{
   //return true;
   return isalpha(username[0]);
}


bool isValidTimestamp(long timestamp )
{
   

  

   if (timestamp >= 1000000000 && timestamp <= 10000000000)
   {
         return true;
   }
   
   
   else 
   { 
      return false;
   }
}






/**********************************************************************
*
***********************************************************************/
void readFile(string &fileName, AccessRecord entry[])
{
   ifstream myFile(fileName.c_str());
   string testline;
   stringstream ss;
   int i = 0;
   string tempFileName;
   string tempUserName;
   long tempTimestamp;
   
   



   while (myFile.good())
   {
      
     
      getline(myFile, testline);

      ss.str(testline);
      
      
      ss >> tempFileName;

      
      if (isValidFilename(tempFileName))
      {
         
         ss >> tempUserName;


         if (isValidUsername(tempUserName))
         {
            tempTimestamp = 0;
            ss >> tempTimestamp;

            if (isValidTimestamp(tempTimestamp))
            {
               entry[i].filename = tempFileName;
               entry[i].username = tempUserName;
               entry[i].timestamp = tempTimestamp;

            }
            else
            {
               
               cout << "Error parsing line: " << testline << "\n";
               
             

            }
         }
         else
         {
            cout << "Error parsing line: " << testline << "\n";
            
         }
      }

      else
      {
         cout << "Error parsing line: " << testline << "\n";
         
      }

      
      i++;
      
      ss.clear();
     
    
   }
}




/**********************************************************************
*
***********************************************************************/
void printDisplay(AccessRecord entry[], long startTime, long endTime)
{
   cout << "\n      Timestamp                File                User\n";
   cout << "--------------- ------------------- -------------------";
   cout << endl;



   for (int p = 0; p < 15; p++)
   {
      if ((entry[p].timestamp < endTime) && (entry[p].timestamp >
         startTime))
      {
         cout << setw(15) << entry[p].timestamp << setw(20) <<
            entry[p].filename << setw(20) << entry[p].username << "\n";
      }
   }
}



/**********************************************************************
* 
***********************************************************************/
int main()
{



   string fileName = "null";


   long startTime;
   long endTime;



   AccessRecord entry[500];
   getFileName(fileName);

   readFile(fileName, entry);

   getTimeStamp(startTime, endTime);

   cout << "\nThe following records match your criteria:\n";



   printDisplay(entry, startTime, endTime);
   cout << "End of records";
   cout << endl;

   string wait;
   cin >> wait;
   return 0;
}


/*regex pattern(".*\\....");
return regex_match(fileName, pattern);*/
/*{
cout << fileName << " good";
return true;
}

cout << fileName << " bad ";

return false;*/
Last edited on
I don't see any advantage in using a weird indentation like 3. Is 4 really too much? It is FAR more common.

Anyway, are you saying that a missing time stamp IS an error, or ISN'T an error?

You aren't controlling your input loop properly. You should test the actual input function itself. I haven't tested this but I think your current code can be rewritten like this.
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
80
81
82
83
84
85
#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <string>
//#include <regex>
#include <cstdlib>     // this is how you include C headers in C++
using namespace std;

struct AccessRecord {
    string username;
    string filename;
    long timestamp;
};

void getFileName(string &fileName) {
    cout << "Enter the access record file: ";
    getline(cin, fileName);
}

void getTimeStamp(long &startTime, long &endTime) {
    cout << "\nEnter the start time: ";
    cin >> startTime;
    cout << "Enter the end time: ";
    cin >> endTime;
}

bool isValidFilename(string fileName) {
    return fileName.find(".") != string::npos;
}

bool isValidUsername(string username) {
    return isalpha(username[0]);
}

bool isValidTimestamp(long timestamp) {
    return timestamp >= 1000000000 && timestamp <= 10000000000;
}

void readFile(string &fileName, AccessRecord entry[]) {
    ifstream myFile(fileName.c_str());
    string testline;
    for (int i = 0; getline(myFile, testline); i++) {
        istringstream ss(testline);
        string tempFileName;
        string tempUserName;
        long tempTimestamp = 0;
        ss >> tempFileName >> tempUserName >> tempTimestamp;
        if (isValidFilename(tempFileName) &&
             isValidUsername(tempUserName) &&
             isValidTimestamp(tempTimestamp)) {
             entry[i].filename = tempFileName;
             entry[i].username = tempUserName;
             entry[i].timestamp = tempTimestamp;
        }
        else
            cout << "Error parsing line: " << testline << '\n';
    }
}

void printDisplay(AccessRecord entry[], long startTime, long endTime) {
    cout << "\n      Timestamp                File                User\n";
    cout << "--------------- ------------------- -------------------\n";
    for (int p = 0; p < 15; p++)
        if (entry[p].timestamp < endTime && entry[p].timestamp > startTime)
            cout << setw(15) << entry[p].timestamp
                 << setw(20) << entry[p].filename
                 << setw(20) << entry[p].username << '\n';
}

int main() {
    AccessRecord entry[500];
    string fileName;
    long startTime;
    long endTime;

    getFileName(fileName);
    readFile(fileName, entry);
    getTimeStamp(startTime, endTime);
    cout << "\nThe following records match your criteria:\n";
    printDisplay(entry, startTime, endTime);
    cout << "End of records\n";

    return 0;
}

Last edited on
Thanks for the help.. I fixed this problem a week or so ago and found that the notepad I was reading had an extra line in it causing the program to iterate 1 extra time.

Also, I prefer to indent 4 but my school has a testbed software that requires all indentation to be at 3.

Thanks for your help here. This still seems like it might be useful to someone so I will leave this here instead of deleting it.
Also, I prefer to indent 4 but my school has a testbed software that requires all indentation to be at 3.

I am afraid of what that software's code looks like. Deeply afraid.

Thanks for your help here. This still seems like it might be useful to someone so I will leave this here instead of deleting it.

Thank you for being considerate! Good luck with your coding.
Topic archived. No new replies allowed.