Capricious Error

This is a discussion on Capricious Error within the C++ Programming forums, part of the General Programming Boards category; Hey... So I am having a hard time with a project I have and I would appreciate if someone makes ...

  1. #1
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68

    Capricious Error

    Hey... So I am having a hard time with a project I have and I would appreciate if someone makes time to read and help me.... It;s kinda big... Anyway, here it is

    I am making a program that has two classes. I have 5 locations where I have sensors for temperature, humidity, wind, sunlight. I get their values for every hour for 5 days (600 values). Each location is an instance of a class named node where i store every hour the date and time values as integers and location as string in a struct named 'data'. I have another class, the "main system" from where I call all the functions(e.g getStats, averageTemp, extremeSun e.t.c e.t.c)

    I save these struct data every time in a file named "measurements.dat" which I open in binary mode like this
    Code:
    void Console::saveValuesF(Data valuesC)	{
    		ofstream outData;
    		if ( !getFileU() )	{
    			outData.open(DATABASE_FILE, ios::out | ios::trunc | ios::binary);
    			setFileU(true);
    		}
    		else
    			outData.open(DATABASE_FILE, ios::out | ios::app | ios::binary);
    			
    		if (outData.is_open())	{			
    			outData.write( (char*)(&valuesC), sizeof(Data) );
    			outData.close();
    		}
    		else
    			cout<<setw(35)<<"File could not be found"<<endl<<endl;
    	}

    When I call the functions for average temperature and humidity and extreme temperatures I open the file and read it 'data' to 'data' with this

    Average Temperature and Humidity
    Code:
    	void Console::averageT_H()	{
    		
    		ifstream inData;
    		inData.open(DATABASE_FILE, ios::in | ios::binary);
    		if (inData.is_open())	{			
    			Data curr;
    			int rodos_tAvrg=0;		int rodos_hAvrg=0;
    			int ioan_tAvrg=0;		
    			int alex_tAvrg=0;		int alex_hAvrg=0;
    			int hania_tAvrg=0;		int hania_hAvrg=0;
    			int kithira_tAvrg=0;	int kithira_hAvrg=0;
    			int j=0;
    			
    			while ( inData.read( (char*)(&curr), sizeof(Data) ) )	{
    				j++;
    				if (curr.location=="Rhodos")	{
    					rodos_tAvrg+=curr.temp;
    					rodos_hAvrg+=curr.humid;
    				}
    				else if (curr.location=="Ioannina")	{
    					ioan_tAvrg+=curr.temp;
    				}
    				else if (curr.location=="Alexandroupoli")	{
    					alex_tAvrg+=curr.temp;
    					alex_hAvrg+=curr.humid;
    				}
    				else if (curr.location=="Chania")	{
    					hania_tAvrg+=curr.temp;
    					hania_hAvrg+=curr.humid;
    				}
    				else if (curr.location=="Kithira")	{
    					kithira_tAvrg+=curr.temp;
    					kithira_hAvrg+=curr.humid;
    				}
    			}
    			cout<<j<<endl;
    			cout<<endl<<"Average temperature of Rhodos is "<<rodos_tAvrg/(j/5)<<(char)249<<"C"
    						<<" and average humidity is "<<rodos_hAvrg/(j/5)<<"%"<<endl;
    						
    			cout<<endl<<"Average temperature of Ioannina is "<<ioan_tAvrg/(j/5)
    						<<(char)249<<"C"<<endl;
    			
    			cout<<endl<<"Average temperature of Alexandroupoli is "<<alex_tAvrg/(j/5)<<(char)249
    						<<"C"<<" and average humidity is "<<alex_hAvrg/(j/5)<<"%"<<endl;
    						
    			cout<<endl<<"Average temperature of Chania is "<<hania_tAvrg/(j/5)<<(char)249<<"C"
    						<<" and average humidity is "<<hania_hAvrg/(j/5)<<"%"<<endl;
    						
    			cout<<endl<<"Average temperature of Kithira is "<<kithira_tAvrg/(j/5)<<(char)249<<"C"
    						<<" and average humidity is "<<kithira_hAvrg/(j/5)<<"%"<<endl;		
    		}
    		else
    			cout<<setw(35)<<"File could not be found"<<endl<<endl;
    		inData.close();
    		
    	}
    Extreme Temperature in all locations
    Code:
    	void Console::extremeTemp()	{
    		ifstream inData;
    		Data curr;		
    		Data extreme_high;
    		Data extreme_low;
    		
    		inData.open(DATABASE_FILE, ios::in | ios::binary);
    		if (inData.is_open())	{	
    			inData.read( (char*)(&curr), sizeof(Data) );
    			extreme_high=extreme_low=curr;
    			
    			while ( inData.read( (char*)(&curr), sizeof(Data) ) )	{
    				if ( curr.temp>extreme_high.temp )	
    					extreme_high=curr;
    				else if ( curr.temp<extreme_low.temp )
    					extreme_low=curr;
    			}
    			cout<<endl<<"Highest temperature was recorded at "<<extreme_high.location<<endl
    				<<" on "<<setfill('0')<<setw(2)<<extreme_high.day<<"/"<<setw(2)<<extreme_high.month
    				<<"/"<<setw(4)<<extreme_high.year<<" "<<setw(2)<<extreme_high.hour
    				<<":00 ---> "<<setfill(' ')<<extreme_high.temp<<endl;
    		
    			cout<<endl<<"Lowest temperature was recorded at "<<extreme_low.location<<endl
    				<<" on "<<setfill('0')<<setw(2)<<extreme_low.day<<"/"<<setw(2)<<extreme_low.month
    				<<"/"<<setw(4)<<extreme_low.year<<" "<<setw(2)<<extreme_low.hour
    				<<":00 ---> "<<setfill(' ')<<extreme_low.temp<<endl;
    		}
    		else
    			cout<<setw(35)<<"File could not be found"<<endl<<endl;
    		inData.close();
    		
    	}
    What is my problem? For some reason (I think it may be memory issues, my partner doesnt know) when I call the function void Systemh::avrgTempHum() the first time it works just fine and shows the averages of the 5 nodes but if I call it again the averages temperatures and humidity of the last node are 0 !!!!! Now if I close the program and rerun it with the file with the previus values it shows again the correct values so this means that the 'data' in the file haven't changed right? The other problem is that if run the void Systemh::avrgTempHum() funtion and then the void Systemh::extremeTemp() funtion for extreme temperatures it crashes. This is where i think it may be problems with allocated memory, I dont know, maybe the program tries to get memory that doesnt belong to it but i dont know how to check it and I dont understand. I use a temp variable. Should I perhaps try to work with pointers. Instead of a temp 'data' variable declare a pointer to a 'data' variable and so on, although I am not very sure...
    Furthemore if I run the extreme temperature function first and then the average the extreme works just fine but the average has the problem with the last node being 0 and if run then the extreme again it crashes...

    I know this is a lot but if anyone can help, it is greatly appreciated. If anyone is interested in the whole program the files can be found here -----> "http://www.geocities.com/vhf_andrew/source.doc" Actually it's a rar file so rename it and extract to a folder. Make a project and add them and then compile....

  2. #2
    ZuK
    ZuK is offline
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    How is Data defined ?
    Code:
    curr.location=="Rhodos"
    looks like location is a std::string. If it is you cannot use read/write to read/save from/to file.
    Kurt

  3. #3
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    Code:
    #ifndef NODEN_H
    #define NODEN_H
    	
    	const int INVALID1=-1;	const int INVALID2=-11;
    	const int T_MAX=40;		const int T_MIN=-10;
    	const int H_MAX=100;	const int H_MIN=0;
    	const int W_MAX=10;		const int W_MIN=0;
    	const int S_MAX=10;		const int S_MIN=0;
    	
    	struct Data{
    		int hour;	int day;	int month;	int year;
    		int temp;	int humid;	int wind;	int sun;
    		std::string location;
    	};
    
    class Node	{
    	
    	public:
    		Node(std::string);
    		~Node(){}
    		void clear();
    		
    		void setHour(int x){values.hour=x;}		int getHour() const {return values.hour;}
    		void setDay(int x){values.day=x;}		int getDay() const {return values.day;}
    		void setMonth(int x){values.month=x;}	int getMonth() const {return values.month;}	
    		void setYear(int x){values.year=x;}		int getYear() const {return values.year;}
    		
    		void setTemp(int x){values.temp=x;}		int getTemp() const {return values.temp;}
    		void setHumid(int x){values.humid=x;}	int getHumid() const {return values.humid;}	
    		void setWind(int x){values.wind=x;}		int getWind() const {return values.wind;}		
    		void setSun(int x){values.sun=x;}		int getSun() const {return values.sun;}
    		
    		std::string getLoc() const {return values.location;}
    				
    		Data getValues() const {return values;}
    			
    	private:
    		Data values;
    };
    #endif

  4. #4
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    this is the node class

  5. #5
    ZuK
    ZuK is offline
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    Yes that's your problem.
    Code:
    outData.write( (char*)(&valuesC), sizeof(Data) );
    does not properly save a Data. You basically just save a pointer to the string data ( but not the data itself ) to file.
    If you restore that pointer and try to access the string's data anything can happen.
    Possibly the best ( easiest ) solution to your problem is to save the data as text.
    Kurt
    Last edited by ZuK; 05-11-2007 at 02:35 PM.

  6. #6
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    Isn't there a way to save the struct data to a file as it is and then retrieve it or even the instance of the class?
    Don't other programs usually save classes or complicated structures?

  7. #7
    ZuK
    ZuK is offline
    Registered User
    Join Date
    Aug 2005
    Location
    Austria
    Posts
    1,990
    You have to find out about object serialisation. But that is not a trivial subject.
    Kurt

  8. #8
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    Many programs save them as text. Simply overload operator<< and operator>> to work with ostreams and istreams respectively, and output the data in some sort of consistent manner. Then you will be able to read it in based on that format.

    To save them as binary structures all at once they can't have dynamic memory, they must be a constant and consistent size. There's not really a lot of benefits to doing that unless you have some need to read and write structures from the middle of the file.

  9. #9
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    Aha, I see. Ok thanks a lot guys... I will do as you said> you probably mean using tokens right?

  10. #10
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    Yes, but's not even that difficult. Put all the information for a single instance of Data on one line. Output each int separated by a space, then output the location and a newline character. When you read in, just read directly into each int with operator>>, then use getline to fill in the location with the rest of the line.

  11. #11
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    By the way, the method I used with char* and sizeof I found it in a book. Is it wrong or like the eof check in a while statement - should be avoided

  12. #12
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    Are you talking about using read and write? It is not wrong, and it is not "to be avoided". It has specific uses. One place you cannot use it is when the structure you are reading and writing contains dynamic data, and your structure does because it uses the string class.

    If there was a maximum length that you could use for your location, then you could change it to a fixed size character array and it would then work. However, the benefits of using the std::string class probably outweigh the benefits of using binary i/o.

  13. #13
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    Okay... Seems I still got A LONG WAY to go... But then again that is why I like programming. Thanks for all the help. Goodnight....

  14. #14
    Registered User Phoenix_Rebirth's Avatar
    Join Date
    Dec 2005
    Location
    Cyprus
    Posts
    68
    Ahmm, Sorry to bother again but out of curiosity, if I wanted to overload the << and >> operators (which by the way IMHO is unnnecessary here) how would I do it. I am having a little trouble understanding it. Can anyone show me to a webpage, article e.t.c for using << with a ofstream and a struct like variable.... Not really important, just curious

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Getting an error with OpenGL: collect2: ld returned 1 exit status
    By Lorgon Jortle in forum C++ Programming
    Replies: 6
    Last Post: 05-08-2009, 08:18 PM
  2. An error is driving me nuts!
    By ulillillia in forum C Programming
    Replies: 5
    Last Post: 04-04-2009, 09:15 PM
  3. Making C DLL using MSVC++ 2005
    By chico1st in forum C Programming
    Replies: 26
    Last Post: 05-28-2008, 01:17 PM
  4. Connecting to a mysql server and querying problem
    By Diod in forum C++ Programming
    Replies: 8
    Last Post: 02-13-2006, 09:33 AM
  5. Couple C questions :)
    By Divx in forum C Programming
    Replies: 5
    Last Post: 01-28-2003, 12:10 AM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21