Saving to file

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • ConfusedAlot
    New Member
    • Mar 2007
    • 17

    Saving to file

    This is my code for a database, whenever i save the database to the file 'database.txt' and display the results i get this;

    name - (correct, is what i put in)
    pin - 3435973836
    slew rate - -9.25596e+061

    these values are the same for every entry i add, i cant seem fo figure out why.

    Plus, the text file i save to is supposed to have the format of

    length

    Name
    Pin
    Slew

    Name
    Pin Slew

    However, the text file looks nothing like it, any ideas as to why it isnt in this format??

    code;
    Code:
    #include <stdafx.h>
    #include <iostream>
    #include <fstream>
    #include <string.h>
    using namespace std;
    
    struct OpAmps {
      char Name[20];  // the name of the op-amp (e.g. "741")
      unsigned int PinCount;  // the number of pins in the package
      double SlewRate;  // the slew rate in volts per microsecond
    };
    
    #define DATABASE_MAX 10
     
    #define DATABASE_FILENAME "database.txt"
    
    // function prototypes
    
    void Enter(OpAmps&, unsigned long&);
    void Save(const OpAmps*, const unsigned long&);
    void Load(OpAmps*, unsigned long&);
    void Sort(OpAmps*, unsigned long&);
    void Display(OpAmps*, const unsigned long&);
    
    int SortByName(const void*, const void*);
    int SortBySlewRate(const void*, const void*);
    
    int main()
    {
      OpAmps OpAmp[DATABASE_MAX];   // the database
      unsigned long database_length = 0;  // the number of elements in the database
      char UserInput;
                          
      // loop until the user wishes to exit
      while (1) {
        
        // show the menu of options
        cout << endl;
        cout << "Op-amp database menu" << endl;
        cout << "--------------------" << endl;
        cout << "1. Enter a new op-amp into the database" << endl;
        cout << "2. Save the database to disk" << endl;
        cout << "3. Load the database from disk" << endl;
        cout << "4. Sort the database" << endl;
        cout << "5. Display the database" << endl;
        cout << "6. Exit from the program" << endl << endl;
        
        // get the user's choice
        cout << "Enter your option: ";
        cin >> UserInput;
        cout << endl;
        
        // act on the user's input
        switch(UserInput) {
          case '1':
            Enter(OpAmp[database_length], database_length);
            break;
          
          case '2':
            Save(OpAmp, database_length);
            break;
          
          case '3':
            Load(OpAmp, database_length);
            break;
          
          case '4':
            Sort(OpAmp, database_length);
            break;
          
          case '5':
            Display(OpAmp, database_length);
            break;
    
          case '6':
            return 0;
    
          default:
            cout << "Invalid entry" << endl << endl;
            break;
        }
      }
    }
    
    
    void Enter(OpAmps& OpAmp, unsigned long& length)
    // if the database is full, inform the user
    {
    	char line[20];
    	unsigned int Pin;
    	double Slew;
    	bool cont=false;
    
    	if (length == 10)
    	{
    		cerr << "The database is full" << endl;
    	}
    
    // if the database is not full, get the data from the user and alter the database length
    
    	else
    		while (cont==false)
    		{
    			cout << "Enter Operational Amplifier name: ";
    			cin.ignore();
    			cin.getline(line, sizeof(line), '\n');
    			strcpy_s(OpAmp.Name, line);
    			cont=true;
    		}
    
    
    	cont = false;
    	while (cont==false)
    	{
    		cout << endl << "Enter number of pins: ";
    		cin.ignore();
    		cin.getline(line, sizeof(line));
    		scanf_s(line,"%u",&Pin), '\n';
    		OpAmp.PinCount=Pin; 
    		cont=true;
    	}
    	
    	cont = false;
    	while (cont==false)
    	{
    		cout << endl << "Enter slew rate: ";
    		cin.ignore();
    		cin.getline(line, sizeof(line), '\n');
    		scanf_s(line,"%f",&Slew);
    		OpAmp.SlewRate=Slew; 
    		cont=true;
    	}
    	length++;
    
    	cout << endl << "Operator Amplifier in memory, to save select option 2 from main menu" << endl;
    }
    
    void Save(const OpAmps* OpAmp, const unsigned long& length)
    {  
      fstream output_file;  // file stream for output
    
      // open the file
      //<enter code here>
      output_file.open(DATABASE_FILENAME, ios::out);
      if (!output_file.good())
      {
    	  cout << "Could not create file";
    	  exit (1);
      }
    
      cout << "Opened file to save data to" << endl;
    
      // write length information to file
      output_file << length << endl << endl;
    
      // write data to file
      unsigned int i;
      for (i=0;i<length;i++);
      {
    	  output_file.write((char *)(&OpAmp[i]), sizeof(OpAmp));
      }
      cout << length << " entry(s) added to database" << endl;
      // close the file
      output_file.close();
    }
    
    void Load(OpAmps* OpAmp, unsigned long& length)
    {  
      fstream input_file;  // file stream for input
    
       //open the file
      input_file.open(DATABASE_FILENAME, ios::in);
      if (!input_file.good())
      {
    	  cout << "Could not open file";
    	  exit (1);
      }
    
      // load database length information from file
      else
      {
    	  cout << "File opened" << endl;
    
    	  char templine[20];
    	  char emptyline[20];
          
    	  OpAmps* pOpAmps = &OpAmp[0];
    
    	  input_file >> emptyline;
    	  unsigned long tempLn=0;
    	  scanf_s(emptyline, "%lu", &tempLn);
    	  cout << tempLn << endl;
    	  length = tempLn;
    
    	  if (length==0)
    	  {
    		cout << "Database empty" << endl;
    	  }
    	  else 
    	  {
    		      unsigned int Pin;
    			  float Slew;
                 
    			  for (unsigned int i=0;i<length;i++)
    			  {
    			     input_file>>templine;
    				 cout<<templine<<endl;
    				 strcpy_s((*pOpAmps).Name,templine);
    
                     input_file>>templine;
    
    				 if (scanf_s(templine,"%u",&Pin))
    				 {
    					 (*pOpAmps).PinCount=Pin;
    					 cout<<Pin<<endl;
    				 }
    				 else
    				 {
    					 cout<<"Error reading "<< ((*pOpAmps).Name) <<endl;
    				 }
    
    				 input_file>>templine;
    							
    				 if (scanf_s(templine,"%f",&Slew))
    				 {
    					 (*pOpAmps).SlewRate=Slew;
    					 cout<<Slew<<endl;
    				 }
    				 else
    				 {
    					 cout<<"Error reading" << ((*pOpAmps).Name) << endl;
    				 }
    				 pOpAmps++;
    			  }
    			  cout<<"Total "<<length<< "entry(s) read"<<endl;
    	  }
      }
    
    
    
    
    
      // close the file
      input_file.close();
    }
    
    
      void Sort(OpAmps* OpAmp, unsigned long& length)
    {  
      char UserInput;
    
      // show the menu of options
      cout << endl;
      cout << "Sorting options" << endl;
      cout << "---------------" << endl;
      cout << "1. To sort by name" << endl;
      cout << "2. To sort by slew rate" << endl;
      cout << "3. No sorting" << endl << endl;
        
      // get the user's choice of sorting operation required
      cout << "Enter your option: ";
      cin >> UserInput;
      cout << endl;
        
      // act on the user's input
      //<enter code here>
      switch(UserInput)
      {
    
    	case '1':
    		qsort((void*)&OpAmp[0], length, sizeof(OpAmp[0]), SortByName);
    		break;
    
    	case '2':
    		qsort((void*)&OpAmp[0], length, sizeof(OpAmp[0]), SortBySlewRate);
    		break;
    
    	case '3':
    
    	    break;
    
        default:
            cout << "Invalid entry" << endl << endl;
            break;
      }
    
    }
    
    
      int SortByName(const void* Value1, const void* Value2)
    {  
      //<enter code here>
    	return strcmp((*(OpAmps*)Value1).Name, (*(OpAmps*)Value2).Name);
    }
    
    
      int SortBySlewRate(const void* Value1, const void* Value2)
    {  
      //<enter code here>
    	if ((*(OpAmps*)Value1).SlewRate<(*(OpAmps*)Value2).SlewRate)
    	{
          return -1;
    	}	
    	else if ((*(OpAmps*)Value1).SlewRate>(*(OpAmps*)Value2).SlewRate) 
    	{
    	 return 1;
    	}
    	else
    	{
    	 return 0;
    	}
    }
    
    void Display(OpAmps* OpAmp, const unsigned long& length)
    {
    	OpAmps* pOpAmps;
    	pOpAmps=&OpAmp[0];
    
      // if the database is empty, inform the user
      if (length==0)
      {
    	  cout << "The database is empty";
      }
      // if the database is not empty, display all the elements in the database
      //<enter code here>
      else
      {
    	  for (unsigned int i=0;i<length;i++)
    	  {
    		  cout << "Operational Amplifier name : " << (*pOpAmps).Name << endl;
    		  cout << "Number of pins : " << (*pOpAmps).PinCount << endl;
    		  cout << "Slew Rate : " << (*pOpAmps).SlewRate << " Volts/microsecond" << endl << endl;
    		  pOpAmps++;
      }
      }
    }
    Last edited by horace1; Mar 15 '07, 05:25 PM. Reason: add code tags
  • Ganon11
    Recognized Expert Specialist
    • Oct 2006
    • 3651

    #2
    The problem is likely with the line

    Code:
    output_file.write((char *)(&OpAmp[i]), sizeof(OpAmp));
    inside the for...loop of the Save function. You are casting the first portion to a char*, but the thing you are casting is the address of an OpAmps object. This is probably a bad cast, which is giving you the strange results.

    Also, the second argument is using sizeof(OpAmp), which is the size of the array you are using - should it be sizeof(OpAmps), the struct?

    Comment

    • horace1
      Recognized Expert Top Contributor
      • Nov 2006
      • 1510

      #3
      you are not reading the pin and slew rate values correctly in function Enter(), try
      Code:
      void Enter(OpAmps& OpAmp, unsigned long& length)
      // if the database is full, inform the user
      {
      	char line[20];
      	unsigned int Pin;
      	double Slew;
      	bool cont=false;
      
      	if (length == 10)
      	{
      		cerr << "The database is full" << endl;
      	}
      
      // if the database is not full, get the data from the user and alter the database length
      
      	else
      		while (cont==false)
      		{
      			cout << "Enter Operational Amplifier name: ";
      			cin.ignore();
      			cin.getline(line, sizeof(line), '\n');
      			strcpy(OpAmp.Name, line);
      			cont=true;
      		}
      
      
      	cont = false;
      	while (cont==false)
      	{
      		cout << endl << "Enter number of pins: ";
      		//cin.ignore();
      		//cin.getline(line, sizeof(line));
      		scanf("%u",&Pin), '\n';
      		OpAmp.PinCount=Pin; 
      		cont=true;
      	}
      	
      	cont = false;
      	while (cont==false)
      	{
      		cout << endl << "Enter slew rate: ";
      		//cin.ignore();
      		//cin.getline(line, sizeof(line), '\n');
      		scanf("%lf",&Slew);
      		OpAmp.SlewRate=Slew; 
      		cont=true;
      	}
      	length++;
      cout << OpAmp.Name << " " <<  OpAmp.PinCount << " " <<  OpAmp.SlewRate << " " << endl;
      	cout << endl << "Operator Amplifier in memory, to save select option 2 from main menu" << endl;
      }
      it is a good idea in a function such as enter where you read in data to print it out to screen so you can check the read worked

      Comment

      • ConfusedAlot
        New Member
        • Mar 2007
        • 17

        #4
        So in the console that works fine, but in the database.txt file the program creates the information is not stored conrrectly. The file only contains the length and then alot of garbage, cant seem to pinpoint where the code is wrong
        ideas??

        Comment

        • ConfusedAlot
          New Member
          • Mar 2007
          • 17

          #5
          I have changed a part of the save function to this:

          unsigned int i;
          for (i=0;i<length;i ++);
          {
          //output_file.wri te((const char*)&OpAmp[i], sizeof(OpAmps)) ;
          output_file << endl;
          output_file << OpAmp[i].Name << endl;
          output_file << OpAmp[i].PinCount << endl;
          output_file << OpAmp[i].SlewRate << endl;

          but it is still not saving the correct text to file, all just garbage still. All the online help i have looked at doesnt help me solve the problem...

          Comment

          • horace1
            Recognized Expert Top Contributor
            • Nov 2006
            • 1510

            #6
            Originally posted by ConfusedAlot
            I have changed a part of the save function to this:

            unsigned int i;
            for (i=0;i<length;i ++);
            {
            //output_file.wri te((const char*)&OpAmp[i], sizeof(OpAmps)) ;
            output_file << endl;
            output_file << OpAmp[i].Name << endl;
            output_file << OpAmp[i].PinCount << endl;
            output_file << OpAmp[i].SlewRate << endl;

            but it is still not saving the correct text to file, all just garbage still. All the online help i have looked at doesnt help me solve the problem...
            you have a ; on the end of your for() statement - this will terminate the for and on exit i will = length so garbage is written to the file

            Comment

            • ConfusedAlot
              New Member
              • Mar 2007
              • 17

              #7
              thanks, so last thing, in the Load function, i always get a length of zero, it is supposed to read the first line of the text file and then read the corresponding entries, the first line in the file is the number 3, so it should read three, but doesnt, ideas??

              Code:
              void Load(OpAmps* OpAmp, unsigned long& length)
              {  
                fstream input_file;  // file stream for input
              
                 //open the file
              
                input_file.open(DATABASE_FILENAME, ios::in);
                if (!input_file.good())
                {
              	  cout << "Could not open file";
              	  exit (1);
                }
              
                // load database length information from file
              
                else
                {
              	  cout << "File opened" << endl;
              
                // load data from file
              
              	  char templine[20];
              	  char emptyline[20];
                    
              	  OpAmps* pOpAmps = &OpAmp[0];
              
              	  input_file >> emptyline;
              	  unsigned long tempLn=0;
              	  if (scanf_s(emptyline, "%lu", &tempLn))
              	  {
              		  cout << tempLn << endl;
              		  length = tempLn;
              	  }
              	  else
              	  {
              		  cout << "Error" << endl;
              	  }
              
              	  if (length==0)
              	  {
              		cout << "Database empty" << endl;
              	  }
              	  else 
              	  {
              		      unsigned int Pin;
              			  float Slew;
                           
              			  for (unsigned int i=0;i<length;i++)
              			  {
              			     input_file>>templine;
              				 cout<<templine<<endl;
              				 strcpy_s((*pOpAmps).Name,templine);
              
                               input_file>>templine;
              
              				 if (scanf_s(templine,"%u",&Pin))
              				 {
              					 (*pOpAmps).PinCount=Pin;
              					 cout<<Pin<<endl;
              				 }
              				 else
              				 {
              					 cout<<"Error reading "<< ((*pOpAmps).Name) <<endl;
              				 }
              
              				 input_file>>templine;
              							
              				 if (scanf_s(templine,"%lf",&Slew))
              				 {
              					 (*pOpAmps).SlewRate=Slew;
              					 cout<<Slew<<endl;
              				 }
              				 else
              				 {
              					 cout<<"Error reading" << ((*pOpAmps).Name) << endl;
              				 }
              				 pOpAmps++;
              			  }
              			  cout<<"Total "<<length<< "entry(s) read"<<endl;
              	  }
                }
              Last edited by Ganon11; Mar 16 '07, 12:12 PM. Reason: code tags added

              Comment

              • Ganon11
                Recognized Expert Specialist
                • Oct 2006
                • 3651

                #8
                Instead of reading the first line into a character array, since you know it will be an int value, why not try reading the value directly into length? Something like:

                Code:
                input_file >> length;
                I only say this because I've never used scanf_s and am not sure if this line is producing errors.

                Comment

                Working...