Unsure if structure has been initialised - c

From my last post I'm dealing with my code block by block to make sure it's all working and there's something very strange going on.
If you look at my code, when it comes to initialising the structure with the unique student IDs it will happily print them after each one has been initialised inside the for loop (which suggests to me it's obviously done it) but, however, when I want to print them again outside the for loop in another for loop as a "double-check" it goes horribly wrong, presumably they're not in there at all?
If you traverse the code to the bottom you'll see my comments.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define ROWS 80
#define SIZE 100
#define STUDENTS 20
int string_compare(void const *x, void const *y)
{
return strcmp(*(char**)x, *(char**)y);
}
struct student
{
char student_ID[SIZE];
};
int main(void)
{
FILE* input;
int i,j,data_items;
int records=0;
char buffer_IDs[ROWS][SIZE];
char buffer_subjects[ROWS][SIZE];
int marks[ROWS];
char *string_ptrs[ROWS];
struct student db[STUDENTS];
if((input=fopen("C:\\marks\\marks.txt", "r"))==NULL)
perror("File open failed!");
else
{
while ( ( data_items=fscanf(input, "%s %s %d", buffer_IDs[records], buffer_subjects[records], &marks[records])) == 3) {
printf("%s %s %d\n", buffer_IDs[records], buffer_subjects[records], marks[records]);
string_ptrs[records]=buffer_IDs[records];
records++;
if ( records > ROWS) {
break;
}
}
}
qsort(string_ptrs, records, sizeof(char*), string_compare);
for(i=0;i<records;i=i+4)
{
j=0;
strcpy(db[j].student_ID,string_ptrs[i]);
printf("%s\n",db[j].student_ID); /*Happily prints the unique IDs contained in the structure*/
j++;
}
for(i=0;i<STUDENTS;i++)
printf("%s\n",db[i].student_ID); /*Does NOT print them outside the for loop which initialises the structure. */
return 0;
}

Looks like your first for loop is always printing only the first student id. at the beginning of the loop, you set j as 0, and at the end you increment it. But, after each step of the loop, the j becomes 0 again.
So, only the first student id are being "initialized", and the next elements are all uninitialized.

Why is your "initialization" cycle jumps over 4 string pointers at each iteration
for(i=0;i<records;i=i+4)
...
?
This cycle will initialize only records / 4 elements in the db array. I.e. the final value of j will tell you how many elements in db have meaningful student_ID values. (And which will be only 1, since as Alef noted in his answer, you reset the value of j on each iteration of "initialization" cycle).
Later you print STUDENTS elements. STUDENTS and the final value of j are unrelated. What if STUDENTS is greater than j? Expectedly, you will print complete garbage from uninitialized elements of db.

Related

How to find the total number of a certain element in an array(C)

I'm trying to create a complete C program to read ten alphabets and display them on the screen. I shall also have to find the number of a certain element and print it on the screen.
#include <stdio.h>
#include <conio.h>
void listAlpha( char ch)
{
printf(" %c", ch);
}
int readAlpha(){
char arr[10];
int count = 1, iterator = 0;
for(int iterator=0; iterator<10; iterator++){
printf("\nAlphabet %d:", count);
scanf(" %c", &arr[iterator]);
count++;
}
printf("-----------------------------------------");
printf("List of alphabets: ");
for (int x=0; x<10; x++)
{
/* I’m passing each element one by one using subscript*/
listAlpha(arr[x]);
}
printf("%c",arr);
return 0;
}
int findTotal(){
}
int main(){
readAlpha();
}
The code should be added in the findTotal() element. The output is expected as below.
Output:
List of alphabets : C C C A B C B A C C //I've worked out this part.
Total alphabet A: 2
Total alphabet B: 2
Total alphabet C: 6
Alphabet with highest hit is C
I use an array to count the number of the existence of each character,
I did this code but the display of number of each character is repeated in the loop
int main()
{
char arr[100];
printf("Give a text :");
gets(arr);
int k=strlen(arr);
for(int iterator=0; iterator<k; iterator++)
{
printf("[%c]",arr[iterator]);
}
int T[k];
for(int i=0;i<k;i++)
{
T[i]=arr[i];
}
int cpt1=0;
char d;
for(int i=0;i<k;i++)
{int cpt=0;
for(int j=0;j<k;j++)
{
if(T[i]==T[j])
{
cpt++;
}
}
if(cpt>cpt1)
{
cpt1=cpt;
d=T[i];
}
printf("\nTotal alphabet %c : %d \n",T[i],cpt);
}
printf("\nAlphabet with highest hit is : %c\n",d,cpt1);
}
There is no way to get the number of elements You write in an array.
Array in C is just a space in the memory.
C does not know what elements are actual data.
But there are common ways to solve this problem in C:
as mentioned above, create an array with one extra element and, fill the element after the last actual element with zero ('\0'). Zero means the end of the actual data. It is right if you do not wish to use '\0' among characters to be processed. It is similar to null-terminated strings in C.
add the variable to store the number of elements in an array. It is similar to Pascal-strings.
#include <stdio.h>
#include <string.h>
#define ARRAY_SIZE 10
char array[ARRAY_SIZE + 1];
int array_len(char * inp_arr) {
int ret_val = 0;
while (inp_arr[ret_val] != '\0')
++ret_val;
return ret_val;
}
float array_with_level[ARRAY_SIZE];
int array_with_level_level;
int main() {
array[0] = '\0';
memcpy(array, "hello!\0", 7); // 7'th element is 0
printf("array with 0 at the end\n");
printf("%s, length is %d\n", array, array_len(array));
array_with_level_level = 0;
const int fill_level = 5;
int iter;
for (iter = 0; iter < fill_level; ++iter) {
array_with_level[iter] = iter*iter/2.0;
}
array_with_level_level = iter;
printf("array with length in the dedicated variable\n");
for (int i1 = 0; i1 < array_with_level_level; ++i1)
printf("%02d:%02.2f ", i1, array_with_level[i1]);
printf(", length is %d", array_with_level_level);
return 0;
}
<conio.h> is a non-standard header. I assume you're using Turbo C/C++ because it's part of your course. Turbo C/C++ is a terrible implementation (in 2020) and the only known reason to use it is because your lecturer made you!
However everything you actually use here is standard. I believe you can remove it.
printf("%c",arr); doesn't make sense. arr will be passed as a pointer (to the first character in the array) but %c expects a character value. I'm not sure what you want that line to do but it doesn't look useful - you've listed the array in the for-loop.
I suggest you remove it. If you do don't worry about a \0. You only need that if you want to treat arr as a string but in the code you're handling it quite validly as an array of 10 characters without calling any functions that expect a string. That's when it needs to contain a 0 terminator.
Also add return 0; to the end of main(). It means 'execution successful' and is required to be conformant.
With those 3 changes an input of ABCDEFGHIJ produces:
Alphabet 1:
Alphabet 2:
Alphabet 3:
Alphabet 4:
Alphabet 5:
Alphabet 6:
Alphabet 7:
Alphabet 8:
Alphabet 9:
Alphabet 10:-----------------------------------------List of alphabets: A B C D E F G H I J
It's not pretty but that's what you asked for and it at least shows you've successfully read in the letters. You may want to tidy it up...
Remove printf("\nAlphabet %d:", count); and insert printf("\nAlphabet %d: %c", count,arr[iterator]); after scanf(" %c", &arr[iterator]);.
Put a newline before and after the line of minus signs (printf("\n-----------------------------------------\n"); and it looks better to me.
But that's just cosmetics. It's up to you.
There's a number of ways to find the most frequent character. But at this level I recommend a simple nested loop.
Here's a function that finds the most common character (rather than the count of the most common character) and if there's a tie (two characters with the same count) it returns the one that appears first.
char findCommonest(const char* arr){
char commonest='#'; //Arbitrary Bad value!
int high_count=0;
for(int ch=0;ch<10;++ch){
const char counting=arr[ch];
int count=0;
for(int c=0;c<10;++c){
if(arr[c]==counting){
++count;
}
}
if(count>high_count){
high_count=count;
commonest=counting;
}
}
return commonest;
}
It's not very efficient and you might like to put some printfs in to see why!
But I think it's at your level of expertise to understand. Eventually.
Here's a version that unit-tests that function. Never write code without a unit test battery of some kind. It might look like chore but it'll help debug your code.
https://ideone.com/DVy7Cn
Footnote: I've made minimal changes to your code. There's comments with some good advice that you shouldn't hardcode the array size as 10 and certainly not litter the code with that value (e.g. #define ALPHABET_LIST_SIZE (10) at the top).
I have used const but that may be something you haven't yet met. If you don't understand it and don't want to learn it, remove it.
The terms of your course will forbid plagiarism. You may not cut and paste my code into yours. You are obliged to understand the ideas and implement it yourself. My code is very inefficient. You might want to do something about that!
The only run-time problem I see in your code is this statement:
printf("%c",arr);
Is wrong. At this point in your program, arr is an array of char, not a single char as expected by the format specifier %c. For this to work, the printf() needs to be expanded to:
printf("%c%c%c%c%c%c%c%c%c%c\n",
arr[0],arr[1],arr[2],arr[3],arr[4],
arr[5],arr[6],arr[7],arr[8],arr[9]);
Or: treat arr as a string rather than just a char array. Declare arr as `char arr[11] = {0};//extra space for null termination
printf("%s\n", arr);//to print the string
Regarding this part of your stated objective:
"I shall also have to find the number of a certain element and print it on the screen. I'm new to this. Please help me out."
The steps below are offered to modify the following work
int findTotal(){
}
Change prototype to:
int FindTotal(char *arr);
count each occurrence of unique element in array (How to reference)
Adapt above reference to use printf and formatting to match your stated output. (How to reference)

Printing last element in an array using if statement

I am currently trying to learn about using pointers and functions together in C, which I don't think is easy.
I am trying to print the last element in an array, it actually does the opposite and prints the first element.
I know people normally use for loops, but I can't figure out how to do that with exactly this kind of problem and therefore I thought that I would try it out with an if statement instead.
Edit:
Why is if statement not working in this case? It seems logic that it should work...
My main.c file:
#include <stdio.h>
#include <stdlib.h>
#include "functions.h"
#define Size 7
int main(void)
{
int array1[] = { 11, 88, 5, 9, 447, 8, 68, 4 };
maxValue(array1, Size);
return 0;
}
My functions.h file:
#pragma once
#ifndef FUNCTIONS_H
#define FUNCTIONS_H
int maxValue(const int *, int);
#endif
My functions.c file:
#include "functions.h"
#include <stdio.h>
#include <stdlib.h>
int maxValue(const int *array1, int Size)
{
int max = array1[0];
if (max < array1[Size]) {
Size++;
max = array1[Size];
}
printf("Max value: %d \n", max);
}
Why is if statement not working in this case? It seems logic that it should work...? Because here
if (max < array1[Size]) { }
Size is defined as 7 and you are comparing array1[0] with array1[7] i.e 11 < 4 -> false, hence it doesn't enter into if block, so the last printf executes and that prints max. But its not a correct logic if if blocks becomes true then further Size++ will cause accessing out of bound array elements which cause undefined behavior.
int maxValue(const int *array1, int Size)
{
int max = array1[0];
if (max < array1[Size]) { /* 11 < 4 false, skips if block */
//Size++; /* this is wrong as Size++ here and next accessing array1[Size] cause UB due to accessing out of bound array element */
max = array1[Size];
}
printf("Max value: %d \n", max); /* max is stills array1[0] i.e 11 */
}
Let's simulate what the CPU does when it enters the maxValue function with those arguments. 1. The variable max is assigned the value of array1[0], which is 11.
2. If max (11) is less than array1[7] (4). It is not, so the if block is not executed.
3. Print max: print 11.
Another thing: Your program causes undefined behaviour. Let's take an example where array1[0] is 3, instead of 11. The if block will be executed (3 < 4), so:
Size is incremented to 8.
max is assigned array1[8]. Since the last index in array1 is 7 (that is how you declared the array), you are accessing a memory adress which you are not supposed to access. This is undefined behaviour.
The names maxValue() and max are misleading and confusing what you are trying to do. lastValue() and last would make much more sense.
However what you are trying to do makes no sense in C because arrays are of known length, so you can access the last element directly:
int array1[] = { 11, 88, 5, 9, 447, 8, 68, 4 };
int array_length = sizeof(array1) / sizeof(*array1) ;
printf("Lastvalue: %d \n", array1[array_length - 1] ) ;
However you cannot do this in a function because arrays are not first class data types in C and when passed to a function will "degrade" to a simple pointer without any information regarding the size of the array pointed to. The calling function having the size information must pass that too (as you have done, but then appeared to get very confused):
void printLast( int* array, int length )
{
printf( "Lastvalue: %d \n", array1[length - 1] ) ;
}
It is difficult to see why you thought you might need any other code or what your maxValue() function is intended to achieve. The "logic" which you say "should work" is thus:
If value of the first array element is less than the value of the last array element, then print the undefined value one past the end of the array; otherwise print the first element of the array.
If you wanted to print the last element, then you simply print it, the value of the first element has nothing to do do with it. Either way you should not index past the end of the array - that value is undefined.

I m trying to build a 2*2 array but my program asks for 5 inputs. Why?

I couldn't zero down where i have missed in the input statement. I have build it to acquire four values as input but it goes one more.
manipulating the array entries to check if the fifth value is stored. Basic things
#include <stdio.h>
int main()
{
int i,j,a[2][2];
for(i=1;i<=2;i++)
{
for(j=1;j<=2;j++)
scanf("%d\t",&a[i][j]);
}
printf("\n%d\t%d\n%d\t%d", a[1][1],a[1][2],a[2][1],a[2][2]);
}
You have declared this
int a[2][2];
which has four items, a[0][0], a[0][1], a[1][0] and a[1][1].
However, you are starting your indexing at 1 and going up to 2, so are stepping out of bounds which is undefined behaviour.
Anything can then happen.
Change your loops i.e.:
for(i=0;i<2;i++)
{
for(j=0;j<2;j++)
// as you were
to index from 0.
You also need to consider your printf statement, since that oversteps too.
#include <stdio.h>
int main()
{
int i,j,a[2][2];
for(i=0;i<2;i++) /*go through rows - arrays in c go [0- (n-1)]*/
{
for(j=0;j<2;j++)/*go through col */
scanf("%d",&a[i][j]); /*remove \t- now will scan 4 values only */
}
printf("\n%d\t%d\n%d\t%d", a[0][0],a[0][1],a[1][0],a[1][1]);
return 0;
}

How to properly pass array pointers to function in C

A different question may have been asked about this program, however in this C code I have three functions: one to print records, one to add a record and one to delete a record.
What I don't understand is why the (add) and (delete) do not make changes in the main function, so when I use the print all records function it prints changes, but it doesn't show changes, what is wrong?
Details are in the comments, please feel free to run the code to visualise the problem.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*The program is to store student record (firstname,lastname and score), it should not be more
than 15 records and the names should not be more than 20 chars, array pointersnare being used
instead of arrays, the (add_record) and (delete_record) functions must
do thsi change in the main function, so when you print all records, the changes are shown*/
void print_records(char **firstname,char **lastname,float *score,int *the_size)
{
int i;
printf("Printing All record(s)...\n");
for (i=0;i<*the_size;i++) /*loop to print records of all arrays in correct format*/
{
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[i],lastname[i],score[i]);
}
}
void add_new_record (char **firstname,char **lastname,float *score,int the_size)
{
printf("Add new record in the format :\nFirstname Lastname Score\n");
/*the strategy here is to check if all 15 elemts are used, if they are, use realloc
to add one more, if not add the record after the last record*/
if (the_size == 15)
{
firstname=realloc(firstname,16*sizeof(char*));
firstname[15]=malloc((20+1)*sizeof(char));
lastname=realloc(lastname,16*sizeof(char*));
lastname[15]=malloc((20+1)*sizeof(char));
score=realloc(score,16*sizeof(float));
scanf("%s %s %f",firstname[15],lastname[15],&score[15]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[15],lastname[15],score[15]);
}
else if (the_size<15)
{
scanf("%s %s %f",firstname[the_size],lastname[the_size],&score[the_size]);
printf("New Record Added Successfully !\n");
printf("Firstname : %s, Lastname : %s, Score : %f\n",firstname[the_size],lastname[the_size],score[the_size]);
}
}
void delete_record (char **firstname,char **lastname,float *score,int the_size)
{
char *str=malloc(20*sizeof(char)); /*String entered by user must be 20 or less chars*/
int i,ctr=0;
char *temp_first=malloc(20*sizeof(char));/*temp array to swap firstname must be 20 or less chars*/
char *temp_last=malloc(20*sizeof(char)); /*temp array to swap lastname must be 20 or less chars*/
float temp_score;/*ctr is the counter used to check if there are no matchs in the end*/
printf("Enter the lastname of record(s) to delete : ");
scanf("%s",str);
/* the strategy here is to move the element to be deleted to the last index and use
relloc to shrink the size by 1 (-1) */
for (i=0;i< the_size;i++)
{
if (strcmp(str,lastname[i])==0)
{
printf("Deleting Record for %s %s...\n",firstname[i],lastname[i]);
temp_score=score[i];
score[i]=score[the_size-1];
score[the_size-1]=temp_score;
strcpy(temp_first, firstname[i]); /*using strcpy function to swap strings*/
strcpy(firstname[i], firstname[the_size-1]);
strcpy(firstname[the_size-1], temp_first);
strcpy(temp_last, lastname[i]);
strcpy(lastname[i], lastname[the_size-1]);
strcpy(lastname[the_size-1], temp_last);
score=realloc(score,(the_size-1)*sizeof(float));
firstname=realloc(firstname,(the_size-1)*sizeof(char*));
lastname=realloc(lastname,(the_size-1)*sizeof(char*));
ctr++;
the_size--;
}
}
if (!ctr) /*if ctr=0 (no increment), then print,there is no match*/
{
printf ("Sorry, no available record for %s",str);
}
free(temp_first);
free(temp_last);
free(str);
}
void main()
{
char **firstname;
char **lastname;
float *score;
int number_of_records,i,j=-1,ctr=1,row=15,col=20;
/*ctr is to keep track of the student's number (makes it easier to
the user), it starts with (1)*/
firstname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
firstname[i]=malloc((col+1)*sizeof(char));
}
lastname=malloc(row*sizeof(char*));
for(i=0;i<row;i++)
{
lastname[i]=malloc((col+1)*sizeof(char));
}
printf("\nPlease indicate number of records you want to enter (min 2, max 15): ");
scanf("%d",&number_of_records);
score=malloc(row*sizeof(float));
printf("\nPlease input records of students\n(enter a new line after"
"each record), with following format:\nfirst name last name score ");
for (i=0;i<number_of_records;i++)
{
printf("\nEnter record for student %d : ",ctr);
scanf("%s %s %f",firstname[i],lastname[i],&score[i]);
ctr++; /*ctr is to keep track of student number
(makes it easy to the user) */
}
while (j!=0) /*Main menu will keep looping after using a function as long as j is not 0
When the user enters 0 (zero) the loop will stop and therefore the program will terminate*/
{
printf("\nSelect desired function by pressing the corresponding key number\n");
printf("\n********** Main Menu **********\n");
printf("\n>>> Print records (press 1)\n");
printf("\n>>> Add a new Record (press 2 )\n");
printf("\n>>> delete record (press 3)\n");
printf("\n>>> Exit the program (press 0)\n");
scanf("%d",&j); /*getting j from the user (j is used for selection and for the while loop)*/
if (j==1)
{
print_records(firstname,lastname,score,&number_of_records);
}
else if (j==2)
{
add_new_record(firstname,lastname,score,number_of_records);
}
else if (j==3)
{
delete_record(firstname,lastname,score,number_of_records);
}
else if (j==0)
{
printf("Exitting program ...\n");
}
}
}
As other answers have observed, in C, all arguments are passed by value. That means the function gets a copy of the caller's value, therefore changes to that value are not visible to the caller. In other words, given
void f(any_type arg) {
arg = any_value;
}
The caller will never detect any change, regardless of what type any_type is or what value any_value is. Note carefully, however, the difference between that, and this:
void f(any_type *arg) {
*arg = any_value;
}
In that case, it is not the function argument (a pointer) that is being modified, it is the thing pointed to. The argument is a copy of the caller's value, so the two point to the same thing. The caller cannot detect changes to the argument, but after the call, it can detect changes to the thing it points to.
Your code exhibits some issues of this type, some of them responsible for your main problems. Most importantly, these have to do with your record keeping on the number of elements in your list (variable number_of_records in main()). Your addition and deletion functions work more or less ok, except that they cannot communicate the revised list size back to main.
There are additional issues in add_new_record() when there are already 15 records; if you can, I would just disallow that case. If you must support it, then you have multiple things to clean up. Some of them to do with pass-by-value issues, others to do with what your code should do when the list initially contains 16 or more records.
Update:
Since you're having so much trouble working this out, here's a revised version of delete_record(). It implements a lot more than the minimal changes required to get the desired output upon record deletion, as there was in fact a goodly number of other issues that I might as well call out as long as I'm going to the trouble. See new and modified comments.
/*
* Can realloc() *firstname, *lastname, and *score and return the updated
* values to the caller. Most importantly, can update *the_size and have
* the caller see the result.
*/
void delete_record (char ***firstname, char ***lastname, float **score, int *the_size)
{
int i;
int initial_size = *the_size;
char str[21]; /* no need to malloc a fixed-length local array */
printf("Enter the lastname of record(s) to delete : ");
fflush(stdout); /* The prompt might not appear if you don't flush */
/*
* Note the field width in the format below. Without it, a user can
* easily cause a buffer overflow.
*/
scanf("%20s", str);
/*
* The strategy for each element to delete (there may be more than one)
* is to free the element's name components (else their allocated memory
* leaks), copy the last (at that time) element's components into
* place (for the name components, just the pointers), and later
* realloc to shrink the overall size to exactly fit the remaining
* elements (once we know how many that is).
*/
for (i = 0; i < *the_size; )
{
if (strcmp(str, (*lastname)[i]) == 0)
{
printf("Deleting Record for %s %s...\n", (*firstname)[i], (*lastname)[i]);
free((*firstname)[i]);
free((*lastname)[i]);
(*firstname)[i] = (*firstname)[*the_size - 1];
(*lastname)[i] = (*lastname)[*the_size - 1];
(*score)[i] = (*score)[*the_size - 1];
*the_size -= 1; /* not the same as *the_size-- */
/* don't increment i, else we miss testing the new i'th element */
} else {
i += 1;
}
}
if (*the_size != initial_size)
{
void *temp;
/*
* Always check the return value of realloc(), even when you're
* shrinking the allocation. Usually, though, you'd want at least
* some kind of diagnostic in the event of failure.
*/
temp = realloc(*firstname, sizeof(char *) * (*the_size));
if (temp)
{
*firstname = temp;
}
temp = realloc(*lastname, sizeof(char *) * (*the_size));
if (temp)
{
*lastname = temp;
}
temp = realloc(*score, sizeof(float) * (*the_size));
if (temp)
{
*score = temp;
}
}
else /* there is no match */
{
printf ("Sorry, no available record for %s",str);
}
}
Your main() would call that like so:
delete_record(&firstname, &lastname, &score, &number_of_records);
Similar changes are needed to add_record(), though you do have the separate issue I already called out there with increasing the number of entries past 16.
Additionally, you're making extra work for yourself by using separate arrays of first name, last name, and score. It would be much easier to define a struct encompassing all three, and use just one dynamic array whose elements are instances of that struct.
First, you're declaring the arguments of add_ as pointers (presumably because you want the function to change the value of the variables whose addresses you pass):
add_new_record (char **firstname, char **lastname, float *score, int the_size) {
But then you simply assign the locals, not the things they point to:
firstname = realloc(firstname,16*sizeof(char*));
score = realloc(score,16*sizeof(float));
If you want to change the variables to which these point, you have to
dereference them for assignment:
*firstname = malloc(16);
*score = 1.0;
Now the original firstname pointer points to a valid chunk of memory (presumably you'll want to strcpy() some actual name there), and the original float variable to which score points is now 1.0.
There are other problems, but that's the primary reason this function doesn't change what you think it should, because you didn't tell it to.

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