Segmentation Fault linear search algorithm - c

This algorithm is a linear search algorithm that finds the desired value. But when I compile this code, gives the segmentation fault in if(dizi[i]==aranan) this line. How can I solve this ?
#include <stdio.h>
int N,i,aranan;
int ArrayBastir(int *dizi,int N)
{
printf("My numbers\n");
for(int i =0; i<N;i++)
{
printf("%d\n", dizi[i]);
}
}
int findValue()
{
printf("The value you want to search");
scanf("%d",&aranan);
}
int Output(int *dizi,int N,int aranan)
{
for(int i =0; i<N;i++)
{
if(dizi[i]==aranan)
{
printf("%d number %d. found in queue \n", aranan,i+1);
}
}
}
int main() {
int N;
int aranan;
printf("Please enter how many numbers you want to enter");
scanf("%d", &N);
int dizi[N];
for(int i =0; i<N;i++)
{
scanf("%d", &dizi[i]);
}
ArrayBastir( dizi, N);
findValue(aranan);
Output(*dizi,N,aranan);
return 1;
}
Linear Search algorithm

You have two objects defined as:
int aranan;
Once is defined at file scope (a global), and one is defined within the scope of main.
When findValue(aranan) is called, a copy of the uninitialized value of aranan within the scope of main is passed to findValue. findValue is lacking a prototype, having not declared its arguments, so this is ignored.
findValue scans a value into the file scope aranan, but when Output(*dizi, N, aranan) is called it uses the value of aranan defined within main. aranan within main was never initialized, and thus this causes Output to search for an indeterminate value.
Additionally, *dizi is an int, when Output expects an int * as its first argument.
ArrayBastir and Output are also defined as each returning an int, which they do not do.
You should not ignore the return value of scanf, as it indicates the number of successful conversions, or a negative value on failure (EOF). In a program this small, you can get away with writing a simple wrapper function for reading integers, that just exits the program if the user enters something invalid.
main returning nonzero generally indicates your program failed. main is special - it is the only non-void function where you can omit a return statement. If main reaches the end of execution without an explicit return, it is treated as though it returned 0.
The issues above can be mitigated by avoiding the use of global variables, and by turning up your compilers warning level to catch obvious type mismatches.
For GCC or Clang, use -Wall -Wextra, and possibly -Werror.
For MSVC, use /Wall, and possibly /Wx.
Minimally refactored:
#include <stdio.h>
#include <stdlib.h>
int get_int(void)
{
int x;
if (1 != scanf("%d", &x)) {
fprintf(stderr, "Invalid input.\n");
exit(EXIT_FAILURE);
}
return x;
}
void ArrayBastir(int *dizi, int N)
{
printf("My numbers\n");
for (int i = 0; i < N; i++) {
printf("%d\n", dizi[i]);
}
}
void Output(int *dizi, int N, int aranan)
{
for (int i = 0; i < N; i++) {
if (dizi[i] == aranan) {
printf("Found <%d> at position %d.\n", aranan, i);
}
}
}
int main(void)
{
printf("Please enter how many numbers you want to enter: ");
int N = get_int();
int dizi[N];
for (int i = 0; i < N; i++) {
dizi[i] = get_int();
}
ArrayBastir(dizi, N);
printf("Enter the value you want to search for: ");
int aranan = get_int();
Output(dizi, N, aranan);
}

Related

Program stops after loop in function

My prog doesn't reach outArray function. it stops after loop of fillArray function. Why this happens. It looks strangely, cause it's simple void function and shouldn't return anything. This should continue run commands in main. And that stops as usual program without any problems and bugs
#include <stdio.h>
#define N 100
int enterNofArray();
void fillArray(int n, float arr[N]);
void outArray(int n, float arr[N]);
int main()
{
float arr[N], sum = 0.0, average;
int n;
//input
n = enterNofArray();
//compute
fillArray(n, &arr[N]);
//output
outArray(n, &arr[N]);
return 0;
}
int enterNofArray()
{
int n;
printf("Enter amount of array...\n");
scanf("%d", &n);
while (n < 1 || n > N)
{
printf("Incorrect!!\n");
printf("Enter in range 1 - 100...\n");
scanf("%d", &n);
}
return n;
}
void fillArray(int n, float arr[N])
{
int num;
for(int i = 0; i < n; i++)
{
printf("Enter number for array[%d times left]...\n", n - i);
scanf("%d", &num);
arr[i] = num;
}
}
void outArray(int n, float arr[N])
{
for(int i = 0; i < n; i++)
{
printf("%f ", arr[i]);
}
}
&arr[N] refers to the memory location (or lvalue) that contains the N-th (out of index!!!) element in the array.
That code invokes Undefined Behavior (UB).
So, you weren't actually passing the whole array to your functions, you were just attempting to pass the N-th element of that array... Read more about that expression here.
Change this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
to this:
fillArray(n, arr);
outArray(n, arr);
Live Demo
The problem was that with your code n was corrupted, containing garbage value after the call to fillArray function. As a result, when outArray function was called, n had a garbage value, which resulted in an uncontrolled for-loop that ended in looping far further than the limits of your array, eventually accessing memory that you didn't own, thus causing a Segmentation Fault.
Not the cause of your problem, but I suggest you do scanf("%f", &num); in your fillArray function (after declaring num as a float of course), since you want to populate an array of floats.
Because you're send double pointer when you do this:
fillArray(n, &arr[N]);
outArray(n, &arr[N]);
Looks like:
fillArray(n, **arr);
outArray(n, **arr);
This happends so much when you work with Structures.

Why does the C program stop executing after providing 1 element?

I am writing a program to check whether a set is a proper subset of a set or not. I am dynamically allocating memory for both of the sets(arrays) but after I provide one element the program stops executing.
#include <stdio.h>
int setID(int arr[],int arr2[],int size,int size2)
{
int counter =0;
for (int i=0; i<size2;i++)
{
if (arr2[i] == arr[i])
{
counter++;
}
}
if (counter == (size2))
{
return 1;
}
else
return 0;
}
int main ()
{
printf("We are going to check if set A is a proper subset of B or not\n");
printf("Please provide the cardinal number of set A \n");
int a=0,b=0;
scanf("%d",&a);
int *p;
p =(int*) malloc(a*sizeof(int));
printf("Please provide the elements of Set A\n");
for (int i=0;i<a;i++)
{
scanf("%d",p[i]);
}
printf("Please provide cardinal number for set B\n");
scanf("%d",&b);
int *p1;
p1= (int*) malloc(b*sizeof(int));
for (int i=0;i<b;i++)
{
scanf("%d",&p1[i]);
}
printf("Please note that 0 is false and 1 is true\n");
printf("%d\n",setID(p,p1,a,b));
return 0;
}
**Also have I passed the arguments correctly in the function: printf("%d\n",setID(p,p1,a,b)); **
There is one error here
scanf("%d",p[i]);
which should be
scanf("%d", &p[i]);
and which is correct a few lines further down when you did this with p1. You say the program stops after providing one element and this is consistent with the error.
There may be other errors too as posted by others.
in setID :
for (int i=0; i<size2;i++)
{
if (arr2[i] == arr[i])
{
counter++;
}
...
you suppose the size of arr is >= the size of arr2, but this is not mandatory because you read their size rather than to use the same when you allocate the arrays and read their values
if size < size2 (a < b in main) you go out of arr (p in main), the behavior is undefined

Sorting program stops working without any error

I typed the following code to sort the components of an int array. It does not show any error but does stops working abruptly. The error is generally after entering 7-8 inputs which shows that program.exe has stopped working. Does it has anything related to the code ?
#include <stdio.h>
#include <stdlib.h>
int main()
{
int n,a[n],i,j,temp;
printf("Enter number of inputs.\n");
scanf("%d",&n);
printf("Enter inputs\n");
for(i=0;i<n;i++)
{
scanf("%d",&a[i]);
}
for(i=0;i<n;i++)
{
for(j=i+1;j<n;j++)
{
if(a[i]<a[j])
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
}
}
}
printf("Numbers in descending order are:\n");
for(i=0;i<n;i++)
{
printf("%d\n",a[i]);
}
return 0;
}
The problem is here:
int n, a[n], i, j, temp;
Declarations are done sequentially. If you write this in a slighly more readably (but equivalent form) you'd have this:
int n;
int a[n]; // here the variable n has not yet been initialized
// it contains an indeterminate value, and therefore the a array
// will have an indeterminate size and the program will have
// so called "undefined behaviour " (google that)
int i;
...
You should write the beginning of your program like this:
int main()
{
int n,i,j,temp;
printf("Enter number of inputs.\n");
scanf("%d",&n);
int a[n]; // now n has a determinate value
printf("Enter inputs\n");
Disclaimer: no error checking is done for brevity.
Always compile with warnings enabled and listen to them. Many of them are actually errors. Especially the warning variable 'somevar' is uninitialized when used here is always an error.

Creating a function for a random number 2D array

So, I have this code which I need to turn into a function:
int main(void) {
int i=0,seed;
printf("\n\nEnter seed integer value: ");
scanf("%d", &seed);
printf("\nSeed value is:%d\n\n",seed);
srand(seed);
int a[5][5];
int x,y;
printf("Matrix A:\n");
for(x=0;x<5;x++) {
for(y=0;y<5;y++) {
a[x][y] = rand() %51 + (-25);
printf("%d ",a[x][y]); }
printf("\n"); }
printf("\n\n");
So basically, it produces a 2D 5x5 array of random numbers. This works fine, however my next task is applying a function to this code, with the function name of:
void generate_matrices(int a[5][5])
I have tried multiple times, the closest I got to a successful code was:
#include <stdio.h>
#include <stdlib.h>
void generate_matrices(int a[5][5]);
int main(void) {
int a, seed;
printf("\n\nEnter seed integer value: ");
scanf("%d", &seed);
srand(seed);
printf("\nSeed value is:%d\n\n",seed);
generate_matrices(a);
return 0;
}
void generate_matrices(int a[5][5]) {
int y,z;
printf("Matrix A:\n");
for(y=0;y<5;y++) {
for(z=0;z<5;z++) {
a[y][z] = rand() %51 + (-25); }
printf("%d ",a[y][z]); }
printf("\n");
}
But this returns the error, "expected 'int(*)[5]' but arguement is of type 'int'.
All/any help is muchly appreciated. To be fair on my part, I have done 90% of the code. This is the only bit I need help with so that I can apply this to the rest of my code.
Cheers!
You have declared a as a single integer on this line int a, seed;
When you call the function with generate_matrices(a); you are passing a single integer instead of a pointer to an array.
Change your declaration line to int a[5][5], seed;
generate_matrices(a); will pass a pointer to the first element in your 5 * 5 array, to the function.
You should really print the results in main and not in the function, then you will know that the array has been modified and is available for use in the body of your program.
You have used unconventional placement of braces '}' and this makes it harder to see what belongs in each part of your for loops.
You have the print statements in the wrong places - as a result only part of the matrix is printed.
This is what it should be (just the results - in main):
printf("Matrix\n ");
for (y = 0; y < 5; y++) {
for (z = 0; z < 5; z++) {
printf("%d\t ", a[y][z]);
}
printf("\n");
}
If you use int a[5][5] and call the function with generate_matrices(a);
a function void generate_matrices(int a[5][5]) {...} compiles without error
#include<stdio.h>
#include<stdlib.h>
void modify(int b[5][5]);
int main()
{
srand(4562);
int i,j,arr[5][5];
modify(arr);
for(i=0;i<5;i++){
for(j=0;j<5;j++){
printf("%d ",arr[i][j]=rand() %51 + (-26)); }
}
return 0;
}
void modify(int b[5][5])
{
int i,j;
for(i=0;i<5;i++) {
for(j=0;j<5;j++) {
b[i][j]; }
}
}
So this is the closest I have come to completing it. It produces the number of elements I want, also within the range I want. However its not producing the 5x5 grid I need. Where have I gone wrong?
EDIT: I'm not going for neatness at the moment, I just want to get the program working how I want it too and then i'll neaten it up.
EDIT 2: Never mind, realised what I didn't include. Its fine now. Thanks for the help.

Endless loop in C; for loop seems valid

I am a student trying to learn c coming from c++. I wrote the following code and it compiles fine; however, when I execute it I get an endless loop when calling the print function. I looked over the code and it seems to be valid to me, so why is it printing an endless loop?
#include <stdio.h>
#include <stdlib.h>
struct student
{
int id;
int score;
};
void generate(struct student *students, int n)
{
int randomId = rand () % n + 1;
int randomTestScore = rand() % 100 + 1;
students->id = randomId;
students->score = randomTestScore;
}
void sort(struct student *students, int n)
{
/*using insertion sort*/
for (unsigned int i = 1; i < n; ++i)
{
int next = students[i].score;
int j = i;
while(j > 0 && students[j-1].score > next)
{
students[j].score = students[j-1].score;
j--;
}
students[j].score = next;
}
}
void print(struct student *students, int n)
{
for (unsigned int i = 0; i < n; i++)
{
printf("Student at position No: %d Test Score: %d\n", i+1, students[i].score);
}
}
int main()
{
/*user enters num of students to create scores for*/
int num_students;
printf("Enter Num of students\n");
scanf("%d", num_students);
/*allocate memory for the amount of students user wants*/
struct student *userStudents = malloc(num_students*sizeof(struct student));
printf("Randomly filling students IDs & Test Scores...\n");
for (unsigned int i = 0; i < num_students; ++i)
{
generate(&userStudents[i], num_students);
}
printf("Array of students before sorting:\n");
print(userStudents, num_students);
printf("\nNow, sorting students by test scores...\n\n");
sort(userStudents, num_students);
printf("Array of students after sorting:\n");
print(userStudents, num_students);
return 0;
}
To use scanf() correctly it needs to alter the passed variable in place, and since there is no pass by refrence in c, you need to pass the address of the variable, so scanf() is able to modify it though a pointer, hence you need to use the & operator, but that is not enough.
The scanf() family of functions, return a value that must be checked before you can access the scanned values, you should never ignore that value, under any circumstances you should check for it.
What your code is doing is called undefined behavior, it's interpreting the passed integer as if it was a pointer, which is undefined behavior.
To prevent that you can activate compiler warnings, many compilers know what kind of parameter the *f functions expect, i.e. the functions which take a string as a format to be parsed and to allow the function to correctly grab the rest of the parameters passed via variable arguments to it.
The correct way to call scanf() in your program is
if (scanf("%d", &num_students) != 1)
return 1;
that is, from main() and hence it's ending the program, because you can't continue after that condition was true, in that case what actually happens is that num_students is not initialized, that would once again cause undefined behavior.
Change the call to scanf to:
/*
* correct way of calling scanf, passing the address of the wanted variable
*/
scanf("%d", &num_students);
^
This elliminates segmentation faults and makes the code runs OK on my machine.
I had a previous hint that you'd need to change your declaration of userStudents to a pointer to pointers, however I was incorrect. You are clearly correctly allocating enough contiguous memory to hold all of your structs pointed by *userStudents.

Resources