How to avoid SIGSEGV Error in Insertion Sort - c

I am trying to implement Insertion sort algorithm in C.
But all I get is SIGSEGV error in online IDEs and the output doesn't show up in Code::Blocks. How to avoid Such errors.
#include <stdio.h>
#include <stdlib.h>
int main()
{
/* Here i and j are for loop counters, temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter");
scanf("%d", &count);
int n[20];
printf("Enter %d elements", count);
// storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", n[i]);
}
// Implementation of insertion sort algorithm
for(i = 0; i < count; i++) {
temp = n[i];
j = i - 1;
while(temp < n[j]) {
n[j+1] = n[j];
j = j - 1;
}
n[j+1] = temp;
}
printf("Order of sorted elements");
for(i = 0; i < count; i++) {
printf("%d", n[i]);
}
return 0;
}

There are a couple of problems with your code. First of all, what is a SIGSEGV error? Well, it's another name for the good old Segmentation fault error, which is basically the error you get when accessing invalid memory (that is, memory you are not allowed to access).
tl;dr: change scanf("%d",n[i]); to scanf("%d",&n[i]);. You're trying to read the initial values with scanf("%d",n[i]);, this raises a segmentation fault error because scanf expects addresses in which put the values read, but what you're really doing is passing the value of n[i] as if it were an address (which it's not, because, as you did not set any value for it yet, it's pretty much just memory garbage). More on that here.
tl;dr: change int n[20]; to int n[count]. Your array declaration int n[20]; is going to store at most 20 integers, what happens if someone wants to insert 21 or more values? Your program reserved a certain stack (memory) space, if you exceed that space, then you're going to stumble upon another program's space and the police (kernel) will arrest you (segmentation fault). Hint: try inserting 21 and then 100 values and see what happens.
tl;dr: change for(i = 0; i < count; i++) { to for(i = 1; i <= count; i++) {. This one is a logic problem with your indexes, you are starting at i = 0 and going until i = count - 1 which would be correct in most array iteration cases, but as j assumes values of indexes before i, you need i to start from 1 (so j is 0, otherwise j = -1 in the first iteration (not a valid index)).
My final code is as follows. Hope it helped, happy coding!
#include <stdio.h>
#include <stdlib.h>
int main() {
/*Here i and j are for loop counters,temp for swapping
count for total number of elements,array for elements*/
int i, j, temp, count;
printf("How many numbers are you going to enter?\n");
scanf("%d",&count);
int n[count];
printf("Enter %d elements\n",count);
//storing elements in the array
for(i = 0; i < count; i++) {
scanf("%d", &n[i]);
}
//Implementation of insertion sort algorithm
for(i = 1; i <= count; i++) {
temp = n[i];
j = i-1;
while(temp < n[j]) {
n[j+1] = n[j];
j--;
}
n[j+1] = temp;
}
printf("Order of sorted elements\n");
for(i = 0; i < count; i++) {
printf("%d\n",n[i]);
}
return 0;
}
Edit: If you're having trouble with online IDEs, consider running your programs locally, it saves a lot of time, plus: you never know what kernel version or magic the online IDEs are using to run your code (trust me, when you're coding in C -- fairly low level language, these things make a difference sometimes). I like to go all root style using Vim as text editor and gcc for compiling as well as gdb for debugging.

Related

qsort in C give wrong results

I am trying to sort an array of structs (A SJF Scheduler). I am using the qsort library function to sort the structs in increasing order according to the attribute bursttime. However, the output is not correct. I've checked some SO questions about the same but they served no use.
struct job
{
int jobno;
int bursttime;
};
typedef struct job job_t;
int mycompare(const void* first, const void* second)
{
int fb = ((job_t*)first)->bursttime;
int sb = ((job_t*)second)->bursttime;
return (fb - sb);
}
int main()
{
int n;
printf("Enter number of jobs: ");
scanf("%d", &n);
job_t* arr = (job_t*)malloc(sizeof(job_t) * n);
for(int i = 1; i <= n; ++i)
{
printf("Enter Burst time for Job#%d: ",i);
scanf("%d", &(arr[i].bursttime));
arr[i].jobno = i;
}
printf("\n");
printf("Order of the Jobs before sort:\n");
for(int i = 1; i <= n; ++i)
{
printf("%d\t", arr[i].jobno);
}
qsort(arr, n, sizeof(job_t), mycompare);
printf("\n");
printf("Order of the Jobs after sort:\n");
for(int i = 1; i <= n; ++i)
{
printf("%d\t", arr[i].jobno);
}
printf("\n");
printf("\n");
return 0;
}
This is my inputfile:
4
7
2
9
4
The output I'm getting is:
Order of the Jobs before sort:
1 2 3 4
Order of the Jobs after sort:
2 1 3 4
The expected order should be: 2,4,1,3. Am I missing anything?
At least this problem
for(int i = 1; i <= n; ++i) // bad
Use zero base indexing.
for(int i = 0; i < n; ++i)
You could change the indexing scheme to start from zero, as others have suggested, and this would certainly be the idiomatic way to do it.
But if you want to use 1-based indexing, you'll need to allocate an extra place in the array (position 0 that will never be used):
job_t* arr = (job_t*)malloc(sizeof(job_t) * (n + 1));
Then you'll need to start your sort at position 1 in the array:
qsort(&arr[1], n, sizeof(job_t), mycompare);
And, of course, you'll have to write your code to index from 1 -- but you've already done that.
The problem is that so many standard functions in C use zero-based indexing that doing anything else is inexpressive. That's a bigger problem than wasting one array position. But, for better or worse, I've had to convert to C a load of code from Fortran, so I've gotten used to working both ways.

Why isn't this program showing any number above 3?

Wrote this to find the prime numbers between 2 to 1000. But it stops after showing that 2 and 3 are prime numbers. I know I can find how to write a code for finding out prime numbers on the internet. But I really need to know what's going wrong here.
#include <stdio.h>
main() {
int i, j;
int ifPrime = 1;
for (i = 2; i < 1000; i++) {
for (j = 2; j < i; j++) {
if (i % j == 0) {
ifPrime = 0;
break;
}
}
if (ifPrime == 1) {
printf("%d is prime\n", i);
}
}
}
The line
int ifPrime=1;
must be inside the outer for loop. There it will be initialized for every i. This corresponds to the natural language words "to check whether a number i is prime, first assume it is. Then check if it is divisible". The code you had before said "to check whether the numbers 2 to 1000 are prime, first assume they are", and this wording was too broad.
The code should be:
int main()
{
for (int i = 2; i < 1000; i++)
{
int ifPrime = 1;
for (int j = 2; j < i; j++)
I replaced main with int main since that is required since 20 years. (You should not learn programming from such old books.)
I moved the int i and the int j into the for loops so that you cannot accidentally use these variables outside the scope where they have defined values.
To avoid this bug in the future, it's a good idea to extract the is_prime calculation into a separate function. Then you would have been forced to initialize the ifPrime in the correct place.
Another way of finding the cause of this bug is to step through the code using a debugger and ask yourself at every step: does it still make sense what the program is doing?
You are not setting ifPrime back to 1 after checking for the single number. So once you get a number that is non_prime, ifPrime is now 0 and hence if(ifPrime == 1) would never return true post that and hence you only see 2, 3 as prime
#include <stdio.h>
int main(void) {
for( int i=2;i<1000;i++)
{
int ifPrime = 1;
for(int j=2;j<i;j++)
{
if(i%j==0)
{
ifPrime=0;
break;
}
}
if(ifPrime==1)
{
printf("%d is prime\n",i);
}
}
return 0;
}

Online judgeProblem (Wrong Answer)

problem in Light OJ:
1001 - Opposite Task:
This problem gives you a flavor the concept of special judge. That means the judge is smart enough to verify your code even though it may print different results. In this problem you are asked to find the opposite task of the previous problem.
To be specific, I have two computers where I stored my problems. Now I know the total number of problems is n. And there are no duplicate problems and there can be at most 10 problems in each computer. You have to find the number of problems in each of the computers.
Since there can be multiple solutions. Any valid solution will do.
Input:
Input starts with an integer T (≤ 25), denoting the number of test cases.
Each case starts with a line containing an integer n (0 ≤ n ≤ 20) denoting the total number of problems.
Output:
For each case, print the number of problems stored in each computer in a single line. A single space should separate the non-negative integers.
Sample Input
Output for
Sample Input:
3
10
7
7
Sample output:
0(space)10
0(space)7
1(space)6
my code :
#include<stdio.h>
#include <stdlib.h>
int main()
{
int c,sum;
int i,j,mini=0,maxi;
int com1,com2;
do{
scanf("%d",&c);
}while (c>25);
int t[c+1];
for(i=1; i<=c; i++)
{
do{
scanf("%d",&t[i]);
}while (t[i]>20);
}
for(i=1; i<=c; i++)
{
maxi=t[i];
com1=rand() % (maxi - mini + 1) + mini;
com2=t[i]-com1;
printf("%d %d\n",com1,com2);
}
return 0;
}
When I submit my code the judge gives wrong answer.
But while I compile the code in CodeBlocks it gives right answer.
I can't understand the problem in online judge.
How can I solve it.
The original post has mini=0 for all cases, but where the total problems is > 10 that may not work. I have adjusted that
#include<stdio.h>
#include <stdlib.h>
int main()
{
int c = 0, mini, maxi, i, com1, com2, *t;
scanf ("%d",&c);
t = malloc (c * sizeof(int));
for (i=0; i<c; i++)
scanf ("%d", &t[i]);
printf("\n");
for (i=0; i<c; i++) {
if (t[i]>10) {
maxi = 10;
mini = t[i] - 10;
} else {
maxi = t[i];
mini = 0;
}
com1 = rand() % (maxi - mini + 1) + mini;
com2 = t[i] - com1;
printf("%d %d\n",com1,com2);
}
free (t);
return 0;
}
Please note that results of malloc() and scanf() have not been checked: they should be.
You seem to be looping unnecessary number of times for the input. I have removed the unnecessary loops from your code while retaining the logic you used. I made a silly mistake with my earlier answer.
#include<stdio.h>
#include <stdlib.h>
int main()
{
int c = 0;
int maxi=10;
scanf("%d",&c);
int t[c];
for(int i=0; i<c; i++)
scanf("%d",&t[i]);
for(int i=0; i<c; i++)
{
int com1 = t[i],com2 = 0;
if (t[i] > 10)
{
com1 = 10
com2 = t[i]-com1;
}
printf("%d %d\n",com1,com2);
}
return 0;
}

Why is my program not sorting the struct?

I am trying to create this program that takes an int number from the user then randomizes a pair of numbers, based on the input, inside the an array of struct. Then it sorts this array based on the sum of the number pair the program randomized.
However my program won´t sort the array of struct. It doesn´t do the sorting properly and Im not sure why. Here is the code.
#define MAX 10
struct NumPair{
int n,m;
};
int main()
{
int i, j, amount=0;
NumPair NumPair[MAX];
srand(time(NULL));
printf("How many pair of numbers? (max 10): ");
scanf("%d", &amount);
for (i=0; i<amount; i++)
{
NumPair[i].n = rand() % 11;
NumPair[i].m = rand() % 11;
}
for (i=0; i<amount; i++)
{
for(j=1; j<amount; j++)
{
if( (NumPair[i].n+NumPair[i].m) > (NumPair[j].n+NumPair[j].m) )
{
int tmp;
tmp = NumPair[i].n;
NumPair[i].n = NumPair[j].n;
NumPair[j].n = tmp;
tmp = NumPair[i].m;
NumPair[i].m = NumPair[j].m;
NumPair[j].m = tmp;
}
}
}
for (i=0; i<amount; i++)
{
printf(" NumPair %d: (%d,%d)\n", i+1, NumPair[i].n, NumPair[i].m);
}
return 0;
}
What am I missing? It's probably something very silly.
Thanks in advance.
Your algorithm is incorrect. This little snippet:
for (i=0; i<amount; i++) {
for(j=1; j<amount; j++) {
will result in situations where i is greater than j and then you comparison/swap operation is faulty (it swaps if the i element is greater than the j one which, if i > j, is the wrong comparison).
I should mention that (unless this is homework or some other education) C has a perfectly adequate qsort() function that will do the heavy lifting for you. You'd be well advised to learn that.
If it is homework/education, I think I've given you enough to nut it out. You should find the particular algorithm you're trying to implement and revisit your code for it.
You are comparing iterators i with j. Bubble sort should compare jth iterator with the next one
for (i=0; i<amount; i++) //pseudo code
{
for(j=0; j<amount-1; j++)
{
if( NumPair[j] > NumPair[j+1] ) //compare your elements
{
//swap
}
}
}
Note that the second loop will go only until amount-1 since you don't want to step out of bounds of the array.
change to
for (i=0; i<amount-1; i++){
for(j=i+1; j<amount; j++){

Why do some C programs work in debug but not in release?

Ok,
So I am stuck here. I have code for a program that systematically executes people standing in a circle based off an algorithm, but I am having a problem with it crashing in release mode. My code runs fine if I run it using the debugger (codeblocks), but if I don't it crashes. I looked around online, and the only thing I am finding is unintialized variables, but I tried immediately setting values for my variables at declaration and it didn't fix the problem.
If anyone can see what my problem is, I would greatly appreciate help.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
// if the program does not work, please run in debugger mode. It will work.
void remove_person(int** array, int arraySize, int position)
{
int i;
for (i = 0; i < arraySize; ++i)
printf("%d ", (*array)[i]);
printf("\n");
int* temp = malloc((arraySize - 1) * sizeof(int)); // create temporary array smaller by one element
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
for (i = 0; i < arraySize - 1; ++i)
printf("%d ", (temp)[i]);
printf("\n");
free (*array);
*array = temp;
}
int kill(int** a, int n)
{
int pos = 0;
int round = 1;
while(n > 1)
{
pos = pos + 2 - (round % 2);
while(pos >= n)
pos = pos - n;
remove_person(a,n,pos);
n--;
while(pos >= n)
pos = pos - n;
round++;
}
return *a[0];
}
void main()
{
int n, survivor, i;
int* people;
printf("Enter number of people for Russian Roulette: \n");
scanf("%d", &n);
people = (int*) malloc(n*sizeof(int));
for(i=0; i < n; i++)
{
people[i] = i;
}
survivor = kill(&people, n);
printf("The survivor is person #%d\n", survivor);
}
The basic answer to the title question ("Why do some C programs work in debug but not in release?") is "when they invoke undefined behaviour".
Here, in
memmove(temp,*array,(position+1)*sizeof(int)); // copy entire array before position
memmove(temp+position,(*array)+(position+1),(arraySize - position)*sizeof(int)); // copy entire array after postion
you copy too much. To see why, observe that the first memmove copies to temp[0], temp[1], ..., temp[position], and the second copies to temp[position], temp[position+1], ..., temp[position+arraySize-position-1] = temp[arraySize-1] (note the overlap at temp[position]). But temp only has space for arraySize-1 elements -- you copied one more than it was allowed to hold, so you get undefined behaviour.
It probably works in debug but not release mode because the heap is laid out differently (debug-mode allocators may pad the allocations with extra space to catch bugs like this when running under a debugger or profiler).
The program segfaults if I enter 4 (or even numbers higher than 4) as input, but I won't go into the code to see why that happens.
Apart from that the program works just fine, the problem is that you don't see the output because I think you run it on windows.
That being said you should add something like scanf("%d", &n); at the end or run cmd.exe, go to the directory that holds the executable and run it from there.

Resources