Link to home
Start Free TrialLog in
Avatar of shaolinfunk
shaolinfunkFlag for United States of America

asked on

How do I store a valid filepath, so that I can retrieve it later?

Ok, I am trying to write a program that goes back in time one day at a time.  I have a database where whenever there is data available for that day it would be located at C:\2010\4\1\ABC.txt.  Given that today is 4/2 the program looks back to yseterday to see if ABC.txt exists for 4/1, then 3/31, then 3/30..etc...for up to 9 days.

On line 117...I do not know how to keep track of valid FilePaths ie there exists an ABC.txt file for that day.  How do I make a list of valid FilePaths that I can call on later?

Thanks for your help!
#include <time.h>
#include <stdio.h>
#include <string>
#include <fstream>
//#include <afx.h>

using namespace std;

unsigned short GetTodaysDate(unsigned short &year, unsigned short &month, unsigned short &day)
{
	time_t rawtime;        //rawtime is variable of data type time_t, related to time.h
    struct tm * timeinfo; //timeinfo points to a struct of type tm, related to time.h
    char str[60];

    rawtime = time (NULL); //retrieves number of seconds from 1/1/70, in GMT, stores in address of rawtime
    timeinfo = localtime ( &rawtime ); //localtime takes rawtime, and creates a "tm" struct

   strftime(str, sizeof(str) , "%Y %m %d", timeinfo);  //formats the timeinfo struct into a string
//   printf(str);                                                       //outputs string to let me see if date is right
   
   year = atoi(&str[0]);   
   month = atoi(&str[5]);
   day = atoi(&str[8]);

   return (year, month, day);
}


string FindOneDayEarlier(unsigned short &year, unsigned short &month, unsigned short &day)
{
//months with 31 days: 1, 3, 5, 7, 8, 10, 12
//months with 30 days: 4, 6, 9, 11
//months with 28/29 days: 2

	day = day - 1; //decrement the day

    if (day == 0) //if day = 0, today must be 1st of the month
	{    
			if (month == 2 || month == 4 || month == 6 || month == 8 || month == 9 || month == 11 || month == 1)
			{
				day = 31;
			}

			if (month == 5 || month == 7 || month == 10 || month == 12)
			{
				day = 30;
			}
			if (month == 3)  //if not a leap year, who cares, just search, find nothing, skip, and decrement to 28
			{
				day = 29;
			}


			month = month - 1;
			if (month == 0)  //if this month is Jan, prior month will be Dec.
			{
				month = 12;  //if we are in Dec., we must be in prior year...so...
				year = year - 1; //we will never count back before year 2000, so it's always positive
			}
    }

   char buffer[40];
   sprintf( buffer, "C:\\\\%d\\\\%d\\\\%d\\\\ABC.txt", year, month, day);

   return string(buffer);
}

bool FileExist( string strFilepath )
{
     
    // ifstream is used for reading files
	ifstream inf( strFilepath.c_str() );

    // If we couldn't open the output file stream for reading
    if (!inf)
    {
        return false;
    }
	else
		return true;
	    
}


/* only works with MFC...must remember to "#include <afx.h>"
bool FileExist2( string strPath )
{
        CFileFind ff;

        return FALSE != ff.FindFile( strPath ); //return false 
}
*/


int main()
{
// Get TODAY's date  
   unsigned short year = 0;
   unsigned short month = 0;
   unsigned short day = 0;

	GetTodaysDate (year, month, day);
   
// Given today's date, get YESTERDAY's date in string form to be used in a file path
	string strFilepath;
	int intNumDaystoLookBack = 9;
	int intCount = 0;

	do
	{
		strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
		if (FileExist(strFilepath))
		{
			intCount = intCount + 1;
// How do I make note of the filepath and store it...for future use?

		}
	}while (intCount <= intNumDaystoLookBack);


    return 0;
}

Open in new window

Avatar of shaolinfunk
shaolinfunk
Flag of United States of America image

ASKER

I realize my question may be poorly or sparsely worded.  If there's something I neglected to elaborate on please ask me for clarification?
Avatar of jkr
That is you want to store it for the next time your program runs?
Oh, what I meant was....my next stop after I store the list of valid filepaths somehow...is to read and go through this list of valid filepaths....read the file that the filepaths refer to...and store the contents of the file iinto a giant string.  This will occur during program execution...not the next time my program runs.

stop = step
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Crap, vectors are waaay over my head.  is there a simpler way to do this? let me explain....

I am not a programmer, but someone who realizes he can make his life simpler by writing a small program to automate a very repetitive task.  My goal is to achieve basic functionality with as little time invested as possible.  I bought Ivar Horton's Beginning Visual C++ 2008 and read up to Chapter 4.  I wrote some code and am now stuck.

Keep in mind I am a beginner, am not writing code for efficiency, speed, or elegance (yet).  I just want to get stuff done, and avoid as much as possible for now, the advanced stuff like pointers, references, arrays, etc...However, with Phoffric's and Infinity's help I am getting more comfortable with those concepts...

If it's absolutely unavoidable to use a vector to solve my problem please let me know...
I just looked up vectors...Chapter 10...I'm only on Chapter 5 right now...:(
OH, so how many recent paths do you want to store? If it is just the last one you processed, you could also do that like
int main()
{
// Get TODAY's date  
   unsigned short year = 0;
   unsigned short month = 0;
   unsigned short day = 0;

   vector<string> vFilePaths;

        GetTodaysDate (year, month, day);
   
// Given today's date, get YESTERDAY's date in string form to be used in a file path
        string strFilepath;
        string strPrevFilepath;
        int intNumDaystoLookBack = 9;
        int intCount = 0;

        do
        {
                strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
                if (FileExist(strFilepath))
                {
                        intCount = intCount + 1;
                        strPrevFilePath = strFilePath;
                }
        }while (intCount <= intNumDaystoLookBack);


    return 0;
}

Open in new window

I don't know in advance how many valid filepaths there are....I just know that in counting back X number of days I want to keep track (maybe in an array?) whenever there is a valid filepath...after I'm done going back X number of days I will then know by the size of the array how many valid filepaths there were...

To answer your question, I don't know the # in advance.  And I want more than just the last one if there are more than two valid filepaths in the last X days (here X = 9).  
If you don't know how many paths you have to deal with, a vector would indeed be the cleanest solution. And they're pretty easy to handle, you can acess elments via their index, e.g. like

string strOlderPath0 = vFilePaths[0];
string strOlderPath1 = vFilePaths[1];
string strOlderPath2 = vFilePaths[2];

// etc.
Instead of the cleanest, most elegant solution is there a simpler, less efficient, and slower solution?  

I can't stress enough that I don't have a computer programming background, and I am nowhere near the chapter on vectors in my book.  How about arrays?  I think I understand arrays a little bit.
In other words, I need to dumb it down and use more rudimentary concepts ie stuff that I have covered in the beginning chapters of a teach-yourself, self-help C++ book.  While I appreciate your answers they are beyond the scope of my understanding (as basic as it is).
>>Instead of the cleanest, most elegant solution is there a simpler, less
>>efficient, and slower solution?

In this case: Not really. Unless you have a limit of how many previous paths you want to store, where you could just use a regular array of strings. If you'd e.g. be able to say "well, there's for sure not going to be any more like 1000" (just as a ballpark figure), you could use

string asFilePaths[1000];

but be sure to check that you don't attempt to store or access more.
Ok...is there no way to dynamically resize the array on the fly, and as needed?

Or is there some equivalent of MFC's CStringArray?

If not, I will implement your code...but can you explain what is going in line 120:                         vFilePaths.push_back(strFilePath);?
Also, when compiling your code I get this error...What am I doing wrong?
#include <time.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
//#include <afx.h>


using namespace std;


unsigned short GetTodaysDate(unsigned short &year, unsigned short &month, unsigned short &day)
{
	time_t rawtime;        //rawtime is variable of data type time_t, related to time.h
    struct tm * timeinfo; //timeinfo points to a struct of type tm, related to time.h
    char str[60];

    rawtime = time (NULL); //retrieves number of seconds from 1/1/70, in GMT, stores in address of rawtime
    timeinfo = localtime ( &rawtime ); //localtime takes rawtime, and creates a "tm" struct

   strftime(str, sizeof(str) , "%Y %m %d", timeinfo);  //formats the timeinfo struct into a string
//   printf(str);                                                       //outputs string to let me see if date is right
   
   year = atoi(&str[0]);   
   month = atoi(&str[5]);
   day = atoi(&str[8]);

   return (year, month, day);
}


string FindOneDayEarlier(unsigned short &year, unsigned short &month, unsigned short &day)
{
//months with 31 days: 1, 3, 5, 7, 8, 10, 12
//months with 30 days: 4, 6, 9, 11
//months with 28/29 days: 2

	day = day - 1; //decrement the day

    if (day == 0) //if day = 0, today must be 1st of the month
	{    
			if (month == 2 || month == 4 || month == 6 || month == 8 || month == 9 || month == 11 || month == 1)
			{
				day = 31;
			}

			if (month == 5 || month == 7 || month == 10 || month == 12)
			{
				day = 30;
			}
			if (month == 3)  //if not a leap year, who cares, just search, find nothing, skip, and decrement to 28
			{
				day = 29;
			}

			month = month - 1;
			if (month == 0)  //if this month is Jan, prior month will be Dec.
			{
				month = 12;  //if we are in Dec., we must be in prior year...so...
				year = year - 1; //we will never count back before year 2000, so it's always positive
			}
    }

   char buffer[40];
   sprintf( buffer, "C:\\\\%d\\\\%d\\\\%d\\\\ABC.txt", year, month, day);

   return string(buffer);
}


bool FileExist( string strFilepath )
{     
    // ifstream is used for reading files
	ifstream inf( strFilepath.c_str() );

    // If we couldn't open the output file stream for reading
    if (!inf)
    {
        return false;
    }
	else
		return true;	    
}


int main()
{
// Get TODAY's date  
   unsigned short year = 0;
   unsigned short month = 0;
   unsigned short day = 0;

	GetTodaysDate (year, month, day);
   
// Given today's date, get YESTERDAY's date in string form to be used in a file path
// then loop through past 9 days, and find out if filepath for each day is valid, or not
// if filepath is valid, save in a vector
	string strFilepath;
	int intNumDaystoLookBack = 9;
	int intCount = 0;  
	vector<string> vFilePaths;

	do
	{
		strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
		if (FileExist(strFilepath))
		{
			intCount = intCount + 1;
            vFilePaths.push_back(strFilePath); // make note of the filepath and store it for future use
		}
	}while (intCount <= intNumDaystoLookBack);


    return 0;
}




1>------ Rebuild All started: Project: junk, Configuration: Debug Win32 ------
1>Deleting intermediate and output files for project 'junk', configuration 'Debug|Win32'
1>Compiling...
1>Junk.cpp
1>c:\documents and settings\administrator\desktop\junk\junk\junk.cpp(111) : error C2065: 'strFilePath' : undeclared identifier
1>Build log was saved at "file://c:\Documents and Settings\Administrator\Desktop\junk\junk\Debug\BuildLog.htm"
1>junk - 1 error(s), 0 warning(s)
========== Rebuild All: 0 succeeded, 1 failed, 0 skipped ==========

Open in new window

Sorry, typo on my side - that should be

            vFilePaths.push_back(strFilepath); // make note of the filepath and store it for future use

and not 'strFilePath'...
>>Or is there some equivalent of MFC's CStringArray?

A 'std::vector' is pretty much the same, but even better ;o)
wow, i didn't realize the capital "P" made a difference.  thanks for the catch!
Thanks jkr, this has been extremely helpful!
Since I'm now using vectors...can you show me how to put this stuff we just made into a function that i can call from the main function?

I know we want to pass into said function the values for year,month,day, and have returned a vector of all the valid filepaths but I have no idea how to return a vector....

Let's call this function GetValidFilePaths and have it contain the code below.  What else do I need to add?



GetValidFilePaths (year, month, day)
{

// Given today's date, get YESTERDAY's date in string form to be used in a file path
// then loop through past 9 days, and find out if filepath for each day is valid, or not
// if filepath is valid, save in a vector
	string strFilepath;
	int intNumDaystoLookBack = 9;
	int intCount = 0;  
	vector<string> vFilePaths;

	do
	{
		strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
		if (FileExist(strFilepath))
		{
			intCount = intCount + 1;
            vFilePaths.push_back(strFilepath); // make note of the filepath and store it for future use
		}
	}while (intCount <= intNumDaystoLookBack);

}

Open in new window

Well, you could indeed have hat funcion return a vector, but it's easier to pass in a reference to a vector, e.g.
void GetValidFilePaths (unsigned short year, unsigned short month, unsigned short day, vector<string>& vFilePaths)
{

// Given today's date, get YESTERDAY's date in string form to be used in a file path
// then loop through past 9 days, and find out if filepath for each day is valid, or not
// if filepath is valid, save in a vector
	string strFilepath;
	int intNumDaystoLookBack = 9;
	int intCount = 0;  

	do
	{
		strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
		if (FileExist(strFilepath))
		{
			intCount = intCount + 1;
            vFilePaths.push_back(strFilepath); // make note of the filepath and store it for future use
		}
	}while (intCount <= intNumDaystoLookBack);

}

Open in new window

Ok, I don't know what a hat and I have a vague idea of what a reference is.  

The code compiled successfully, but can you tell me if I called the function correctly in the main function?  Or do I need to use an & somewhere?
#include <time.h>
#include <stdio.h>
#include <string>
#include <vector>
#include <fstream>
//#include <afx.h>


using namespace std;


unsigned short GetTodaysDate(unsigned short &year, unsigned short &month, unsigned short &day)
{
	time_t rawtime;        //rawtime is variable of data type time_t, related to time.h
    struct tm * timeinfo; //timeinfo points to a struct of type tm, related to time.h
    char str[60];

    rawtime = time (NULL); //retrieves number of seconds from 1/1/70, in GMT, stores in address of rawtime
    timeinfo = localtime ( &rawtime ); //localtime takes rawtime, and creates a "tm" struct

   strftime(str, sizeof(str) , "%Y %m %d", timeinfo);  //formats the timeinfo struct into a string
//   printf(str);                                                       //outputs string to let me see if date is right
   
   year = atoi(&str[0]);   
   month = atoi(&str[5]);
   day = atoi(&str[8]);

   return (year, month, day);
}


string FindOneDayEarlier(unsigned short &year, unsigned short &month, unsigned short &day)
{
//months with 31 days: 1, 3, 5, 7, 8, 10, 12
//months with 30 days: 4, 6, 9, 11
//months with 28/29 days: 2

	day = day - 1; //decrement the day

    if (day == 0) //if day = 0, today must be 1st of the month
	{    
			if (month == 2 || month == 4 || month == 6 || month == 8 || month == 9 || month == 11 || month == 1)
			{
				day = 31;
			}

			if (month == 5 || month == 7 || month == 10 || month == 12)
			{
				day = 30;
			}
			if (month == 3)  //if not a leap year, who cares, just search, find nothing, skip, and decrement to 28
			{
				day = 29;
			}

			month = month - 1;
			if (month == 0)  //if this month is Jan, prior month will be Dec.
			{
				month = 12;  //if we are in Dec., we must be in prior year...so...
				year = year - 1; //we will never count back before year 2000, so it's always positive
			}
    }

   char buffer[40];
   sprintf( buffer, "C:\\\\%d\\\\%d\\\\%d\\\\ABC.txt", year, month, day);

   return string(buffer);
}


bool FileExist( string strFilepath )
{     
    // ifstream is used for reading files
	ifstream inf( strFilepath.c_str() );

    // If we couldn't open the output file stream for reading
    if (!inf)
    {
        return false;
    }
	else
		return true;	    
}

void GetValidFilepaths(unsigned short year, unsigned short month, unsigned short day, vector<string>& vFilePaths)
{

// Given today's date, get YESTERDAY's date in string form to be used in a file path
// then loop through past 9 days, and find out if filepath for each day is valid, or not
// if filepath is valid, save in a vector
	string strFilepath;
	int intNumDaystoLookBack = 9;
	int intCount = 0;  


	do
	{
		strFilepath = FindOneDayEarlier(year, month, day);//goes back in time, 1 day at a time

//  Given the FilePath for yesterday's date, find out if the Example.txt file exists
		if (FileExist(strFilepath))
		{
			intCount = intCount + 1;
            vFilePaths.push_back(strFilepath); // make note of the filepath and store it for future use
		}
	}while (intCount <= intNumDaystoLookBack);

}

int main()
{
// Get TODAY's date  
   unsigned short year = 0;
   unsigned short month = 0;
   unsigned short day = 0;

	GetTodaysDate (year, month, day);

	vector<string> vFilePaths;
    GetValidFilepaths (year, month, day, vFilePaths);

    return 0;
}

Open in new window

Avatar of phoffric
phoffric

@shaolinfunk,
If you are moving onto Chapter 5, then no doubt you have master chapter 4 (pointers, right?) But, nevertheless, I highly recommend that you watch the last 10 minutes of the following movie (starting at 35:30, immediately after the recursion discussion)
    http://www.academicearth.org/lectures/backtracking-pseudocode
and then watch the next 41 minutes of:
    http://www.academicearth.org/lectures/pointer-movie
and then watch now (or later) the use of pointers for a linked-list:
    http://www.academicearth.org/lectures/coding-with-linked-list
Ok, I will watch those now.....in the meantime I'm trying to implement the read file function you helped me with earlier in conjunction with jkr's vectors...but it doesn't seem to work...see here:

https://www.experts-exchange.com/questions/25668401/Why-can't-I-open-read-files-with-this-code.html?anchorAnswerId=29502771#a29502771
If you have firefox and the downloader add-on, that works well with this site. Otherwise, I think they limit you to 2 at a time. There's another trick with downloading from there I've noticed. They do a nice burst initially to get the buffers filled (even for downloads). So, if you're getting impatient, you can pause, exit, and start again for another burst.
I had been letting it buffer in the background...I am done watching the first one...now waiting on second one.  Thanks.
If you have questions on these movies, you can ask, but give the link and the MM:SS-MM:SS range. If you turn off the sound, the instructor appears to be an orchestra conductor.
Lol...ok.