Before you say, yes I've checked nearly all the other postings, none are working.
My program has been giving me a segmentation error for hours and hours and nothing is fixing it. I debugged it to the point where I found it's in the file pointer. From what I know, it's because of the way I'm either using the file pointer in the 'makeArray' function or from the file closing statement. I don't really understand how it's not working because I used my last program as reference for this and it runs perfectly fine but this one won't.
#include <stdio.h>
#include <stdlib.h>
#define ROWS 12
#define COLS 8
void makeArray(FILE*, int [][COLS]);
int getScore(int [][COLS], int, int);
int getMonthMax(int [][COLS], int);
int getYearMax(int [][COLS]);
float getMonthAvg(int [][COLS], int);
float getYearAvg(int [][COLS]);
int toursMissed(int [][COLS]);
void displayMenu();
int processRequest(int [][COLS], int);
void printArray(int [][COLS]);
int main(){
int scoresArray[ROWS][COLS];
int choice, constant = 0;
FILE* inputPtr;
inputPtr = fopen("scores.txt", "r");
makeArray(inputPtr, scoresArray);
fclose(inputPtr);
while(constant == 0){
displayMenu();
scanf("%d", &choice);
processRequest(scoresArray, choice);
}
return 0;
}
void makeArray(FILE* inputPtr, int scoresArray[][COLS]){
int i, j;
for(i = 0; i < ROWS; i++){
for(j = 0; j < COLS; j++){
fscanf(inputPtr, "%d", &scoresArray[i][j]);
}
}
return;
}
I've tried moving the file pointers to every different spot in the code and nothing. I don't necessarily want you to just give me the answer but I want an explanation of why it's happening in this specific code because every other post I've checked and their results don't match up to mine.
Also the input file is
26 35 25 92 0 6 47 68 26 72 67 33 84 28
22 36 53 66 23 86 36 75 14 62 43 11 42 5
14 58 0 23 30 87 80 81 13 35 94 45 1 53
14 55 46 19 13 0 25 28 66 86 69 0 81 15
55 60 26 70 22 36 15 67 62 16 71 7 29 92
84 37 2 30 7 5 4 50 0 67 2 53 69 87
8 23 74 58 86 0 78 88 85 12 1 52 999
I wonder if your university compiler is picky about the input file - can you remove all new lines from a copy of your input file and try running with the copied modified input file --- so it is just a stream of numbers --- see if this sorts it out...
........ in my experience of scanf and fscanf these functions can be a bit fragile if the input does not run exactly the way you say it will in the format part - here "%d" does not tell fscanf about new line characters....
Related
I'm facing an issue where my code seems to misbehave - the cursor is blinking in the terminal, but the code isn't responding, it's stuck.
I tried to do some debugging, but couldn't figure out what's causing it to happen.
Here's my code:
#include <stdio.h>
int main()
{
int prim[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71},szam,i=0;
printf("Kerek egy szamot!\n");
scanf("%d",&szam);
while(szam!=1)
{
if(szam%prim[i]==0)
{
szam=szam/prim[i];
printf("%d*",prim[i]);
}
else
{
if(szam%prim[i]!=0)
{
prim[i]=prim[i+1];
}
}
}
printf("1");
return 0;
}
Basically, what it should do for an integer input is (as the title suggests integer factorization).
I went through various inputs on a sheet and checked what would happen according to my code.
For input = 40 it should execute the first while loop, then step into the if clause, then get divided by 2, and output 2*. Skip the else part and enter the while loop again since 20 not equals with 1. Again, should get divided by 2, and output another 2*, repeat the same process one more time, by now outputting 2*2*2*, and for the 4th iteration, it should enter the else clause, as the input has reduced to 5. Then execute the if clause, increase value of "i" by 1, and since the value of the input should remain 5, iterate the else clause again. Then increase the value of "i" by 1 again, which points to the third element of the array by now, which is 5. Now that both values are the same (input and "i"), it should do the first if clause one more time and output 2*2*2*5*1.
The code is never showing the requested 1 before the return 0;, which makes me think it gets stuck inside the while loop.
Any help is highly appreciated.
Thank you in advance.
There are multiple problems with Revision 1 of the self-answer. These include:
You should not be editing the prim array, but your else clause changes it. Make that const int prim[] = { … };. For a single-cycle program, that doesn't matter, but if you tried to create a loop so as to analyze multiple numbers in a single run, modifying the prim array means that it can't be reused on the next cycle unless it is initialized, but the first 20 primes don't change so you really shouldn't be modifying it at all.
Also, prim[i] = prim[i++]; is UB — you use i twice and modify it, and the sequencing is not defined.
You need to use i++ rather than the assignment, but you also need to ensure that i does not go out of bounds of the array.
Here's a mildly modified version of your code — it prints the prim array to show the damage done.
#include <stdio.h>
static void dump_array(const char *tag, size_t size, const int array[size])
{
printf("%s (%zu):\n", tag, size);
const char *pad = "";
for (size_t i = 0; i < size; i++)
{
printf("%s%d", pad, array[i]);
pad = " ";
}
putchar('\n');
}
int main(void)
{
int prim[20] =
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
};
int szam, i = 0;
dump_array("Primes before", sizeof(prim)/sizeof(prim[0]), prim);
printf("Kerek egy szamot!\n");
scanf("%d", &szam);
while (szam != 1)
{
if (szam % prim[i] == 0)
{
szam = szam / prim[i];
printf("%d*", prim[i]);
}
else
{
prim[i] = prim[i + 1];
i++;
}
}
printf("1\n");
dump_array("Primes after", sizeof(prim)/sizeof(prim[0]), prim);
return 0;
}
This produces correct outputs on some inputs. The source was in pr53.c and the program was pr53:
$ pr53
Primes before (20):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Kerek egy szamot!
48
2*2*2*2*3*1
Primes after (20):
3 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
$ pr53
Primes before (20):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Kerek egy szamot!
47
47*1
Primes after (20):
3 5 7 11 13 17 19 23 29 31 37 41 43 47 47 53 59 61 67 71
$ pr53
Primes before (20):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Kerek egy szamot!
46
2*23*1
Primes after (20):
3 5 7 11 13 17 19 23 23 29 31 37 41 43 47 53 59 61 67 71
$ pr53
Primes before (20):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Kerek egy szamot!
165
3*5*11*1
Primes after (20):
3 5 7 11 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
$
So far, so good. Note that the code handles numbers bigger than 71 as long as the biggest prime factor is no larger than 71.
If the code reused the prim array, the factor 2 has been lost. Over time, other factors would be lost too — the analysis would no longer be correct.
However, the behaviour is less than satisfactory when the number entered has a prime factor larger than 71:
$ pr53
Primes before (20):
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71
Kerek egy szamot!
73
Floating point exception: 8
$
It is not very hard to write code that handles such range errors better. For example, consider this program (source pr71.c, program pr71). Since the array of primes is constant, there's no need to print it; it doesn't change. I also print 1 first so that the factors are consistently increasing. At the end, the code prints szam if it is not 1, and adds a newline.
#include <stdio.h>
int main(void)
{
const int prim[20] =
{
2, 3, 5, 7, 11, 13, 17, 19, 23, 29,
31, 37, 41, 43, 47, 53, 59, 61, 67, 71,
};
enum { NUM_PRIM = sizeof(prim) / sizeof(prim[0]) };
int szam;
printf("Kerek egy szamot!\n");
if (scanf("%d", &szam) != 1)
return 1;
int i;
printf("1");
for (i = 0; i < NUM_PRIM && szam > 1; i++)
{
while (szam % prim[i] == 0)
{
szam = szam / prim[i];
printf("*%d", prim[i]);
}
}
if (szam > 1)
printf("*%d", szam);
putchar('\n');
return 0;
}
Example runs:
pr71
Kerek egy szamot!
48
1*2*2*2*2*3
LP2-US-51694112 JL: pr71
Kerek egy szamot!
47
1*47
LP2-US-51694112 JL: pr71
Kerek egy szamot!
46
1*2*23
$ pr71
Kerek egy szamot!
73
1*73
$ pr71
pr71
Kerek egy szamot!
166
1*2*83
$ pr71
Kerek egy szamot!
5329
1*5329
$
Only the last result is incorrect; 5329 is 73², so it is composite.
One of the many tests I ran processed the numbers in the range 5300..5330, and pr71 produced the filtered output:
1*2*2*5*5*53
1*3*3*19*31
1*2*11*241
1*5303
1*2*2*2*3*13*17
1*5*1061
1*2*7*379
1*3*29*61
1*2*2*1327
1*5309
1*2*3*3*5*59
1*47*113
1*2*2*2*2*2*2*83
1*3*7*11*23
1*2*2657
1*5*1063
1*2*2*3*443
1*13*409
1*2*2659
1*3*3*3*197
1*2*2*2*5*7*19
1*17*313
1*2*3*887
1*5323
1*2*2*11*11*11
1*3*5*5*71
1*2*2663
1*7*761
1*2*2*2*2*3*3*37
1*5329
1*2*5*13*41
This agrees with the output from another program factoring the same range — except for the second last line where 5329 is properly factored:
5300: (2^2).(5^2).53
5301: (3^2).19.31
5302: 2.11.241
5303: 5303
5304: (2^3).3.13.17
5305: 5.1061
5306: 2.7.379
5307: 3.29.61
5308: (2^2).1327
5309: 5309
5310: 2.(3^2).5.59
5311: 47.113
5312: (2^6).83
5313: 3.7.11.23
5314: 2.2657
5315: 5.1063
5316: (2^2).3.443
5317: 13.409
5318: 2.2659
5319: (3^3).197
5320: (2^3).5.7.19
5321: 17.313
5322: 2.3.887
5323: 5323
5324: (2^2).(11^3)
5325: 3.(5^2).71
5326: 2.2663
5327: 7.761
5328: (2^4).(3^2).37
5329: (73^2)
5330: 2.5.13.41
Thank you very much for the replies! I didn't know the increment could never be done by "+1". I applied your suggestions, and it works as wanted.
#include <stdio.h>
int main()
{
int prim[20]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71},szam,i=0;
printf("Kerek egy szamot!\n");
scanf("%d",&szam);
while(szam!=1)
{
if(szam%prim[i]==0)
{
szam=szam/prim[i];
printf("%d*",prim[i]);
}
else
{
prim[i]=prim[i++];
}
}
printf("1");
return 0;
}
The program is supposed to swap neighbouring elements which don't have a common denominator, and an element can only be swapped once.
When i run the program, pretty much for any input works fine. Except for this one:
100 //input for number of elements
48 92 76 93 17 38 59 34 53 99 58 20 50 0 38 37 16 36 91 12 59 1 76 82 20 76 7 72 13 70 64 23 81 70 41 69 11 0 16 41 37 83 41 99 73 79 4 38 24 32 87 38 95 24 77 30 61 13 89 67 87 76 22 31 67 31 25 90 6 76 21 43 40 55 72 91 91 28 18 58 72 71 83 22 99 23 86 58 75 53 69 29 5 55 46 8 98 55 19 46 //the elements
For this input, the program hangs and prints nothing. Does someone know what is going on in this particular case?
#include <stdio.h>
int nzd(int a, int b)
{
if(a==b || b==0)
return a;
if(a>b)
return nzd(a-b, b);
return nzd(a, b-a);
}
int swap(int *niza, int i)
{
int temp;
temp=*(niza+i);
*(niza+i)=*(niza+i+1);
*(niza+i+1)=temp;
}
int main()
{
int a[100], n, i;
scanf("%d", &n);
for(i=0; i<n; i++)
{
scanf("%d", &a[i]);
}
for(i=0; i<n; i++)
{
if(i+1==n) continue;
if(nzd(a[i], a[i+1])==1)
{
swap(a, i);
i++;
}
}
for(i=0; i<n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
Your gcd function checks for the case of b==0 but not the case for a==0. Because you skip that check, you end up calling nzd(0, b-0); which is exactly the same as the prior call. This puts you in an infinite recursion loop which will eventually cause a stack overflow.
Add the check for this case in your function:
if(a==b || b==0 || a == 0)
Also, a faster implementation of gcd, called Euclid's algorithm, is as follows:
int gcd(int a, int b)
{
if (b==0) {
return a;
} else {
return (b, a%b);
}
}
Your function nzd() fails to handle the case a == 0 correctly and gets stuck in an endless loop. You need to handle this case, too:
int nzd(int a, int b)
{
if(a==b || a==0 || b==0)
return a;
if(a>b)
return nzd(a-b, b);
return nzd(a, b-a);
}
I want to generate a series of "random" unique numbers, for use at a card game! These numbers should be between 0 and 81.
I don't care about security or speed at this stage, i just want something simple to have the work done.
In my code below, i have managed to create 2 unique random numbers in the array that holds them, but the rest 10 numbers don't change but stay -1 that was the initial value..
I have found more accurate ways for random number generation, but i will check them out at a later stage!
#include <stdio.h>
#include <stdlib.h>
int getRandomNumber(int Min, int Max)
{
double rnd= (double)rand()/((double)RAND_MAX+1);
return (int)(rnd*(Max-Min+1))+Min;
}
int main()
{
int j,counter,temp,deck[13];
srand(time(NULL));
int i;
counter=1;
for (i=0;i<12;i++)
{deck[i]=-1;
temp = getRandomNumber(0,81);
for (j=0;j<=i;j++)
{if (temp==deck[j])
{counter=0;}
if (counter!=0)
deck[i]=temp;
}
}
for(i=0;i<12;i++)
printf("%d ",deck[i]);
}
Your code has one of the weirder indentation and brace layout schemes I've ever seen:
#include <stdio.h>
#include <stdlib.h>
int getRandomNumber(int Min, int Max)
{
double rnd= (double)rand()/((double)RAND_MAX+1);
return (int)(rnd*(Max-Min+1))+Min;
}
int main()
{
int j,counter,temp,deck[13];
srand(time(NULL));
int i;
counter=1;
for (i=0;i<12;i++)
{deck[i]=-1;
temp = getRandomNumber(0,81);
for (j=0;j<=i;j++)
{if (temp==deck[j])
{counter=0;}
if (counter!=0)
deck[i]=temp;
}
}
for(i=0;i<12;i++)
printf("%d ",deck[i]);
}
Converted to a more orthodox style (Allman, more or less — see Wikipedia on Indent style), you get:
#include <stdio.h>
#include <stdlib.h>
static int getRandomNumber(int Min, int Max)
{
double rnd = (double)rand() / ((double)RAND_MAX + 1);
return (int)(rnd * (Max - Min + 1)) + Min;
}
int main(void)
{
int j, counter, temp, deck[13];
srand(time(NULL));
int i;
counter = 1;
for (i = 0; i < 12; i++)
{
deck[i] = -1;
temp = getRandomNumber(0, 81);
for (j = 0; j <= i; j++)
{
if (temp == deck[j])
{
counter = 0;
}
if (counter != 0)
deck[i] = temp;
}
}
for (i = 0; i < 12; i++)
printf("%d ", deck[i]);
}
The static and int main(void) are needed to get the code past my default compilation options; otherwise, they're cosmetic.
Now we can see some problems. The counter is set to 1 once, outside the outer loop; it is set to 0 sometimes inside the loop, but once that happens, it is never reset to 1, so no further numbers are added to the deck. You need to rework the inner loop, maybe like this:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
static int getRandomNumber(int Min, int Max)
{
double rnd = (double)rand() / ((double)RAND_MAX + 1);
return (int)(rnd * (Max - Min + 1)) + Min;
}
int main(void)
{
int deck[13];
srand(time(NULL));
for (int i = 0; i < 12; i++)
{
int temp = getRandomNumber(0, 81);
deck[i] = -1;
int counter = 1;
for (int j = 0; j <= i; j++)
{
if (temp == deck[j])
{
counter = 0;
break;
}
}
if (counter != 0)
deck[i] = temp;
else
i--; // Try again with a new random choice for the same i
}
const char *pad = "";
for (int i = 0; i < 12; i++)
{
printf("%s%d", pad, deck[i]);
pad = " ";
}
putchar('\n');
return 0;
}
I dislike trailing blanks, so the printing loop takes care to ensure there aren't any.
Sample output with getRandomNumber() — on macOS Sierra 10.12.2 with GCC 6.3.0:
7 73 38 61 11 13 41 66 29 39 72 20
7 2 18 17 54 31 45 40 34 22 63 16
7 13 80 54 16 49 14 58 28 53 23 26
7 24 60 10 67 53 69 32 23 2 66 12
7 34 40 48 21 3 57 43 6 18 27 80
7 45 20 3 65 21 61 17 12 69 66 27
7 67 62 78 70 57 68 46 9 2 72 39
7 77 41 34 32 75 72 20 64 78 33 25
7 6 21 72 76 11 75 38 73 27 64 33
7 17 1 27 37 28 80 49 12 67 59 36
That first number isn't very random — shortly after that sequence of tests, it changed from 7 to 8, but was equally non-random. An alternative
way of generating random numbers is:
static int getRandomNumber(int Min, int Max)
{
int rnd;
int range = (Max - Min + 1);
while ((rnd = rand()) > RAND_MAX - (RAND_MAX % range))
;
return (rnd % range) + Min;
}
This avoids the bias from that fact that 82 doesn't divide RAND_MAX exactly, which would weight the distribution of the lower numbers slightly higher than the upper numbers in the range 0..81. It also avoids the unexpectedly consistent first number, though the new first number is also semi-predictable when the tests are run at 1-second intervals.
Sample results:
48 33 28 78 14 2 81 13 23 75 38 40
45 42 74 1 11 68 17 33 78 49 23 80
42 51 38 3 5 52 35 56 54 23 59 41
39 60 2 8 36 53 79 30 72 75 62 37
36 69 45 10 78 20 71 17 6 53 54 30
33 78 9 15 75 7 40 61 27 36 70 68
30 5 55 17 69 73 25 63 37 1 21 71
27 14 19 66 57 43 1 13 3 65 71 21
24 26 62 63 41 61 68 28 67 20 74 17
21 35 26 57 28 79 47 44 2 52 60 77
Notice that the first number decreases by 3; the second seems to increase by 9; ugh — the randomness isn't all that good. It's well known that rand() is often not a high quality PRNG (pseudo-random number generator), but I'm a little surprised by this apparently systematic behaviour with seeds that differ by 1 each time.
On my Mac, when I changed srand() to srandom() and rand() to random(), I got better (as in, more unpredictable) results:
29 1 7 11 25 52 63 15 26 55 75 64
40 4 64 18 8 57 73 27 38 15 60 28
43 3 27 17 1 58 26 72 73 18 20 7
76 16 27 43 64 20 63 30 35 17 33 57
79 47 32 33 6 30 35 7 38 55 25 61
69 57 79 75 15 54 5 35 21 46 65 61
30 79 66 14 56 39 19 8 50 47 76 33
62 65 81 44 52 39 25 30 54 12 24 68
27 49 60 72 53 35 14 41 63 46 45 65
67 39 9 11 60 19 64 73 43 17 21 26
And the Mac man page for random() still suggests using arc4random() instead, but this is a lot better than plain rand(). What you find on other systems will depend on the facilities provided by the system — rand() may not be as awful as it seems to be on Mac. Basically, be cautious with your choice of PRNG — especially if you're going to use systematically generated seeds (such as the current time).
For the purpose you propose (generating a random sequence of numbers ranging from 0 through 81, where each item differs from the others), you will need a particular kind of random number generator (RNG), one that can generate all possible permutations of 82 items (expressed as 82!, or 82 factorial). However, only a limited selection of RNGs can do this. In particular the C rand() function's implementation is unspecified, so is not guaranteed to generate that many permutations.
A pseudorandom number generator (PRNG, a kind of RNG as used here) can't generate more random number sequences than its period. For 82! permutations, no PRNG with a period less than 82! can do this (the next highest power of 2 is 2408, meaning the generator needs to takes a seed at least 408 bits, or 51 bytes, long for it to possibly do so -- and 51 bytes is much bigger than srand can usually take). Alternatively, for this purpose, you would be well advised to use an RNG that generates "unpredictable" numbers, which neither the C language nor the C library includes as standard. See "Shuffling" and "Unpredictable RNGs" in my article on randomness for more information.
I'm trying to do a partial sort with a threads,
my current output it
27 12 21 48 15 28 82 69 35 91
13 82 33 35 46 5 35 28 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
33 50 9 6 13 27 97 21 70 22
3 4 6 6 7 15 34 59 63 70
As you can see I am getting it partially sorted I want my output to be this (no merging at the end)
12 15 21 27 28 35 48 69 82 91
5 13 28 33 35 35 46 82 87 95
0 10 20 22 23 30 52 80 86 96
3 8 42 53 67 70 70 71 75 79
5 8 8 18 41 43 70 79 86 88
10 51 56 60 65 84 87 91 94 99
23 25 38 39 40 44 51 56 69 75
20 21 25 29 29 38 66 71 73 96
6 9 13 21 22 27 33 50 70 97
3 4 6 6 7 15 34 59 63 70
I can get the right output if instead of using a struct I use &array[i] and manually input the length
This is the code I have so far:
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <pthread.h>
int cmpfunc(const void *a, const void *b) {
return (*(int*)a - *(int*)b);
}
struct values {
int *arrayptr;
int length;
};
void *thread_fn(void *a) {
struct values *start = a;
qsort(start->arrayptr, start->length, sizeof(int), cmpfunc);
return (void*)a;
}
int main(int argc, const char *argv[]) {
FILE *fp = fopen(argv[3], "r");
FILE *fp1 = fopen("numS1.dat", "w+");
//amount of threads
int threadAmount = atoi(argv[1]);
//size of input
int numberAmount = atoi(argv[2]);
//multidimensional array
int array[threadAmount][numberAmount / threadAmount];
for (int i = 0; i < threadAmount; i++)
for (int j = 0; j < numberAmount / threadAmount; j++)
fscanf(fp, "%d", &array[i][j]);
pthread_t threadid[threadAmount];
for (int i = 0; i < threadAmount; ++i) {
struct values a = { array[i], numberAmount / threadAmount };
pthread_create(&threadid[i], NULL, thread_fn, &a);
}
for (int i = 0; i < threadAmount; ++i)
pthread_join(threadid[i], NULL);
for (int i = 0; i < threadAmount; i++) {
if (i != 0)
fprintf(fp1, "\n");
for (int j = 0; j < numberAmount / threadAmount; j++)
fprintf(fp1 ,"%d ", array[i][j]);
}
return 0;
}
Do you know where I am going wrong?
I think its the struct but everything I see online does what I'm doing.
You are passing a pointer to automatic storage to newly created threads: the struct values object becomes invalid as soon as the calling scope is exited, thus it cannot be reliably accessed by the new thread. You should allocate the struct values and pass the pointer to the allocated object as a parameter to pthread_create:
for (int i = 0; i < threadAmount; ++i) {
struct values *a = malloc(sizeof(*a));
a->arrayptr = array[i];
a->length = numberAmount / threadAmount;
pthread_create(&threadid[i], NULL, thread_fn, a);
}
The structure can be freed by the thread function before exiting.
Notes:
the way you split the array into chunks only works if the length is a multiple of the number of threads.
the comparison function does not work for large int values, you should use this instead:
int cmpfunc(const void *a, const void *b) {
return (*(int*)b < *(int*)a) - (*(int*)a < *(int*)b);
}
I'm trying to submit the solution for Spoj - Prime Intervals problem. But I'm getting a runtime error SIGXFSZ. It is given that, it occurs due to exceeded file size. I have used the Sieve of Eratosthenes algorithm to find the prime numbers. I don't understand what's wrong with my code and this is bugging me from last the 2 days. Please help me with the submission. Here is my code...
#include<stdio.h>
#include<string.h>
#include<stdbool.h>
#include<math.h>
int main(){
int t, turn;
long i, l,u,k,j;
scanf("%d", &t);
/*Looping for t test cases*/
for(turn=0; turn<t; turn++){
scanf("%ld %ld", &l, &u);
bool arr[u-l+1];
/*Assigning whole array with true*/
memset(arr, true, u-l+1);
/*Sieve of Eratosthenes logic for assigning false to composite values*/
for(i=0; i<=(int)sqrt(u)-l; i++){
k=0;
j = i+l;
if(arr[i]==true){
while((j*j + k*j) <= u){
arr[(j*j + k*j) - l] = false;
k++;
}
}
}
/*Printing all the primes in the interval*/
for(i=0; i<u-l; i++){
if(arr[i]==true){
printf("%ld\n", i+l);
}
}
}
return 0;
}
Test Input:
2
2 10
2 100
Output:
2
3
5
7
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
I ran the posted code. the results were far from correct.
Most of the numbers output are not primes and fails to check the last number is the range, as shown in the second set of results
Here are the results:
1 <-- 1 test case
20 100 <-- range 20...100
20 <-- the outputs
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
Note: using 1 as the low end of the range usually results with no output produced
here is another run
The output should have been 5 7 11
1 <-- test cases
5 11 <-- range
5 <-- outputs
6
7
8
9
10
The following code does not try to minimize the size of the arr[] array, and if the upper end of the range is less than 16k then could declare the arr[] as short rather than unsigned int
The lowest valid value for the low end of the input is 2, but the code is not checking for that low limit, you might want to add that check.
The code makes no effort to minimize the number of loops executed by checking for the square root of the upper limit, you might want to add that check.
The code compiles cleanly, handles the case when the upper limit is a prime and when the lower limit is a prime as well as when the limit values are not primes.
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
int numTestCases, testCase;
size_t i; // index
size_t lowLimit;
size_t upperLimit;
size_t k; // offset multiplier
scanf("%d", &numTestCases);
/*Looping for t test cases*/
for(testCase=0; testCase<numTestCases; testCase++)
{
scanf("%lu %lu", (unsigned long*)&lowLimit, (unsigned long*)&upperLimit);
unsigned arr[upperLimit+1];
/*Assigning whole array to indicate entry is a prime*/
memset(arr, 0x01, upperLimit+1);
/*Sieve of Eratosthenes logic for assigning false to composite values*/
//size_t sqrtUpperLimit = (size_t)ceil(sqrt(upperLimit));
for(i=2; i<= upperLimit; i++)
{
if(arr[i])
{
if( i >= lowLimit )
{
printf("%ld\n", i);
}
for( k=2; (i*k) <= upperLimit; k++)
{
arr[(i*k)] = 0;
}
}
}
}
return 0;
} // end function; main
here is an edited version of the code, with the addition of some instrumentation in the way of prompts to the user via calls to printf()
#include <stdio.h>
#include <string.h>
#include <math.h>
int main()
{
int numTestCases, testCase;
size_t i; // index
size_t lowLimit;
size_t upperLimit;
size_t k; // offset multiplier
printf("enter number of test cases\n");
scanf("%d", &numTestCases);
/*Looping for t test cases*/
for(testCase=0; testCase<numTestCases; testCase++)
{
printf( "enter lower limit upper limit limits\n");
scanf("%lu %lu", (unsigned long*)&lowLimit, (unsigned long*)&upperLimit);
unsigned arr[upperLimit+1];
/*Assigning whole array to indicate entry is a prime*/
memset(arr, 0x01, upperLimit+1);
/*Sieve of Eratosthenes logic for assigning false to composite values*/
//size_t sqrtUpperLimit = (size_t)ceil(sqrt(upperLimit));
for(i=2; i<= upperLimit; i++)
{
if(arr[i])
{
if( i >= lowLimit )
{
printf("%ld\n", i);
}
for( k=2; (i*k) <= upperLimit; k++)
{
arr[(i*k)] = 0;
}
}
}
}
return 0;
} // end function; main
Using the above instrumented code and the input of:
5 2 3 30 31 20 27 2 3 4 5
it worked perfectly.
This was the output:
enter number of test cases
5
enter upper/lower limits
2 3
sizeof arr[]: 4
2
3
enter upper/lower limits
30 31
sizeof arr[]: 32
31
enter upper/lower limits
20 27
sizeof arr[]: 28
23
enter upper/lower limits
2 3
sizeof arr[]: 4
2
3
enter upper/lower limits
4 5
sizeof arr[]: 6
5