| 1 |  | /* $Id$ */ | 
| 2 |  |  | 
| 3 | #include <stdio.h> | #include <stdio.h> | 
| 4 |  | #include <stdlib.h> | 
| 5 | #include <math.h> | #include <math.h> | 
| 6 | #define PRINTPRIME(x) if(prime(x)) printf("%i\n", x) | #include <limits.h> | 
| 7 | int prime(int number) | #include <errno.h> | 
| 8 |  |  | 
| 9 |  | #ifdef _MSC_VER | 
| 10 |  | #define snprintf _snprintf | 
| 11 |  | #endif | 
| 12 |  |  | 
| 13 |  | #define BOOL int | 
| 14 |  | #define TRUE 1 | 
| 15 |  | #define FALSE 0 | 
| 16 |  |  | 
| 17 |  | #define PRINTPRIME(x) if (is_prime(x)) printf("%i\n", x) | 
| 18 |  | #define PRINTERROR(message) fprintf(stderr, "ERROR: %s\n", message) | 
| 19 |  | #define PRINTWARNING(message) fprintf(stderr, "WARNING: %s\n", message) | 
| 20 |  |  | 
| 21 |  | #define MAX_LINE_LENGTH 80 | 
| 22 |  |  | 
| 23 |  |  | 
| 24 |  | /* check for prime number */ | 
| 25 |  | BOOL is_prime(long int number) | 
| 26 | { | { | 
| 27 | int i; | int i,sq; | 
| 28 | for(i=2;i*i<=number;i++){ | /* negative values, 0 and 1 are never prime numbers */ | 
| 29 | if((number%i) == 0) | if (number < 2) return FALSE; | 
| 30 | return 0; | sq=sqrt(number); | 
| 31 | } |  | 
| 32 | return 1; | /* check all numbers 2..sqrt(number) for being a prime number */ | 
| 33 |  | for (i=2; i <= sq; i++) { | 
| 34 |  | if ((number % i) == 0) | 
| 35 |  | return FALSE; | 
| 36 |  | } | 
| 37 |  | return TRUE; | 
| 38 | } | } | 
| 39 |  |  | 
| 40 |  | /* convert from string to long int, with error checking */ | 
| 41 |  | long int convert_number(const char *nptr, BOOL warn) { | 
| 42 |  |  | 
| 43 |  | char * endptr; | 
| 44 |  | errno = 0; | 
| 45 |  | long int number = strtol(nptr, &endptr, 10); | 
| 46 |  |  | 
| 47 |  | /* invalid characters? */ | 
| 48 |  | if (*endptr != '\0') { | 
| 49 |  | char message[256]; | 
| 50 |  | snprintf(message, 255, "Could not convert '%s' to a valid (integer) number.", nptr); | 
| 51 |  | if(warn) | 
| 52 |  | PRINTWARNING(message); | 
| 53 |  | else{ | 
| 54 |  | PRINTERROR(message); | 
| 55 |  | exit(EXIT_FAILURE); | 
| 56 |  | } | 
| 57 |  | } | 
| 58 |  |  | 
| 59 |  | /* invalid range? */ | 
| 60 |  | /* if (number == LONG_MAX || number == LONG_MIN) { */ | 
| 61 |  | if (errno == ERANGE) { | 
| 62 |  | char message[256]; | 
| 63 |  | snprintf(message, 255, "Number is not in range of 'long int': %s", nptr); | 
| 64 |  | if(warn) | 
| 65 |  | PRINTWARNING(message); | 
| 66 |  | else{ | 
| 67 |  | PRINTERROR(message); | 
| 68 |  | exit(EXIT_FAILURE); | 
| 69 |  | } | 
| 70 |  | } | 
| 71 |  |  | 
| 72 |  | return number; | 
| 73 |  |  | 
| 74 |  | } | 
| 75 |  |  | 
| 76 | int main(int argc, char * argv[]) | int main(int argc, char * argv[]) | 
| 77 | { | { | 
| 78 | int i, j; |  | 
| 79 | FILE * fp; | if (argc == 1) { | 
| 80 | char num[11]; | PRINTERROR("No arguments given."); | 
| 81 | if(argc > 2 ){ | exit(EXIT_FAILURE); | 
| 82 | j=atoi(argv[2]); | } | 
| 83 | for(i=atoi(argv[1]) ; i< j; i++){ |  | 
| 84 |  | /* (3) range mode */ | 
| 85 |  | if (argc > 2) { | 
| 86 |  | long int i, j; | 
| 87 |  | i = convert_number(argv[1],FALSE); | 
| 88 |  | j = convert_number(argv[2],FALSE); | 
| 89 |  | for (i; i< j; i++) { | 
| 90 | PRINTPRIME(i); | PRINTPRIME(i); | 
| 91 | } | } | 
| 92 | }else { |  | 
| 93 | fp=fopen(argv[1], "r"); | /* other modes */ | 
| 94 | if(fp==NULL){ | } else { | 
| 95 | PRINTPRIME(atoi(argv[1])); | int err; | 
| 96 | }else{ | /* try to open file for reading */ | 
| 97 | while(fgets(num, 11, fp)) | FILE * fp = fopen(argv[1], "r"); | 
| 98 | PRINTPRIME(atoi(num)); | err=errno; | 
| 99 |  | /* (1) test-single-number mode: first argument is not a filename */ | 
| 100 |  | if (fp == NULL) { | 
| 101 |  | long int number = convert_number(argv[1],TRUE); | 
| 102 |  | if(err){ | 
| 103 |  | fprintf(stderr, "%s: %s\n", argv[1], strerror(err)); | 
| 104 |  | return -1; | 
| 105 |  | } | 
| 106 |  | PRINTPRIME(number); | 
| 107 |  |  | 
| 108 |  | /* (2) file mode: read numbers from file */ | 
| 109 |  | } else { | 
| 110 |  | char line[MAX_LINE_LENGTH + 1]; | 
| 111 |  | long int number; | 
| 112 |  | int line_length; | 
| 113 |  | long int line_no = 0; | 
| 114 |  | while (fgets(line, MAX_LINE_LENGTH + 1, fp)) { | 
| 115 |  |  | 
| 116 |  | /* count line number (for warnings) */ | 
| 117 |  | line_no++; | 
| 118 |  |  | 
| 119 |  | line_length = strlen(line); | 
| 120 |  |  | 
| 121 |  | /* skip empty lines */ | 
| 122 |  | if (strlen(line) < 2) continue; | 
| 123 |  |  | 
| 124 |  | /* line handling: policy = skip exceeding lines */ | 
| 125 |  |  | 
| 126 |  | /* line exceeds max length */ | 
| 127 |  | if (line_length == MAX_LINE_LENGTH && line[line_length-1] != '\n') { | 
| 128 |  | char message[254]; | 
| 129 |  | snprintf(message, 256, "Line too long (max %i chars) in line number: %i", MAX_LINE_LENGTH, line_no); | 
| 130 |  | PRINTWARNING(message); | 
| 131 |  |  | 
| 132 |  | /* eat all characters until newline or EOF */ | 
| 133 |  | while (1) { | 
| 134 |  | int charcode = fgetc(fp); | 
| 135 |  | if (charcode == 10 || charcode == EOF) break; | 
| 136 |  | } | 
| 137 |  |  | 
| 138 |  | /* skip this line from prime calculation */ | 
| 139 |  | continue; | 
| 140 |  | } | 
| 141 |  |  | 
| 142 |  | /* if last char is newline, strip it */ | 
| 143 |  | if (line[line_length-1] == '\n') { | 
| 144 |  | line[line_length-1] = '\0'; | 
| 145 |  | } | 
| 146 |  |  | 
| 147 |  | /* finally: prime number calculation and output */ | 
| 148 |  | number = convert_number(line,FALSE); | 
| 149 |  | PRINTPRIME(number); | 
| 150 |  |  | 
| 151 |  | } | 
| 152 | fclose(fp); | fclose(fp); | 
| 153 | } | } | 
| 154 | } | } |