My C code won't stop taking in inputs using scanf function - c

This is my first semester learning C and I have trouble with one of my homeworks.
It's a program to receive the lists of homework as sets of (t,d) and to evaluate the urgency of each homework. (t means time left until deadline and d mean difficulty.) The task is to sort the list primarily by the order of remaining time and if the remaining time is equal, to sort it by difficulty.
This code works perfectly well when the input is something like
(1,0), (2, 1), (4,5) ...
But when the input is like
(1,0), (1, 4), (2, 1)...
it won't stop receiving inputs. This happens when the 'time' of the homework is the same (or so I think). I can't figure out why it's doing this.
#include <stdio.h>
#define MAX 1024
void insertionSort(int a[], int b[], int num);
void printArray(int a[], int b[], int num);
int main()
{
int a[MAX] = {0};
int b[MAX] = {0};
int i, num;
scanf("%d", &num);
for(i=0; i<num; i++){
scanf("%d", &a[i]);
scanf("%d", &b[i]);
}
insertionSort(a, b, num);
return 1;
}
void insertionSort(int a[], int b[], int num)
{
int i, j, val, val2;
for(i=1; i<num; i++)
{
val = a[i];
val2 = b[i];
j = i-1;
while((j>=0) && (a[j]>=val))
{
if(a[j] == val){
if(val2 < b[j]){
a[j+1] = a[j];
b[j+1] = b[j];
j--;
}
}
else{
a[j+1] = a[j];
b[j+1] = b[j];
j--;
}
a[j+1] = val;
b[j+1] = val2;
}
}
printArray(a, b, num);
}
void printArray(int a[], int b[], int num)
{
int i;
for(i=0; i<num; i++){
printf("%d ", a[i]);
printf("%d", b[i]);
printf("\n");
}
}

Your code is not continuously receiving inputs, instead it is stuck in an infinite loop inside the insertionSort function
You just need to add an else case and break the loop.
Here is the working code:
#include <stdio.h>
#define MAX 1024
void insertionSort(int a[], int b[], int num);
void printArray(int a[], int b[], int num);
int main()
{
int a[MAX] = {0};
int b[MAX] = {0};
int i, num;
scanf("%d", &num);
for(i=0; i<num; i++)
{
scanf("%d", &a[i]);
scanf("%d", &b[i]);
}
insertionSort(a, b, num);
return 1;
}
void insertionSort(int a[], int b[], int num)
{
int i, j, val, val2;
for(i=1; i<num; i++)
{
val = a[i];
val2 = b[i];
j = i-1;
while((j>=0) && (a[j]>=val))
{
if(a[j] == val)
{
if(val2 < b[j])
{
a[j+1] = a[j];
b[j+1] = b[j];
j--;
}
else
{
break;
}
}
else
{
a[j+1] = a[j];
b[j+1] = b[j];
j--;
}
a[j+1] = val;
b[j+1] = val2;
}
}
printArray(a, b, num);
}
void printArray(int a[], int b[], int num)
{
int i;
for(i=0; i<num; i++)
{
printf("%d ", a[i]);
printf("%d", b[i]);
printf("\n");
}
}

Related

Why does the array only display garbage value

The C program(main function)asks the user for the number of elements in an array(which this function works). The C function findSecondSmallest finds the second smallest element of an array(points toward the first index). The C function sortAscending arranges the array elements in ascending order (does not display the inputted elements, just garbage values) and the C function displayArray should display the arranged array in ascending order.
#include<stdio.h>
#include<limits.h>
int initializeArray(int num,int arr[]);
int findSecondSmallest(int num,int arr[]);
int *sortAscending(int num,int arr[]);
void displayArray(int num,int arr[]);
void main(){
int array[50],*arr;
int n = sizeof(array) / sizeof(array[0]);
initializeArray(n,array);
findSecondSmallest(n,array);
arr = sortAscending(n,array);
displayArray(n,arr);
}
int initializeArray(int num,int arr[]){
int i;
printf("Input the number of elements in an array: ");
scanf("%d", &num);
printf("\nEnter %d elements: ", num);
for(i = 0;i < num;i++){
scanf("%d", &arr[i]);
}
}
int findSecondSmallest(int num,int arr[]){
int i,secondSmall,small;
small = secondSmall = INT_MAX;
for(i = 1;i < num;i++){
if(arr[i] < small){
secondSmall = small;
small = arr[i];
}else if(arr[i] < secondSmall && arr[i] > small){
secondSmall = arr[i];
}
}
printf("The second smallest element is %d", secondSmall);
}
int *sortAscending(int num,int arr[]){
int i,j,temp;
for(i = 0;i < num;i++){
for(j = i + 1;j < num;j++){
if(arr[i] > arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
}
void displayArray(int num,int arr[]){
int i;
for(i = 0;i < num;i++){
printf("Element at Array[%d] = %d ", i, arr[i]);
}
}
In need of help
You need to process only the elements that the user input, not the entire array, since the rest of the array is uninitialized.
Change initializeArray() to return the number of elements that the user input. Then use that instead of n when calling the other functions.
initializeArray() wasn't using the parameter num. It should use that to check that the user doesn't enter more elements than the array can hold. So you need to use a different variable for the parameter and the user's input, so you can compare them.
findSecondSmallest() doesn't return anything, so it should be declared void, not int.
sortAscending() is supposed to return a pointer to the array, but it was missing the return statement.
In findSecondSmallest() you can initialize the variables to the first element of the array rather than INT_MAX. Then it makes sense to start your loop from i = 1, since you've already used element 0.
#include<stdio.h>
#include<limits.h>
#include <stdlib.h>
int initializeArray(int num,int arr[]);
void findSecondSmallest(int num,int arr[]);
int *sortAscending(int num,int arr[]);
void displayArray(int num,int arr[]);
int main(void){
int array[50],*arr;
int n = sizeof(array) / sizeof(array[0]);
int num = initializeArray(n,array);
findSecondSmallest(num,array);
arr = sortAscending(num,array);
displayArray(num,arr);
}
int initializeArray(int n,int arr[]){
int i, num;
printf("Input the number of elements in an array: ");
scanf("%d", &num);
if (num > n) {
printf("That's too many elements\n");
exit(1);
}
printf("\nEnter %d elements: ", num);
for(i = 0;i < num;i++){
scanf("%d", &arr[i]);
}
return num;
}
void findSecondSmallest(int num,int arr[]){
int i,secondSmall,small;
small = secondSmall = arr[0];
for(i = 1;i < num;i++){
if(arr[i] < small){
secondSmall = small;
small = arr[i];
}else if(arr[i] < secondSmall && arr[i] > small){
secondSmall = arr[i];
}
}
printf("The second smallest element is %d\n", secondSmall);
}
int *sortAscending(int num,int arr[]){
int i,j,temp;
for(i = 0;i < num;i++){
for(j = i + 1;j < num;j++){
if(arr[i] > arr[j]){
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
void displayArray(int num,int arr[]){
int i;
for(i = 0;i < num;i++){
printf("Element at Array[%d] = %d\n", i, arr[i]);
}
}

endless loop in Quicksort

I was implementing the Quicksort Algorithm, but I have some error and I'm not able to figure out.
I'm using the rand() function to generate random numbers. I'm limiting these numbers in mod(100). mod (100) works well but when I make it mod(10) it doesn't work. The program runs but stops after printing the random unsorted array.
Here's my code:
#include <stdio.h>
#include <stdlib.h>
int a[50];
void quicksort(int l, int r)
{
int s;
if(l<r)
{
s=partition(l, r);
quicksort(l, s-1);
quicksort(s+1, r);
}
}
int partition(int l, int r)
{
int p, i, j, temp;
p = a[l];
i=l;
j=r+1;
while(i<=j)
{
while(a[i]<=p && i<r+1)
i=i+1;
while(a[j]>=p && j>l)
j=j-1;
temp = a[i];
a[i] = a[j];
a[j] = temp;
}
temp = a[i];
a[i] = a[j];
a[j] = temp;
temp = a[l];
a[l] = a[j];
a[j] = temp;
return j;
}
int main()
{
int n, i;
printf("Enter number of elements: \n");
scanf("%d", &n);
printf("Random Array: \n");
for(i=0; i<n; i++)
{
a[i] = rand()%100; // The error seems to be here for rand()%10
printf("%d ", a[i]);
}
quicksort(0,n-2);
printf("\n Solution: \n");
for(i=0; i<n; i++)
{
printf("%d ", a[i]);
}
return 0;
}
Any help would be appreciated.
Thanks.
This loop condition inside partition() can end up in an endless loop:
while(i<=j)
To avoid change it to
while(i<j)
It never needs to swap at two identical indexes anyway.

Bubble sort does not seem to work-segmentation error

Hi there somehow my bubble sort that is suppose to work does not seem to work.Im not sure where the error is being caused.It is suppose to give me a sorted output list.It is giving me segmentation error and have been trying this for about 1 hr.Heres the code:
#include <stdio.h>
#include <stdlib.h>
#define N 10
void sort(int [], int);
void show(char *, int [], int);
int main(void)
{
int i, j, a[N];
srand(0);
for (j = 1; j <= 5; j++) {
// initialise array (pseudo-randomly)
for (i = 0; i < N; i++) {
a[i] = rand()%100;
}
// display, sort, then re-display
printf("Test #%d\n",j);
show("Sorting", a, N);
sort(a, N);
show("Sorted ", a, N);
}
return 0;
}
// sort array using bubble sort
void sort(int a[], int n)
{
int i, j, nswaps;
for (i = 0; i < n; i--) {
nswaps = 0;
for (j = n-1; j > i; j--) {
if (a[j] < a[j-1]) {
int tmp;
tmp = a[j];
a[j] = a[j-1];
a[j-1] = tmp;
nswaps++;
}
}
if (nswaps == 1) break;
}
}
// display array, preceded by label
void show(char *label, int a[], int n)
{
int i;
printf("%s:", label);
for (i = 0; i < n; i++) {
printf(" %02d", a[i]);
}
printf("\n");
}
Your are not technically sorting here.Instead of this for (i = 0; i < n; i--), try for (i = 0; i < n; i++).This is because you are starting with i=0 so in a FOR loop you need to increment i.

Convert nested loop to recursion

I have used 3 nested loop. Now i want to convert these loops to recursive.
Also is there a general way to convert a loop into recursive?
#include <stdio.h>
#define f(x, y, z) ((x + y) * (y + z))
int main()
{
int test_case, p, q, r, i, j, k, a[100001], b[100001], c[100001], sum;
scanf("%d", &test_case);
while (test_case--) {
scanf("%d%d%d", &p, &q, &r);
sum = 0;
for (i = 0; i < p; i++) {
scanf("%d", &a[i]);
}
for (i = 0; i < q; i++) {
scanf("%d", &b[i]);
}
for (i = 0; i < p; i++) {
scanf("%d", &c[i]);
}
for (i = 0; i < q; i++) { // I have convert this to recursion.
for (j = 0; j < p; j++) {
for (k = 0; k < r; k++) {
if (b[i] >= a[j] && b[i] >= c[k]) {
sum += f(a[j], b[i], c[k]);
}
}
}
}
printf("%d\n", sum % 1000000007);
}
return 0;
}
A loop like:
for (int i=0; i<n; i++) {
func(i);
}
can be translated to recursion as:
void rec_fun(int i,int n) {
if (!(i<n)) return;
func(i);
rec_fun(i+1,n);
}
...
rec_fun(0,n);
So:
for (i = 0; i < q; i++) { // I have convert this to recursion.
for (j = 0; j < p; j++) {
for (k = 0; k < r; k++) {
if (b[i] >= a[j] && b[i] >= c[k]) {
sum += f(a[j], b[i], c[k]);
}
}
}
}
can be translated as:
void rec_k(int k,int r,int i,int j) { // k-loop
if (!(k<r)) return;
if (b[i] >= a[j] && b[i] >= c[k]) {
sum += f(a[j], b[i], c[k]);
}
rec_k(k+1,r,i,j); // recurse
}
void rec_j(int j,int p,int i,int r) { // j-loop
if (!(j<p)) return;
rec_k(0,r,i,j); // inner loop
rec_j(j+1,p,i,r); // recurse
}
void rec_i(int i,int q,int p,int r) { // i-loop
if (!(i<q)) return;
rec_j(0,p,i,r); // inner loop
rec_i(i+1,q,p,r); // recurse
}
...
rec_i(0,q,p,r);
I'm not sure this is either more readable or useful, but it meets your initial needs.
Let us assume that the intention of this code is to only calculate the sum.
You can make a function as
int recurse_sum(int i, int j, int k) {
int res = .... // Logic for calculating sum for these indices i, j, k.
k++;
if (k==r) {
k = 0;
j++;
}
if(j==p){
j=0;
i++;
}
if(i==q){
return res;
}
return res + recurse_sum(i,j,k);
}
Now you can just call with recurse_sum(0,0,0);
The rest of the parameters can either be made global or just passed along with i,j,k.
I hope this helps.
Edit:
As mentioned by #dlasalle this code can be made open to tail call recursion optimization by placing the call at the end of the function.
In that case you can have the following version.
int recurse_sum(int i, int j, int k, int sum) {
int res = .... // Logic for calculating sum for these indices i, j, k.
k++;
if (k==r) {
k = 0;
j++;
}
if(j==p){
j=0;
i++;
}
if(i==q){
return res + sum;
}
return recurse_sum(i,j,k,res+sum);
}
Here the function ends with returning the value from the inner call and hence can be easily optimized.
Ofcourse in this case it will have to be called as recurse_sum(0,0,0,0);
Thanks to #Jean-Baptiste Yunès .
I made these changes to my code to convert it to recursive.
#include<stdio.h>
#define f(x, y, z) ((x + y)*(y + z))
int sum=0;
void rec_k(int k,int r,int i,int j,int a[],int b[],int c[]) { // k-loop
if (!(k<r)) return;
if (b[i] >= a[j] && b[i] >= c[k]) {
sum += f(a[j], b[i], c[k]);
}
rec_k(k+1,r,i,j,a,b,c);
}
void rec_j(int j,int p,int i,int r,int a[],int b[],int c[]) { // j-loop
if (!(j<p)) return;
rec_k(0,r,i,j,a,b,c);
rec_j(j+1,p,i,r,a,b,c);
}
void rec_i(int i,int q,int p,int r,int a[],int b[],int c[]) { // i-loop
if (!(i<q)) return;
rec_j(0,p,i,r,a,b,c);
rec_i(i+1,q,p,r,a,b,c);
}
int main() {
int test_case, p, q, r, i, j, k, a[100001], b[100001], c[100001];
scanf("%d", &test_case);
while(test_case--) {
scanf("%d%d%d", &p, &q, &r);
sum=0;
for(i=0;i<p;i++) {
scanf("%d", &a[i]);
}
for(i=0;i<q;i++) {
scanf("%d", &b[i]);
}
for(i=0;i<p;i++) {
scanf("%d", &c[i]);
}
rec_i(0,q,p,r,a,b,c);
printf("%d\n", sum%1000000007);
}
return 0;
}

Quick Sort algorithm behaving strangely

This is a program which attempts to sort an array using the quick sort algorithm.
All seems to be fine, except that the output is not correct.
(Try the program for n=5, and then n=10. It works correctly for the former, but not the latter.)
#include <stdio.h>
//#include <iostream.h>
//#include <conio.h>
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i <= j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i <= j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
return i;
}
void quick_sort(int arr[], int p, int r) {
if (p<r) {
int q=partition(arr, p, r);
quick_sort(arr, p, q-1);
quick_sort(arr, q+1, r);
}
}
int main() {
int values[100], n, i;
//clrscr();
printf("Enter no. of elements ");
scanf("%d", &n);
if (n>100) {
printf("Invalid input. Exiting now");
//getch();
return 0;
}
for (i=0; i<100; i++) values[i]=0;
printf("Enter the numbers\n");
for (i=0; i<n; i++) scanf("%d", &values[i]);
printf("The numbers you entered are\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
printf("\n");
quick_sort(values, 0, n-1);
printf("Numbers after sorting are\n");
printf("(The output might not be the expected one (Be careful).\n");
for (i=0; i<n; i++) printf("%d ", values[i]);
//std::cin.get();
return 0;
}
There are two problems. First, the comparison i <= j is wrong. If i == j, you should not swap an element with itself. This should be changed to i < j in both places. Secondly, you should not move the i and j array indicies along after swapping. If it is the last swap, this pushes i past the actual pivot and causes your error.
int partition(int arr[], int left, int right) {
int i = left, j = right;
int temp;
//Choosing the middle element as the pivot
//int pivot=arr[left];
int pivot = arr[(left+right)/2];
while (i < j) {
while (arr[i] < pivot) {i++;}
while (arr[j] > pivot) {j--;}
if (i < j) {
temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
return i;
}
is better to use the std sort from algorithm.h :
http://www.cplusplus.com/reference/algorithm/sort/

Resources