Sieve for 8 digit primes - c

I am not able to find prime numbers of 8 digits in spite of increasing size of array a. It is working for smaller numbers:
#include<stdio.h>
#include<math.h>
int main()
{
int n,a[100000],i,m,k;
scanf("%d",&n);
for (i=2;i<=n;i++)
a[i]=1;
m=(sqrt(n)+1);
for (i=2;i<=m;i++)
if (a[i]==1)
for (k=i*i;k<=n;k+=i)
a[k]=0;
for (i=0;i<=n;i++)
if (a[i]==1)
printf("%d\t",i);
return 0;
}

I could not get larger than 6 digits either by using the locally declared array. Such an array uses stack memory, which is in short supply compared to heap memory. The other problem is that you didn't check if the value entered for n will break the fixed size array that you declared. I solved both problems by using malloc() to allocate the exact amount of memory required, from the heap, and checked to see if the memory allocation worked.
The other small thing I tidied up was the use of \t to format the output. Once the numbers get large that will look messy. I gave a field width of 10 because that will contain an 8-digit number, also because most text terminals have a width of 80, so the numbers won't break across lines.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int n,i,m,k;
int *a;
scanf("%d",&n);
if ((a = malloc((n+1)*sizeof(int))) == NULL) {
printf ("Not enough memory\n");
exit (1);
}
for (i=2;i<=n;i++)
a[i]=1;
m=(sqrt(n)+1);
for (i=2;i<=m;i++)
if (a[i]==1)
for (k=i*i;k<=n;k+=i)
a[k]=0;
for (i=0;i<=n;i++)
if (a[i]==1)
printf("%10d",i);
printf("\n");
free (a);
return 0;
}

Related

function declaration and call and definition in c

Why is this code not running after printing of array if I take value of n>=9?
#include <stdio.h>
#include <math.h>
float mean_function(float array[],int n);
int main() {
int i,n;
float array[n],mean,sum=0,s2,summation,deno,C[i],elements;
printf("Enter No of Elements\n");
scanf("%d",&n);
printf("Enter Elements\n");
for(i=0;i<n;i++){
scanf("%f",&array[i]);
printf("%f",array[i]);
}
printf("sample variance(s2) : (sum((x-mean)*(x-mean)))/(n-1) /n");
printf("population variance(sigma2) : (sum((x-u)*(x-u))/n");
mean_function(array,n);
for(i=0;i<n;i++) {
deno=((array[i]-mean)*(array[i]-mean));
C[i]=deno;
summation=summation+C[i];
}
s2=((summation)/(n-1));
printf("s2=%f \n",s2);
}
float mean_function(float array[],int n) {
int i;
float sum=0,mean;
for(i=0;i<n;i++){ sum=sum+array[i]; }
mean=(sum/n);
return mean;
}
Why is this code not running after printing of array if I take value
of n>=9?
Some thoughts about your code (and about building programs in steps):
Arrays in C don't change in size once defined. VLAs are out for a variety of reasons. malloc() is in.
Use double, unless there is a specific reason to use floats.
Define and initialize one variable per line. Uninit vars can only result in an error as mentioned by #Jens.
Function declarations at the top (which you have done)
During development, there is no need to complicate things with a scanf (at least initially). It only adds an unwarranted layer of complexity. If you are testing statistical functions (mean, variance), put numbers in a pre-defined static array and verify functionality first.
C[i] as been declared with uninitialized i.
For this initial phase of building this program, I include a basic program.
I am not a fan of zero space between tokens (but ignore that)
Consider calling your array something other than 'array'.
Calculating the size of the samples array allows you to change the number of elements without changing anything else in code; which adds another layer of complexity to an already difficult phase.
#include <stdio.h>
#include <math.h>
double sample_mean(double* p, int n);
int main()
{
double samples[] = {1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 16.5, 2.3};
double mean = 0.0;
int size_samples = sizeof samples/sizeof(double);
printf("size_samples = %d\n", size_samples);
mean = sample_mean(samples, size_samples);
printf("Mean = %.2lf", mean);
}
// -------------------------------
double sample_mean(double* p, int n)
{
double mean = 0.0;
double total = 0.0;
for(int i = 0; i < n; i++)
total += *p++;
mean = total/n;
return mean;
}
Once this functionality is present (saved), you can start working on other stat functions. This way you can work step by step to get closer to the desired outcome.
Next up you can define sample_variance(double* p, int n) and work on that knowing that additional(new errors) are not coming from your code written so far.
Output:
size_samples = 8
Mean = 5.24
I hope it helps.
The code is likely not running because array[n] is declared with an uninitialized n. At the time you read n with scanf(), the array does not automatically "grow into the right size". You should either declare array big enough, or if you really want it to be user-defined, use malloc to allocate it (read the comp.lang.c FAQ) and all Stackoverflow questions tagged array...)
In addition, the scanf at some point fails. Note that when you enter numbers, you also have the "Enter" as a newline ('\n') in the input stream. You never read the newline so the next scanf fails.
This becomes obvious when you actually check the return value from scanf with code like this:
if (scanf("%f", &array[i]) == 1) {
/* successfully converted 1 item */
}
else {
/* scanf failed */
}
Usually what you want is to skip whitespace in the input. You do this by placing a space in the scanf format. Note that a single space tells scanf to skip any amount of white-space.
if (scanf(" %f", &array[i]) == 1) {

Coverting To Bytes In C

My teacher has developed a server that generates random characters and numbers. I need to create a program that takes what is generated and put it in standard input form and find the amount of bytes using the sizeof() operator. Also, if a random end of file occurs then it should generate a message and how many bytes have come through. I am a basic coder and need a little help with my program because I have no clue where to go from here to fix my mistake.
#include <stdlib.h>
#include <stdio.h>
int main () {
int input;
int sum;
int size;
do {
size = sizeof(input);
sum =+ size;
input = 0;
} while (scanf("%c", &input)!=EOF);
if (EOF) {
printf("Random End of File Has Occured.\n%d Bytes Have Been Received.", sum);
}
else {
printf("End of Transmission Completed.\n%d Bytes Have Been Received.", sum);
}
return 0;
}
Here is an example of what I need it to look like:
Example
267.625293748653
5233.717459639272
29779
6489
3579.434430982391
28896
8834
3152.852412488174
25321
8320
28836
8875.864858351391
9539.445326098274
3859.598437452315
12345
195.324900951882
25139
22473
595.885992279732
2765.982421338542
6554.456891649837
5822.693258461257
9979.479628894926
193.095583971679
9349.095348739159
7462
Read 447 bytes from standard input
C:\Users\Brett\Downloads\hw2 (1)>
There are two things you will need to fix.
You need to initialize sum = 0; before you start adding size to it sum += size;. The way you have it now the sum variable has been initialized with garbage because it is on the stack. Essentially, you are adding a known size to a garbage value.
Your code is not adding size to sum. You need to change sum =+ size; to sum += size;
Hope this helps!

Getting segmentation fault while scanning an integer value

Though this is strange, but I am getting a segmentation fault while scanning an integer value.
Here is my program :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int t,n,i,j;
char c;
int grid[1000][1000],right[1000][1000],down[1000][1000];
scanf("%d",&t);
printf("hello\n");
while(t--)
{
scanf("%d",&n);
memset(right, 0, sizeof(int) * 1000 *1000);
memset(down, 0, sizeof(int) * 1000 *1000);
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
scanf("%c",&c);
printf("CHAR = %c\n", c);
if(c == '.')
grid[i][j] = 1;
else
grid[i][j] = 0;
}
}
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
printf("%d",grid[i][j]);
}
}
}
return 0;
}
Doing gdb shows segmentation fault at line scanf("%d",&t);. I cannot figure out how this is happening?
[Using gcc-4.8.4 on a linux 32-bit machine ]
The problem is that your arrays: grid, right and down are too big to fit into the stack.
As far as the reason for no compile error is concerned:
Because there is nothing wrong with this code in terms of syntax or semantics. The linker also does not have any problem.
The problem arises when the loader tries to load the program and allocate that much memory on the stack. The stack is usually 8 MB on linux systems and your arrays surpass that.
You can make them static (as suggested in the comments) as static members are allocated on the bss or data segment. But in reality you need to rethink if you need such big arrays.
Set you linker to instruct the loader to allocate a max stack segment limit that is large enough to fit your big local array.

Segmentation fault while loading big txt.file into C program

I wrote a program in C langage. I have no problems when trying to run it with my small txt file as an argument. Unfortunately when i am trying to load much bigger file, i am getting Segmentation fault (core dumped. Even 1 line of my main function is not executed. Here is part of code responisble for starting and loading txt file as my argv[1] argument.I dont really see where is the problem.Big Txt files are about 13 MB. I am working linux(ubuntu). I would be grateful for help.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int x;
int y;
int wage;
}Edge;
int main(int argc, char *argv[]) {
printf("Program starts");
int x,y,z;
int counter = 1;
int N,E; //node,edges
FILE *fid;
fid = fopen(argv[1],"r");
fscanf(fid,"%d%d",&N,&E);
Edge Graph[E];
int visited[N+1];
while(counter <= E){
fscanf(fid, "%d%d%d", &x, &y,&z);
Graph[counter-1].x=x;
Graph[counter-1].y=y;
Graph[counter-1].wage=z;
counter=counter+1;
}
printf("\nWe load all edges. Here is our Graph");
fclose(fid) ;
printf("Program ends");
return 0;
}
First some approximations:
With 13MB of data, your text file contains certainly over 1 million of edges (assuming that node x and y are each representend in average with 3 digits followed by a space, wage in average 1 digit followed by a space) and at least 1400 nodes.
Your variable length arrays Graph[E] and visited[N+1] are local variables, hence stored on the stack. Assuming 4 bytes per integer, that's more than 12 MB of data to put on the stack.
The amount of data that you require on the stack exceeds the usal default stack size on most linux system (8 MB).
You could consider increasing the stack size as explained in this SO question.
But you should really better consider dynamic allocaton:
Edge *Graph = calloc (sizeof(Edge),E);
int *visited = calloc (sizeof(int), N+1);
if (Graph==NULL || visited==NULL) {
printf ("Oops ! Out of memory (%d edges, %d notes) !!", E, N+1);
exit (1); // or some other kind of error handling
}

C program to find the n'th prime number-

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
int prime(long long int);
long long int *arr; //array to hold n prime numbers
int main()
{
int i,count=4;;
long long int n;
scanf("%lli",&n);
arr=malloc(sizeof(long long int)*n);
arr[0]=2;
arr[1]=3;
arr[2]=5;
arr[3]=7;
if (n==1) printf("%lli",arr[0]);
else{ if (n==2) printf("%lli",arr[1]);
else{ if (n==3) printf("%lli",arr[2]);
else{ if (n==4) printf("%lli",arr[3]);
else
{
for(i=2;count<n;i++)
{
if(prime(6*i-1)) { /*As prime nos are always 6k+1 or
arr[count]=6*i-1; 6k-1fork>=2 I checked only for those*/
count++; }
if(prime(6*i+1)&&count<=n) {
arr[count]=6*i+1;
count++; }
}
printf("%lli",arr[count]);
}}}}
//free(arr);
return 0;
}
int prime(long long int x)
{
int j=1,flag=1;
while(arr[j]<=sqrt(x))
{
if (x%arr[j]==0)
{
flag=0;
break;
}
j++;
}
return flag;
}
The code is working only for n=1,2,3,4, i.e i=0,1,2,3 for which the values are explicitly given. For n=5 onwards it is giving 0 as O/P
There is some glitch related to the global dynamic array as free(arr) is giving core dump error.
Q: Is this the right way to declare a global dynamic array? What could be the problem in this code?
Thank You in advance.
If that is your actual code you have 4 bugs:
2 line comment scopes out a line of your code
the second if should check count < n not count <= n as if count == n you cannot write to arr[count]
You cannot print arr[count] only arr[count-1] which is probably what you mean
In the case where n is less than 4 you still set arr[1], arr[2] and arr[3] which may be out of bounds
It is of course also inefficient to call sqrt(x) in every loop iteration, potentially you should call it outside and there may be a potential rounding issue bug due to the way square roots are calculated, so you might prefer:
while( arr[j] * arr[j] < x )
It would be preferable not to make this global and to pass it into your function.
It would also be preferable to move the main loop logic of your program outside of main().
I'm surprised you say you program works for n=1, 2 and 3 as it looks like you are setting out of bounds.
Your counter goes beyond the size of the array. Specifically both conditions (6i-1 and 6i+1) are met for i=2, and therefore counter is incremented twice, resulting in using arr[5] where you only allocated 5 places in the array. This is because you check counter<=n and not counter
Not sure this could be also be the reason for free creating a core dump, but it is possible (because once corrupting the memory, free may access corrupted data).

Resources