How do I write a loop that has an unkown end?

I have been programming part time for about a month now so if you reply and I dont understand , please bare with me! I have written a program that will read a text file , grab some lines , do some maths and spit out what it needs to, it loads the text files in sequential order.

Example: file1.txt, file2.txt, file3.txt, file4.txt,

I fstream the first file grab the data I need sling it into multiple variables , close the text file and open the next.

This is done in a for loop.

1
2
3
4
for (int i = 0, i < 4, i++
{
all my code
}


This works great and im very happy with it, but obviously I only have 4 files here so the loop grabs all 4 and its done. What happens when I dont know how many files I have? say I have 1,000 files my code inside the loop will be fine as im using arrays to store each loop of data but I dont know how to write a loop that says keep looping until it finds the end (either by date of the file or finding no great file number?) or just to keep looping until asked to stop ?

This is all written in console just for me to work out the logic before I put it into UI.

Cheers.
1
2
3
4
5
6
7
8
9
10
11
12
int i = 1;
bool EndFile = false;
while(!EndFile)
{
/*openfile 'i', put data in ect.*/
i++;
if(/*check if this is the last file*/)
{
EndFile = true;
};

}


I think this should work but I don't know how you want to check if the file is the last one you want to check.
I don't think there is any simple way to do it if you don't know how many files there are, or what they are called. If they are all in the same folder, and only those files are in the folder, you can do it like this (though it is complicated, and requires you to be running Windows):

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
#include <windows.h>
#include <tchar.h>

#include <iostream>

int main() {
    TCHAR sPath[] = _T(".\\foldername"); //Insert the target folder's name

    HANDLE hFind; // file handle
    WIN32_FIND_DATA FindFileData;

    TCHAR DirectoryPath[MAX_PATH];
    TCHAR Filename[MAX_PATH];

    _tcscpy(DirectoryPath,sPath);
    _tcscat(DirectoryPath,_T("\\"));
    _tcscpy(Filename,sPath);
    _tcscat(Filename,_T("\\*")); //Searching all files

    hFind = FindFirstFile(Filename, &FindFileData); //Find the first file

    if(hFind != INVALID_HANDLE_VALUE) {
        do {
            _tcscpy(Filename + _tcslen(DirectoryPath), FindFileData.cFileName);

            if(!(FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
                //File isn't a directory, you can do stuff now.

                //DO YOUR FILE FUNCTIONING HERE; E.g. (just outputting file name)
                std::cout << FindFileData.cFileName << std::endl;
            }
        } while (FindNextFile(hFind,&FindFileData) != 0); //Any more files?

        FindClose(hFind); //Closing file handle

        return 0;
    }

    return -1;
}


If you want to get the filename (for example) of the file you just found, the filename of the currently stored file is in FindFileData.cFileName.

If you're not running windows, this won't work, so you may as well not bother trying. If you are, and you have no idea what's going on here, then either you can look it up on MSDN or you can ask someone.
Hmm thanks for the response and I will try that as a failsafe if I cant get my loop working. I know what part of the files are called. All text files are named:

HH20130717Txxxxxxxxx.txt

The first part is just HH(date) that obviously changes daily and the Txxxxxxxxx part is just a random number that always increases (but not by any particular number).

So essentially I am just renaming them to HH1,HH2,HH3,HH4 for testing. but I want to be able to grab the filename of HH(todays date) read in the Txxxxxxxxx part too and loop until it cannot find a bigger number.

Hope thats a bit clearer :)
I have a solution for where the numbers might not be in order, but if you know there aren't any skipped numbers then you could set this up to run much quicker, and this program does have a maximum range, but that isn't a bad thing because otherwise you would have an infinite loop which would get you a frozen screen.

I can think of several ways that you could work this out differently, either have all the numbers be sequential (001, 002, 003, etc) <- most efficient, keep a record of the highest number that you reach and use that as the top of your range, save each filename that you create into a master .txt file which you could search through... or use NT3's example...

Delete the cout>>filename that is inside the first loop, it's only to show that the naming scheme is working, but the graphics slow down the run-time.

Also, right now I have the program opening the files using ifstream because it doesn't create a file when none exists, while ofstream does, so what you can do is use this setup to record what numbers on the files actually exist, then reuse those stored numbers when you start with ofstream.

You'll have to rework this code to figure in that part about today's date, I haven't worked in <time.h> or <locale.h> which is where I think you would get the date and time info.

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
#include <iostream>
#include <string>
#include <fstream>



using namespace std;
int incrementstring(string &num);
int main()
{

//for sequential files...
	string filename;
	string word1 = "File"; //set to whatever date format like "2013.07.18"
	string number = "0000"; // this is how you set the max range of numbers to search, 
                                             //More 0's means higher search range
	string extension = ".txt";

	filename = word1;
	filename += number;
	filename += extension;
	ifstream file; //you can use ifstream a a test since it doesn't automatically create a file if it isn't found.
					//if you need to use ofstream then record which number got a hit in the if(file.good()) block
	while(incrementstring(number)) 	
	{
		filename = word1;
		filename += number;
		filename += extension;
		file.open(filename);
		cout<<filename; //this runs much quicker without a cout in the loop,
						//I just want to show that the filename is running correctly.
		if(file.good())
		{
			
			 //File is good, which means it is both opened and exists
			
		}
		file.close();
	}

	int wait;
	cin>>wait;

}	

int incrementstring(string &num)//returns 0 if the num is at the max, can't be incremented
{
static string hold = num;
int len = num.length();
int count = len-1;
num[count]++;
while(count>0)
{
	
	if(num[count]>'9')
		{
			num[count] = '0';
			num[count-1]++;
		}

	count--;
	}
	if(num[0]>'9')
	{
		num[0] = 'h';
		return false;
	}
	else 
		return true;
}

I didn't try NT3's code, but since you said you haven't been coding for long I wanted to make sure you had a native C++ example that didn't have any Windows API. Follow NT3's example if you meant you have been dealing with Windows Programing for several months.
Last edited on
Yea I really have no experience with windows api, I am going to try your version and play around with it to see what I can come up with. Will post an update to see how it goes!
Yea that works good! thanks :) , but.. due to the naming convention of the text files I realised it will be way quicker just to load everything in the folder (or from a certain date within the folder) I think that will be easy enough but I am not sure on how I would be able to keep adding new ones so say for example I had button on the UI called "start"

it grabs all the info from the text files and stores them in their respective arrays, but 10 mins later a new file is put into the folder I want that file to be calculated too without hitting "start" again, any ideas?
You're using only C++ and the console interface, right? Or do you have a graphical user interface like SFML?
What you're asking is possible and somewhat expected in Windows API, but I'm skeptical that it would be possible in an efficient manner for the regular console.

I'm assuming that the file is being placed in the folder by the user, so you could give them a refresh option that basically checks the folder for any new content... or before the program finishes do a final check for any new additions to that folder.

So are you using a graphical interface other than the console?
Last edited on
Im using console atm just for testing purposes and then I will make a UI for it later, hmm I need it to literally be off and on as the only options to be able to grab new text files.
OK, so if that's your plan, then I suggest making everything into functions, that way they will be easy enough to copy and past into a new code source. Right now you're going to have to settle for not being able to do everything because the console has its limits like not being able to automatically update itself.
When you start using a GUI you will be able to start putting those functions that you make in console programming into use as a larger program, but for now just try to make the bare-bones version.
Last edited on
Topic archived. No new replies allowed.