Hi there guys!

Just want to say these communities are great! i've really benefited alot from the forum and its tutorials. Special thanks to FireNet and his file handling tutorials. It really helped me alot! Not forgetting, thanks alot to all of the members here too. :idea: :cheesy:

anyway, ive got this assignent to finish off and are having problems with a small block of codes here.

class video
{

protected:

	struct videoData
	{
		char title[30];
		char star1[30];
		char star2[30];
		char producer[30];
		char director[30];
		char productionCo[30];
		int copiesInStock;
		int totalCopiesInStock;
	};

public:


//////[Modify Record]/////////////////////////////////////////////////////

	void modifyVideoList()
	{

		fstream file4;
		videoData fields;
		char titleTemp [30];

		int flag=0;

		cout<<"\t\n\nEnter title of video to search: \n";
		cin.getline(titleTemp,30);

		file4.open("videolist.dat", ios::app | ios::out | ios::in | ios::binary);
		file4.seekg(0, ios::beg);
		file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );

		while ( !file4.eof())
		{

				
			if(strcmp(fields.title,titleTemp)==0)
			{
				
				//Display old record information
				cout<< "\n\t::Displaying '" << fields.title << "'  information::\n";
				cout<< "Movie Title: " << fields.title <<endl;
				cout<< "Movie Star 1: " << fields.star1 <<endl;
				cout<< "Movie Star 2: " << fields.star2 <<endl;
				cout<< "Movie Producer: " << fields.producer <<endl;
				cout<< "Movie Director: " << fields.director <<endl;
				cout<< "Production Company: " << fields.productionCo <<endl;
				cout<< "Number of Copies In Stock: " << fields.copiesInStock <<endl;
				cout<< "Total Copies in Store: " << fields.totalCopiesInStock <<endl;

				cout<< "\n\n";

				//Enter new record information
				cout<< "\n\n"<<endl;
				cout<< "\t::Enter new information::\n"<<endl;

				cout<<"Video Title: ";
				cin.getline(fields.title, 30);

				cout<<"Movie Star 1: ";
				cin.getline(fields.star1, 30);

				cout<<"Movie Star 2: ";
				cin.getline(fields.star2, 30);

				cout<<"Movie Producer: ";
				cin.getline(fields.producer, 30);

				cout<<"Movie Director: ";
				cin.getline(fields.director, 30);

				cout<<"Production Company: ";
				cin.getline(fields.productionCo, 30);

				cout<<"Number of Copies in Stock: : ";
				cin>> fields.copiesInStock;

				cout<<"Total Copies in Store: ";
				cin>> fields.totalCopiesInStock;

				file4.seekp(0, ios::beg);
				file4.write( reinterpret_cast<char*>(&fields), sizeof(fields) );
				
		
			}
				file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );
			
		}

		if(flag==1)
		{
			cout<<"Video title not found!"<<endl;
			fflush(stdin);
		}

		cout<< "\nRecord has been updated!\n" <<endl;
		
		file4.close();
		system("Pause");
		system("Cls");


	}

what im trying to do here is to create a file handling database with add, display records and modify records for a video rental store. the problem here is the modify record section where i cant get any datas into my file.

can anyone help me with this? this block of codes are copied from my header file so if anyone needs the whole thing please tell me so. thanks alot! ;)

Member Avatar for iamthwee

Hi there guys!

Just want to say these communities are great! i've really benefited alot from the forum and its tutorials. Special thanks to FireNet and his file handling tutorials. It really helped me alot! Not forgetting, thanks alot to all of the members here too. :idea: :cheesy:

anyway, ive got this assignent to finish off and are having problems with a small block of codes here.

class video
{

protected:

	struct videoData
	{
		char title[30];
		char star1[30];
		char star2[30];
		char producer[30];
		char director[30];
		char productionCo[30];
		int copiesInStock;
		int totalCopiesInStock;
	};

public:


//////[Modify Record]/////////////////////////////////////////////////////

	void modifyVideoList()
	{

		fstream file4;
		videoData fields;
		char titleTemp [30];

		int flag=0;

		cout<<"\t\n\nEnter title of video to search: \n";
		cin.getline(titleTemp,30);

		file4.open("videolist.dat", ios::app | ios::out | ios::in | ios::binary);
		file4.seekg(0, ios::beg);
		file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );

		while ( !file4.eof())
		{

				
			if(strcmp(fields.title,titleTemp)==0)
			{
				
				//Display old record information
				cout<< "\n\t::Displaying '" << fields.title << "'  information::\n";
				cout<< "Movie Title: " << fields.title <<endl;
				cout<< "Movie Star 1: " << fields.star1 <<endl;
				cout<< "Movie Star 2: " << fields.star2 <<endl;
				cout<< "Movie Producer: " << fields.producer <<endl;
				cout<< "Movie Director: " << fields.director <<endl;
				cout<< "Production Company: " << fields.productionCo <<endl;
				cout<< "Number of Copies In Stock: " << fields.copiesInStock <<endl;
				cout<< "Total Copies in Store: " << fields.totalCopiesInStock <<endl;

				cout<< "\n\n";

				//Enter new record information
				cout<< "\n\n"<<endl;
				cout<< "\t::Enter new information::\n"<<endl;

				cout<<"Video Title: ";
				cin.getline(fields.title, 30);

				cout<<"Movie Star 1: ";
				cin.getline(fields.star1, 30);

				cout<<"Movie Star 2: ";
				cin.getline(fields.star2, 30);

				cout<<"Movie Producer: ";
				cin.getline(fields.producer, 30);

				cout<<"Movie Director: ";
				cin.getline(fields.director, 30);

				cout<<"Production Company: ";
				cin.getline(fields.productionCo, 30);

				cout<<"Number of Copies in Stock: : ";
				cin>> fields.copiesInStock;

				cout<<"Total Copies in Store: ";
				cin>> fields.totalCopiesInStock;

				file4.seekp(0, ios::beg);
				file4.write( reinterpret_cast<char*>(&fields), sizeof(fields) );
				
		
			}
				file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );
			
		}

		if(flag==1)
		{
			cout<<"Video title not found!"<<endl;
			fflush(stdin);
		}

		cout<< "\nRecord has been updated!\n" <<endl;
		
		file4.close();
		system("Pause");
		system("Cls");


	}

what im trying to do here is to create a file handling database with add, display records and modify records for a video rental store. the problem here is the modify record section where i cant get any datas into my file.

can anyone help me with this? this block of codes are copied from my header file so if anyone needs the whole thing please tell me so. thanks alot! ;)

I've not looked at your code properly, I'm only responding to the question about modifying lines in a text file.

This happens to be problematic, appending a text file is not.

It would require you to read the original file into memory, ammend the line/lines whilst still in memory, than write it over the original file. Me thinks :sad:

yah, i was thinking of that too. mabe what i can do is create another set of temporary variables as a temporary memory location, edit the temp location, then store the temp location overwriting the original location.

but im not so sure on which direction should i be looking at.

maybe a pseudocode from someone will do?

Here's a version using two files rather than holding the file contents in memory.

Mirror the original file contents to a temporary file.
Find the spot you want to change.
Write the correction to the temporary file.
write the rest of the original file to the temporary file.
rename the temporary file the same as the original.
delete the original file.

IF the correction has the same number of bytes as the original---for example you wanted to change the word cold to the word bold, then you could do something different. But if the correction isn't the exact same number of bytes, you need to do it the other way, tedious as it is.

Hmmm. This could be one way if im just doing a modify record.

But are there any other ways i could do this in a much simpler way? what i have here is other functions that, for example needs to add an incremental counter into the "file" that im trying to modify.

Erm.. i dont knwo how to put into words. For example, i have a video data list with records of how many stocks left for a particualr video. whenevr someone checks out (rent a video) it will decrease the stock level and updates the database accordingly so i can konw how many stocks are left.

i believe this uses a modify record technique but to do this for my all other functions is just too tedious. are there any other ways that i could for example,

find a record
read the contents
edit the record content
point the pointer to the record i found prevuosly
and simply rewrite it

Thanks alot you all for the help. Really appreaciates it. ;)

If the file is set up predictably then you can modify just the data you need, but it can't change any data beyond the memory of the original. Say you have a file with a series of records. Each record has an int representing the number of copies available and a char array that has exactly 50 characters to it that represents the name of whatever it is you are trying to keep track of. Some of the char in the char array may be fillers without any "useful" meaning---sort of like leading zeros to a number, but for this to work each record has to have the same exact number of characters to the string. Under those circumstances you could use seekp() (or maybe it's seekg(), you'll have to look it up for sure) to locate the exact bits/bytes of memory you want to change without destroying the entire file and rewriting it. To do this you can try something like this:

read in each record one at a time until you find the one you want based on the char array field of the record. Keep track of how many records from the beginning of the file the desired record is. Then call seekp() using the stream you are using to write to the file and pass it two parameters, the first being the start of the file and the second being the product of the number of records from the beginning the file the desired record is and the size of each record as determined by the sizeof() operator. This will place the file pointer used to write to the file at the memory location representing the start of the desired record within the desired file (assuming the file is sequential in file memory). Then determine the number of bytes the desired field is within the desired record from the start of the desired record. If the int value is the first field in each record you are already there. Otherwise call seekp() again to move the file pointer the desired distance within the given record. Once the file pointer is correctly postioned you can use the << operator to overwrite the desired memory you want with the desired value you want without reading the entire file in, changing the desired value, and rewriting the entire file back. However, you have to have some way to know where to go to get to the desired memory in the file to change the information you want to change and then the memory used for the desired changes must match the memory used by the original information in memory, otherwise you are likely to corrupt the file.

if i assign lets say

char video[40];

and for example a word "hello world" is in that video[40]. if i want to updat it to "hello big world"

is that suppose to mean i already have a fix memory space?


If its ok can someone please provide me a little bit of sample code on how this update thing suppose to be done. thanks alot!

Member Avatar for iamthwee

if i assign lets say

char video[40];

and for example a word "hello world" is in that video[40]. if i want to updat it to "hello big world"

is that suppose to mean i already have a fix memory space?


If its ok can someone please provide me a little bit of sample code on how this update thing suppose to be done. thanks alot!

Hello, let me introduce you to your newest friend. The std::string. In time you will wonder how you ever got things done without them.

#include <iostream>
#include <string>

int main()
{
    std::string crap="hello";
    
    crap=crap+" big world"; //ammend the string

   
    std::cout<<crap; //new string;
    std::cout<<"\nHey that was easy!";
    std::cin.get();
    return 0;
}

The example isn't exactly as you have described but is shown for simplicity and understanding.

Yup i noe using strings is a good choice. :) What im stucked here is to modify a record. I really need some answers on how i can do this. Ive done tons of research about how to do it and really have the concepts on how to do it but i dont konw how to implement it!

i know what im suppose to do it using seekg to seek for the record i want to modify, simply using cin.getline to input a new record into a temporary "char" so when i want to use the fstream.write() funtion, i dont know how to go around with it..

i really just need a sample of how modify code works...

IMO, in this case, using strings may not be the best answer, you might want to go with plain old char array work. I can't say that I've done this so I'm talking theory here, but I confident it should work. In order to use seekx() to change file contents you need to know exactly where to place the file pointer. That works easiest if you count char (each char is one byte) to place the pointer where you want or if you know the exact size of each record written to or contained within the file. Assume for arguments sake that each record consists of an int and a string. We know the int has a standard memory size irregardless of whether the value stored is 4 or 4444, but the string does not. That is, if the string in the record is declared as char s[20] each string could have up to 20 char, but it may have none or 3 or 12 or 18, or maybe even twenty. Each char in the string will have a memory footprint of one byte, but the entire string may or may be 20 bytes. The point is each string could be of different length. In contrast, you can be sure that each char array written to file is exactly 20 char long if your treat it as a char array and not as a string. In order for each record to take up the same memory footprint in the file if you write a string to the file you will need to pad the string field to be 20 char if the string isn't 20 char long. If you use << to write the string to the file, then you will need to determine the length of the string and determine the amount to pad from there. On the other hand the char array can be initialized to some default value and then the characters of the string can be entered into the array as appropriate leaving default values for anything beyond the length of the string, and then you could use a function to loop through all 20 char writing each char one at a time to the file thereby assuring that each record written to file has an int to begin and 20 char after that. Either way, using a string and calculating how much to pad, or using a standard char array with defaults, you could replace "hello world" with "hello big world" within the string file since it doesn't take up more than the memory footprint for the string field, in fact you will still need some padding to get you to the 20 char desired to keep the file intact.

Member Avatar for iamthwee

>What im stucked here is to modify a record. I really need some answers on how i can do this.

Erm, well I've done a litte code to help how you might modify a file... but I'm using vectors and std::strings instead, anywhoo...have a look

First save this file in your c: directory

records.txt

Movie title:The matrix
Movie star 1:Keanu Reeves
Movies star 2:Lawrence Fishbourne
Movie producer:Joel Silver
Movie director:Wachowski Brothers
Production Company:Warner Brothers
Number of Copies in Stock:25
Total Copies in store:1

Here's the code...

//pedantic.cpp
//A program to demonstrate how to ammend a text file
//Released into the public domain on the 02/04/06
//All rights reserved 

#include <iostream>
#include <string>
#include <fstream>
#include <vector>

int main()
{
    std::vector <std::string> bullcrap; //create a vector of strings
    std::vector <std::string> more_bullcrap; //create a vector of strings
    
    bullcrap.push_back("Movie title:");
    bullcrap.push_back("Movie star 1:");
    bullcrap.push_back("Movie star 2:");
    bullcrap.push_back("Movie producer:");
    bullcrap.push_back("Movie director:");
    bullcrap.push_back("Production company:");
    bullcrap.push_back("Number of Copies in Stock:");
    bullcrap.push_back("Total Copies in store:");
    
    std::ifstream read("c:/records.txt");
    
    std::string tee_he;
    
    while(getline(read,tee_he,'\n'))//read in file line by line
    {
        std::cout<<tee_he<<std::endl;
        more_bullcrap.push_back(tee_he);
    }
    read.close();    
    
    std::cout<<"\n\n\nWhat do ya wanna change,gimme a number chump:\n"<<std::endl;
    
    for(int i=0; i<more_bullcrap.size(); i++)
    {
        std::cout<<"  "<<i+1<<")"<<more_bullcrap[i]<<std::endl;
    }    
    int choice;
    std::cin>>choice;
    
    std::cout<<"You have chosen "<<bullcrap[choice-1];
    std::cout<<"\nWhat do you wanna change it to:"<<std::endl;
    
    std::cin.ignore();
    std::string burp;
    std::getline(std::cin, burp, '\n');
    
    more_bullcrap[choice-1].erase(); //delete entire line chosen by user
    more_bullcrap[choice-1]=burp; //replace line with new value
    
    std::cout<<"\n\n\n";
    std::cout<<"Your file has been ammended\nThanQ";
    
    remove("c:/records.txt");//delete file
    
    std::ofstream write("c:/records.txt");//write to file
    for(int i=0; i<more_bullcrap.size(); i++)
    {
        if (i==choice-1)
        {
           write<<bullcrap[i]<<more_bullcrap[i]<<std::endl;
        }  
        else
        {
           write<<more_bullcrap[i]<<std::endl;
        }    
          
    }  
    write.close();

    std::cin.get();
    return 0;
    
    
}

And a sample run...

Movie title:The matrix
Movie star 1:Keanu Reeves
Movies star 2:Lawrence Fishbourne
Movie producer:Joel Silver
Movie director:Wachowski Brothers
Production Company:Warner Brothers
Number of Copies in Stock:25
Total Copies in store:1



What do ya wanna change,gimme a number chump:

  1)Movie title:The matrix
  2)Movie star 1:Keanu Reeves
  3)Movies star 2:Lawrence Fishbourne
  4)Movie producer:Joel Silver
  5)Movie director:Wachowski Brothers
  6)Production Company:Warner Brothers
  7)Number of Copies in Stock:25
  8)Total Copies in store:1
1
You have chosen Movie title:
What do you wanna change it to:
The matrix Revolutions



Your file has been ammended
ThanQ

Hmm?

Yup, that's the read the file, change the data, overwrite old file technque. I think he wants the change the file contents without overwriting the entire file version, though.

Member Avatar for iamthwee

Yup, that's the read the file, change the data, overwrite old file technque. I think he wants the change the file contents without overwriting the entire file version, though.

I agree that doing it my way is inefficient, especially if the file is tens of thousands of pages long. And Probably the use of std::strings and std::vectors just confused him? I hate using c-style strings :sad:

The only other way I can see how to do this without going into the complicated proceedure you outlined in your previous post is to:-

Open the original file
Read in the file line by line holding one line at a time in memory
If that line is to remain unchanged write it to a temporary file
If that line is to be changed ammend that line whilst still in memory and then write it to the temporary file.
Carry on till you have read all of the original file.
Then remove the original file and rename the temporary file with the name of the original file.

(which is basically just the method you had described earlier)

This way, instead of reading the whole file into memory you are only reading one line at a time into memory. ???

If it's any more complicated than that, I think you should consult your teacher. This assignment shouldn't really be any more complicated than this.


Most of that stuff I've done with std::strings can be done using c-style strings. I'll post up a link in a bit if you're intent on using c-style strings.

Hey there guys!

I've solved my own problem here. After more and more (which i've already done so much... :( sigh)research, i've finally found out a way to do this. it might not be the more efficient way to go around the problem but it works and im planing to stick around with it unless i've got time to play around wit it.

Special thanks to iamthwee and Lerner for replying to my problems! its great to learn from u guys. Really appreaciates it!

anyway, here is my code out for anyone else who might have got the same problem as i do and are searching the forum for answer. Hope it helps them!

void modifyVideoList()
	{
		videoDataTemp temp; //videodataTEMP to temp (temporary storage)
		fstream file4; //fstream is file4
		videoData fields; //videoData is fields (original)
		
		char titleTemp [30]; //temporary storage for search function
		int flag=0;
		int num=0; //counter to count how many record it has go thru
		int counter=0;

		cout<<"\t\n\nEnter title of video to search: \n";
		cin.getline(titleTemp,30);

		file4.open("videolist.dat", ios::out | ios::in | ios::binary);
		file4.seekg(0, ios::beg);
		file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );
		
		//while not end of file
		while ( !file4.eof())
		{

			//if string compare original title is equals to temporary
			//return true
			if(strcmp(fields.title,titleTemp)==0)
			{
				num = num+1; //num plus 1
				//cout<<num<<endl;
	
				///////display previos title

				cout<< "\nDisplaying '" << fields.title << "' Information\n";
				cout<< "Movie Title: " << fields.title <<endl;
				cout<< "Movie Star 1: " << fields.star1 <<endl;
				cout<< "Movie Star 2: " << fields.star2 <<endl;
				cout<< "Movie Producer: " << fields.producer <<endl;
				cout<< "Movie Director: " << fields.director <<endl;
				cout<< "Production Company: " << fields.productionCo <<endl;
				cout<< "Number of Available Copies In Stock: " << fields.availableCopies <<endl;
				cout<< "Total Copies in Store: " << fields.copiesInStock <<endl;

				cout<< "\n\n";

				//////////edit into temporary storage

				cout<<"Video Title: ";
				cin.getline(temp.TEMPtitle, 30);

				cout<<"Movie Star 1: ";
				cin.getline(temp.TEMPstar1, 30);

				cout<<"Movie Star 2: ";
				cin.getline(temp.TEMPstar2, 30);

				cout<<"Movie Producer: ";
				cin.getline(temp.TEMPproducer, 30);

				cout<<"Movie Director: ";
				cin.getline(temp.TEMPdirector, 30);

				cout<<"Production Company: ";
				cin.getline(temp.TEMPproductionCo, 30);

				cout<<"Number of Available Copies in Stock: ";
				cin>> temp.TEMPavailableCopies;

				cout<<"Total Copies in Store: ";
				cin>> temp.TEMPcopiesInStock;
				
				//seek position of the original file and replace using write
				file4.seekp(num*sizeof(fields),ios::beg);	//move the write ponter this time
				file4.write( reinterpret_cast<char*>(&temp), sizeof(fields)); //<-- Edited Version
				break;

			}

			num = counter++;
				
			file4.read( reinterpret_cast<char*>(&fields), sizeof(fields) );
			
		}

		if(flag==1)
		{
			cout<<"Video title not found!"<<endl;
			fflush(stdin);
		}
		
		cout << endl;
		file4.close();
		system("Pause");
		system("Cls");

	}

Resources i've gone thru for anyone looking for answers.
1. http://www.cplusplus.happycodings.com/index.html
2. file:///D:/Documents%20and%20Settings/weehoong/My%20Documents/My%20Received%20Files/Tips%20and%20Tricks%20for%20Using%20C%20I-O%20(input-output).htm
3. http://cboard.cprogramming.com/showthread.php?t=68697

Hope these links help anyone having the same problems as i do. Its really a pleasure to have these forums around!

How about serialization or XML? Would those help?

As Lerner said, the problem is that if you have to make a dramatic change, you have to move the whole file.

You have an option here, though. If you buffer every entry with a lot of empty space, you can use the file pointer to overwrite "safe" space without modifying the rest of the file. You just have to check that you don't overrun the buffer.

Unfortunately, this increases your file size, and could be costly if your records list gets really big....

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.