I am debugging a function and as usual I always dump the memory to check if the address of a variable that I used actually contains the correct data.
Anyway, I do the same thing when I assign a file to a file pointer variable. in my function I opened the file mFile1.txt. and in the "watch1" window it show
-fileNames[0] 0x004e4b02 "mFile1.txt" char * const |
So I can say that fileNames[0] and "mFiles1.txt" are one and the same.
Then I went to the "command window" and display the first 32 bytes pointed by the address "0x4e4b02" using the command "db /count:32 0x4e4b02". This 32 bytes represents the first 32 bytes contents of the file.
and this is what I got. what it constains is something I am not interested, I only want to be sure there is something in it to read and display.
>db /count:32 0x004e4b02
0x004E4B02 6d 46 69 6c 65 31 2e 74 78 74 00 6d 46 69 6c 65
0x004E4B12 32 2e 74 78 74 00 6d 46 69 6c 65 33 2e 74 78 74 |
Then a declare a variable "ret" of type (ifstream which has an address of "0x004e4b7c" in the "watch1 window". if you notice there is a prefix "+" on variable "ret" indication that I could expand it and see the entire class.
+ret 0x004e4b7c {_Filebuffer={...} } std::basic_ifstream<char,std::char_traits<char> > * |
then on the command window I dump the first 32bytes starting from that address.
>db /count:32 0x004e4b7c
0x004E4B7C 9c 09 f1 00 cd cd cd cd 00 00 00 00 00 00 00 00
0x004E4B8C ac 09 f1 00 68 4f 4e 00 00 00 00 00 00 00 00 00 |
the first four bytes in the dumps memory of address 0x004e4b7c is an address
0x00f1099c so I also look on that memory location.
db /count:32 0x00f1099c
0x00F1099C 00 00 00 00 68 00 00 00 00 00 00 00 64 1e f1 00
0x00F109AC 92 14 f0 00 fa 15 f0 00 37 15 f0 00 67 12 f0 00 |
I have ran this program and it is working correctly so "ret" must be pointing to the correct file.
Since "ret" is related to "fileNames[0] somewhere in the dumped memory of ret, I should find the address of fileNames[0]. This is a concern to me because I do not have anything that I could tie "ret" and the file name "mFile1.txt". Making the program run correctly is OK to me but I want fool proof that will tell me that the two variables are related.
My question is in the watch1 window where would I find the address of mFile1.txt under the name "ret"? If I expand "ret" where would I go? I am attaching the main program and the functions for your perusal.please note that the main requires 5 arguments which are file names, those files should be existing if you want to run the program. If not the program will terminate gracefully without executing the main code.
MAIN PROGRAM:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
|
#include <cstdlib>
#include <iostream>
#include <fstream>
using namespace std;
ifstream *OpenFiles(char * const fileNames[], size_t count);
void MergeAndDisplay(ifstream files[], size_t count);
int main(int argc, char *argv[])
{
const int FILE_NAME1_ARG_NO = 1; // command line arg: first file name
ifstream *files = OpenFiles(&argv[FILE_NAME1_ARG_NO], size_t(argc - 1));
MergeAndDisplay(files, size_t(argc - 1));
delete[] files;
cin.get();
return EXIT_SUCCESS;
}
#endif
|
FUNCTIONS CALLED BY THE MAIN.
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
|
#include <fstream>
#include <iostream>
using namespace std;
//Constant Declaration global to this file
const int SIZE_OF_IFSTREAM = 5;
const int SIZE_OF_CHAR_STORAGE = 16;
const char EMPTY[] = "";
// Open files as per specification as describe on the title above
ifstream *OpenFiles(char * const fileNames[], size_t count)
{
//Variable declaration and initialization of ifstream pointer and
//dynamically allocate memory
ifstream *ret = new ifstream[count];
// If no command line arguments, error and exit we compared the count to 1 instead of 0
// because the executable is argument #1 which should always be there.
if (count <= 1)
{
cerr << "There is no arguments.\n";
//display message and wait for response before exiting
cin.get();
exit(EXIT_FAILURE);
}
//opens the files in the main program arguments
int loopCount;
int filecntr = (int)count;
while (--filecntr >= 0)
{
//open the file in a read optional second argument
ret[filecntr].open(fileNames[filecntr]);
//if any of the files fails to open close all the files and exit
if (!ret[filecntr].is_open())
{
cerr << "Failed to open " << fileNames[count] << "\n";
for (loopCount = --filecntr; loopCount >= 0; loopCount--)
{
ret[loopCount].close();
cout << "Closed " << fileNames[loopCount] << "\n";
count = 0;
}
}
}
return ret;
}
// Obtain string in one line of each file and display those 1 line per file
void MergeAndDisplay(ifstream files[], size_t count)
{
// function variable declaration
char fileOneLine[SIZE_OF_CHAR_STORAGE];
bool fileisEmpty[SIZE_OF_IFSTREAM], allFilesClosed = false;
unsigned int boolCntr;
//Initialize the file "empty flag"
for (boolCntr = 0; boolCntr < count; boolCntr++)
fileisEmpty[boolCntr] = false;
//Enter the title of the table
cout << "The Display Would Be\n\n";
//get the data from each file and display it.
//for (unsigned int lineCntr = 1; !allFilesClosed; ++lineCntr)
while (!allFilesClosed)
{
//processing only one line of each file
for (unsigned int fileCntr = 0; fileCntr < count; ++fileCntr)
{
//when the file has been closed it is no longer used and only the remaining files are process
if (fileisEmpty[fileCntr])
continue;
//obtain the line of each file and store it in a character storage to be process.
files[fileCntr].getline(fileOneLine, SIZE_OF_CHAR_STORAGE, '\n');
//process this when the line read in the file is empty
if (strcmp(fileOneLine, EMPTY))
cout << fileOneLine << '\n';
else
//when the line is empty, it is assumed to have reached the EOF and this section is executed
//only once for the same file
if (!fileisEmpty[fileCntr])
{
files[fileCntr].close();
fileisEmpty[fileCntr] = true;
}
}
//exit the process when all files are closed
allFilesClosed = true;
//check if all the files are closed, if it is exit the program
for (boolCntr = 0; boolCntr < count; boolCntr++)
if (!fileisEmpty[boolCntr])
allFilesClosed = false;
}
return;
}
|