Programming Forums
User Name Password Register
 

RSS Feed
FORUM INDEX | TODAY'S POSTS | UNANSWERED THREADS | ADVANCED SEARCH

Reply
 
Thread Tools Display Modes
Old Dec 14th, 2006, 7:05 PM   #1
Ghosty
Newbie
 
Join Date: May 2005
Location: NJ
Posts: 18
Rep Power: 0 Ghosty is on a distinguished road
Send a message via AIM to Ghosty
new unix problem: signals and write() calls

The following code will print prime numbers and output them to a file specified by the user. Also, it will call the alarm() based on values passed on the command line. The SIGALRM and the SIGUSR1 will cause the program to print the last prime number generated. I'm having problems doing my write(). It should be the most straightforward function but I'm really tired and I can't seem to figure it out. There's also a bug with the way I implemented my command line arguments to call the alarm() but I'm not requesting help with that. I just haven't gotten to fixing it yet.

Thanks in advance. Sorry for how ugly the code is.
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <list>
#include <algorithm>
#include <fcntl.h>

using namespace std;

void generatePrimesFile(int*, char*);
void usr1_handler(int);
void alarm_handler(int);
list<int> alarm_values;

//I don't like globals but we can't pass the handler functions anything
int currentPrime = 1;

int main(int argc, char *argv[]) {
	if(argc < 2){
		cerr << "Usage: Lab6 <file to be written> <optional time>" << endl;
		return 1;
	}
	char * name = argv[1];
	int * cp_ptr = &currentPrime;

    // Setup the signal handlers
    struct sigaction usr1Act;
	struct sigaction alarmAct;
    usr1Act.sa_handler = usr1_handler;
	sigemptyset( &usr1Act.sa_mask );
	usr1Act.sa_flags = SA_RESTART;
	
	alarmAct.sa_handler = alarm_handler;
	sigemptyset( &alarmAct.sa_mask);
	alarmAct.sa_flags = SA_RESTART;
	
    if( sigaction( SIGUSR1 , &usr1Act, NULL ) == -1 ) {
		//syserr("sigaction");
    	perror( "sigaction" );
    	exit( 1 );
	}

	if( sigaction( SIGALRM, &alarmAct, NULL) == -1 ) {
		perror( "sigaction alarm");
		exit(1); 
	}
	//fill alarm values list
	alarm_values.clear();
	for(int i= 2; i < argc; i++){
		alarm_values.push_back(i);
	}
	//sort it
	alarm_values.unique();
	alarm_values.sort();
	//set the alarm to the lowest value in the list
	alarm( alarm_values.front() );
	
	generatePrimesFile(cp_ptr, name);
}

void usr1_handler(int signo){
	cout << "Current Prime: " << currentPrime << endl;
}

void alarm_handler(int signo) {
	cout << "Current Prime: " << currentPrime << endl;
	if(!alarm_values.empty()){
		int temp = alarm_values.front();
		alarm_values.pop_front();
		alarm( alarm_values.front() - temp );
	}
}
 
void generatePrimesFile(int * currentPrime, char* name) {
		const int BIGNUMBER = 65534;
		bool isPrime=true;
		
		int fd;
		if( (fd = open(name, O_WRONLY|O_APPEND|O_CREAT, 0700)) == -1){
			perror("open");
			exit(1);
		}

		for ( int i = 0; i < BIGNUMBER; i++) {
				for ( int j = 2; j < BIGNUMBER; j++) {
						if ( i!=j && i % j == 0 ) {
						  isPrime=false;
						  break;
						}
				}
				if (isPrime) {
					*currentPrime = i;
					int buff[] = {i};
					write(fd, buff, 2);
					sleep(1);
				}
				isPrime=true;
		}
}
Ghosty is offline   Reply With Quote
Old Dec 14th, 2006, 7:15 PM   #2
Game_Ender
Professional Programmer
 
Game_Ender's Avatar
 
Join Date: May 2006
Location: Maryland, USA
Posts: 306
Rep Power: 3 Game_Ender is on a distinguished road
Did you even look up the prototype of write?
ssize_t write(int fildes, const void *buf, size_t nbyte);
You need a char buffer, not an int one. After you have done that use itoa to turn the number into a character. Then just call write with that buffer.
Game_Ender is offline   Reply With Quote
Old Dec 14th, 2006, 8:43 PM   #3
Ghosty
Newbie
 
Join Date: May 2005
Location: NJ
Posts: 18
Rep Power: 0 Ghosty is on a distinguished road
Send a message via AIM to Ghosty
Well that certainly explains why I wasn't getting readable files. But I included <stdlib.h> and itoa() is reported as undefined. Does Gcc not support it?

Edit: A little googling made me aware of sprintf(). I'm going to try that.
Edit2: sprintf works for my purposes.

Last edited by Ghosty; Dec 14th, 2006 at 9:27 PM.
Ghosty is offline   Reply With Quote
Old Dec 14th, 2006, 11:16 PM   #4
Ghosty
Newbie
 
Join Date: May 2005
Location: NJ
Posts: 18
Rep Power: 0 Ghosty is on a distinguished road
Send a message via AIM to Ghosty
This code works for the most part. I don't know how to format the output though. Ideally, I'd like the output file to look similar to this:

1
2
3
5
7
11
13
and so on with primes

Thanks in advance and again sorry for the mess.

#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <list>
#include <algorithm>
#include <fcntl.h>
#include <cstdio>
#include <signal.h>

using namespace std;

void generatePrimesFile(int*, char*);
void usr1_handler(int);
void alarm_handler(int); 

//I don't like globals but we can't pass the handler functions anything
int currentPrime = 1;
list<int> alarm_values;

int main(int argc, char *argv[]) {
	if(argc < 2){
		cerr << "Usage: Lab6 <file to be written> <optional time>" << endl;
		return 1;
	}
	char * name = argv[1];
	int * cp_ptr = &currentPrime;

    // Setup the signal handlers
    struct sigaction usr1Act;
	struct sigaction alarmAct;
    usr1Act.sa_handler = usr1_handler;
	sigemptyset( &usr1Act.sa_mask );
	usr1Act.sa_flags = SA_RESTART;
	
	alarmAct.sa_handler = alarm_handler;
	sigemptyset( &alarmAct.sa_mask);
	alarmAct.sa_flags = SA_RESTART;
	
    if( sigaction( SIGUSR1 , &usr1Act, NULL ) == -1 ) {
		//syserr("sigaction");
    	perror( "sigaction" );
    	exit( 1 );
	}

	if( sigaction( SIGALRM, &alarmAct, NULL) == -1 ) {
		perror( "sigaction alarm");
		exit(1); 
	}
	//fill alarm values list
	alarm_values.clear();
	for(int i= 2; i < argc; i++){
		alarm_values.push_back(atoi(argv[i]));
	}
	//sort it
	alarm_values.unique();
	alarm_values.sort();
	//set the alarm to the lowest value in the list
	alarm( alarm_values.front() );
	
	generatePrimesFile(cp_ptr, name);
}

void usr1_handler(int signo){
	cout << "Current Prime: " << currentPrime << endl;
}

void alarm_handler(int signo) {
	cout << "Current Prime: " << currentPrime << endl;
	if(!alarm_values.empty()){
		int temp = alarm_values.front();
		alarm_values.pop_front();
		alarm( alarm_values.front() - temp );
	}
}
 
void generatePrimesFile(int * currentPrime, char* name) {
		const int BIGNUMBER = 2000;
		bool isPrime=true;
		
		int fd;
		if( (fd = open(name, O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, 0700)) == -1){
			perror("open");
			exit(1);
		}

		for ( int i = 0; i < BIGNUMBER; i++) {
				for ( int j = 2; j < BIGNUMBER; j++) {
						if ( i!=j && i % j == 0 ) {
						  isPrime=false;
						  break;
						}
				}
				if (isPrime) {
					*currentPrime = i;
					char buff[500];
					int n = sprintf( buff, "%d", i );
					buff[n+1] += '\0';              
					write(fd, buff, n+1);
					sleep(1);
				}
				isPrime=true;
		}
}
Ghosty is offline   Reply With Quote
Old Dec 15th, 2006, 6:11 AM   #5
DaWei
Resident Grouch
 
DaWei's Avatar
 
Join Date: Jun 2005
Posts: 6,453
Rep Power: 10 DaWei is on a distinguished road
You need to be more than aware of sprintf; you need to read its docs (and possibly follow the link to printf). If you want a newline after the number, consider using "%d\n".
__________________
Abstraction doesn't make it impossible to write bad code; it makes it possible to write superior code.
Contributor's Corner: Grumpy on C++ Exceptions DaWei on Pointers
DaWei is offline   Reply With Quote
Old Dec 15th, 2006, 1:59 PM   #6
Ghosty
Newbie
 
Join Date: May 2005
Location: NJ
Posts: 18
Rep Power: 0 Ghosty is on a distinguished road
Send a message via AIM to Ghosty
You are indeed right DaWei. I was in a rush to fix the code and didn't bother reading up on sprintf. I have the code working however.

Thanks for the help GE.
Ghosty is offline   Reply With Quote
Old Dec 15th, 2006, 9:48 PM   #7
lectricpharaoh
Caffeinated Neural Net
 
lectricpharaoh's Avatar
 
Join Date: Jun 2005
Location: Dry west coast of Canada
Posts: 1,031
Rep Power: 5 lectricpharaoh will become famous soon enough
Quote:
Originally Posted by Ghosty
Well that certainly explains why I wasn't getting readable files. But I included <stdlib.h> and itoa() is reported as undefined. Does Gcc not support it?
There is no itoa() in standard C (or C++). It's a compiler-specific function present in some compilers.
Quote:
Originally Posted by Ghosty
Edit: A little googling made me aware of sprintf(). I'm going to try that.
Yes, that would be my suggestion. As DaWei mentioned, you need to be 'more than aware' of it. There is also a risk of buffer overflows; however, since the source is a value with a defined and known range, it's relatively trivial to ensure that the destination string is allocated with sufficient size. The various minimums and maximums for integer values are stored in <limits.h>; you can use these values at run time to allocate a defined buffer size, or (preferably) at compile time via conditional compilation to set a symbolic constant to the appropriate size. Don't forget the terminating zero.

An alternative that avoids all of these allocation size issues would be to use stringstreams. This lets you use the stream I/O syntax you're already familiar with. Info to get you started can be found here.
__________________
And once again, Probability proves itself willing to sneak into a back alley and service Drama as would a copper-piece harlot.
- Vaarsuvius, Order of the Stick
lectricpharaoh is offline   Reply With Quote
Old Dec 17th, 2006, 11:21 PM   #8
Ghosty
Newbie
 
Join Date: May 2005
Location: NJ
Posts: 18
Rep Power: 0 Ghosty is on a distinguished road
Send a message via AIM to Ghosty
Quote:
Originally Posted by lectricpharaoh View Post
An alternative that avoids all of these allocation size issues would be to use stringstreams. This lets you use the stream I/O syntax you're already familiar with. Info to get you started can be found here.
Thanks for the link. I'm definitely going to read up on string streams.
Ghosty is offline   Reply With Quote
Reply

Bookmarks

« Previous Thread in Forum | Next Thread in Forum »

Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Forum Jump




DaniWeb IT Discussion Community
All times are GMT -5. The time now is 10:17 PM.

Powered by vBulletin® Version 3.7.0, Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Copyright ©2007 DaniWeb® LLC