Displaying the output of a sorted array causes problem - c

I tried applying bubble sort algorithm to an array of values.
I have 5000 values in my input, from 1 to 5000. I imported values from a text file to create the array, which worked fine. The bubble sort algorithm also worked fine.
The issue is somewhere with the output. Some values do not appear in the output at all, whereas some values are being printed multiple times. I am attaching my code and the image of the output for reference.
#include<stdio.h>
#include<conio.h>
int main() {
FILE * fp;
long int i, j, n, temp;
printf("Enter array size:");
scanf("%ld",&n);
long int array[n];
fp = fopen("5000averagecase.txt", "r");
for (i=0; i < n; ++i)
fscanf(fp,"%ld",&array[i]);
for (i=0; i < n; ++i)
for (j=0; j < n-1-i; ++j)
if (array[j] > array[j+1]) {
temp = array[j];
array[j] = array[j+1];
array[j+1] = temp;
temp = 0;
}
for (i=0; i< n; ++i)
printf("%ld\t", array[i]);
return(0);
}
https://i.stack.imgur.com/ZbxVU.png

Since your file has only values from 1 to 5000 and I assume they're not sorted in any way, why don't you just make another file like this
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
// shuffles an array given a pointer to the array and its length
void shuffleArray(int *array, int len) {
srand(time(NULL));
int n1, n2, tmp;
for(int i = 1;i < len - 1; i++) {
// get random two positions in the array to swap
n1 = rand() % len, n2 = rand() % len;
// just swap'em
tmp = array[n1];
array[n1] = array[n2];
array[n2] = tmp;
}
}
int main() {
FILE * fp = fopen("5000averagecase.txt", "w");
// check for file pointer validity
if(fp == NULL) {
printf("Error: can't open the file!");
exit(0);
}
// creating an array of 5000 number
int arr[5000];
// fill it from 1 to 5000
for(int i = 0;i < 5000; i++) {
arr[i] = i + 1;
}
// shuffle it
shuffleArray(arr, 5000);
// write the array in `5000averagecase.txt` for later use
for(int i = 0;i < 5000; i++) {
fprintf(fp, "%d ", arr[i]);
}
// don't forget to close the file at the end
fclose(fp);
return 0;
}
Now after executing this you get your valid file, and after executing your sorting code on it you see that it works as expected

Related

Why is my selection sort output different to my input?

So i have a file called output.txt which contains a list of numbers (12365 25460 12522 22707 8714 28771 235 11401 25150 26342 0) and i want to take them and pass them through my selection sort, ive managed to open the file and read them into my program but instead when the selction sort fiishes it comes out with a list of numbers that have nothing to do with my input (although they are in order as they should be)
#include <stdio.h>
int main() {
FILE *outp;
char arr[10];
outp = fopen("output.txt", "r");
if (outp == NULL)
{
puts("Issue in opening the input file");
}
while(1)
{
if(fgets(arr, 10, outp) ==NULL)
break;
else
printf("%s", arr);
}
fclose(outp);
int n=10;
int i, j, position, swap;
for (i = 0; i < (n - 1); i++) {
position = i;
for (j = i + 1; j < n; j++) {
if (arr[position] > arr[j])
position = j;
}
if (position != i) {
swap = arr[i];
arr[i] = arr[position];
arr[position] = swap;
}
}
for (i = 0; i < n; i++)
printf("%d\n", arr[i]);
return 0;
}
You're just reading the first 10 characters in the file, and setting the elements of arr to their character codes.
You need to parse the file contents as integers.
int arr[10];
for (i = 0; i < 10; i++) {
fscanf(outp, "%d", &arr[i]);
}

Removing duplicate elements in array without sorting - wrong output

I have been trying to write a function to remove duplicate elements in an array of ints without sorting it.
For that task, I created a function named removeDuplicateElements, which gets an array and its string, and returns a new dynamically allocated array, which is a copy of the original array with removal of all duplicates elements. This function also returns by reference the size of the new array.
I also used in my code functions which build a dynamic array and print it.
Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
void printArray(int *arr, int size);
int *buildArray(int size);
int *removeDuplicateElements(int *arr, int size, int *newSize);
void main() {
int size,newSize;
int *arr;
int *newArr;
printf("please enter a number for the size of array: ");
scanf("%d", &size);
printf("\nenter %d numbers: ", size);
arr = buildArray(size);
printf("\nthe array after removing the duplicate elements is: ");
newArr = removeDuplicateElements(arr, size, &newSize);
printArray(newArr, newSize);
free(newArr);
free(arr);
}
/* this function removes all duplicate elements in a given array */
int *removeDuplicateElements(int *arr, int size, int *newSize) {
int *newArr;
int count = size, i, j;
/* finding the new size of the original array with removal its duplicate elements */
for (i = 1; i < size; i++) {
for (j = 0; j < size; j++)
if (arr[i] == arr[j] && i != j) {
count--;
break;
}
}
newArr = (int*)malloc(count * sizeof(int)); /* dynamically allocating the new array */
count = 1;
newArr[0] = arr[0];
/*adding the elements in the new array without changing the order*/
for (i = 1; i < size; i++) {
for (j = 0; j < size; j++) {
if (arr[i] == arr[j] && i != j) {
break;
}
if (j == size - 1) {
newArr[count] = arr[i];
count++;
}
}
}
*newSize = count; /* updating the size of the new array */
return newArr; /* returning the address of new array */
}
void printArray(int *arr, int size) {
int i;
for (i = 0; i < size; i++)
printf("%d ", arr[i]);
printf("\n");
}
int *buildArray(int size) {
int i;
int *arr = (int*)malloc(size * sizeof(int));
if (!arr) {
printf("ERROR! Not enough memory!\n");
exit(1);
}
for (i = 0; i < size; i++)
scanf("%d", &arr[i]);
return arr;
}
I get a wrong output for that code, and I dont understand why
For instance, for the following array with size=5 :1 1 3 1 3
I get the wrong output 1, whereas the expected outout is
1 3.
Any help would be appreciated.
You're firstly calculating the size of the new array incorrectly. For your example input, when you're looking at the first 3, it scans the whole array to see how many 3's there are and finds there are 2 and concludes it's a duplicate. It then does the exact same thing for the 2nd 3. So you end up with the size of the new array as 1.
Instead of scanning the whole array, you only want to scan the array for the elements preceding the one you're checking. So something like this.
for(i=1;i<size;i++)
{
for (j = 0; j < i; j++)
if (arr[i] == arr[j])
{
count--;
break;
}
}
And for the code that fills the new array has the same problem
for(i=1;i<size;i++)
{
for (j = 0; j < i; j++)
if (arr[i] == arr[j])
{
break;
}
if(j==i)
{
newArr[count++]=arr[i];
}
}
There is an alternative way of doing it, ofcourse it involves modifying the original array but this is just an alternative. Basically it involves crossing off the duplicate element by replacing it with a maximum value like 0xFFFF.
int* removeDuplicateElements(int *arr, int size, int *newSize)
{
int *newArr;
int count = size, i, j;
int index = 0;
/*finding the new size of the original array with removal its duplicate elements*/
for(i=0;i<size;i++)
{
for (j = i+1; j < size; j++)
if (arr[i] == arr[j] && arr[i] != 0xFFFF)
{
count--;
arr[j] = 0xFFFF;
}
}
printf("Size is %d \n", count);
newArr = (int*)malloc(count * sizeof(int)); /*dynamically allocating the new array*/
for(i=0;i<size;i++)
{
if(arr[i] != 0xFFFF)
newArr[index++] = arr[i];
}
*newSize = count; /*updating the size of the new array*/
return newArr; /*returning the address of new array*/
}

Saving matrix to a file (.txt format) in C

I'm having some issues trying to write a quick program which purpose is, given a matrix (bidimensional array allocated dinamically), saving it to a file. When checking the resulting output file I'm given at the end of each line of the file the following simbols, in bold and red, "\00".
This is my code:
/*\param n number of rows
\param m number of columns
\param mat pointer to the matrix
\param f file already opened in write mode where to write the matrix
*/
int save_to_file (char** mat, unsigned n, unsigned m, FILE* f){
int i, j;
for(i = 0;i <= n; i++)
for(j = 0; j <= m; j++)
if(j == m)
fprintf(f, "%c\n", mat[i][j]);
else
fprintf(f, "%c", mat[i][j]);
if (f == NULL)
return -1;
else
return 0;
}
Is the issue lying in the way I'm writing on the file? If that's the case, can anybody help me to fix it?
The first problem with your code is the range in the for loops. If you have n rows the loop must go from 0 to n-1 (both included). So these lines:
for(i = 0;i <= n; i++)
for(j = 0; j <= m; j++)
if(j == m)
shall be
for(i = 0;i < n; i++) // Remove =
for(j = 0; j < m; j++) // Remove =
if(j == m-1) // Insert -1
The second problem is that you check for f being NULL after you have used f. That is a bad idea and it may/will cause a program crash if f is NULL. Instead do the check as the first thing in the function:
int save_to_file (char** mat, unsigned n, unsigned m, FILE* f){
if (f == NULL) return -1;
....
....
return 0;
}
The third problem is the way you access the matrix. If your matrix is a 2D array (as you write in the text without posting the code), you can't access it correctly as a char**. The char** can be used when you have an array of char-pointers that points to arrays of chars. But not for a 2D array.
Below is an example of how the function could look for a matrix based on a 2D array.
#include <stdio.h>
int save_to_file (unsigned n, unsigned m, char mat[n][m]){
int i, j;
for(i = 0; i < n; i++)
for(j = 0; j < m; j++)
if(j == m-1)
printf("%c\n", mat[i][j]);
else
printf("%c", mat[i][j]);
}
int main(void) {
char a[2][3] = {{'a','b','c'},{'d','e','f'}};
save_to_file(2,3,a);
return 0;
}
Output:
abc
def
Notice: The above function prints to stdout instead of a file but that can be easily changed by using fprintf

Files and generating numbers ,c programming

Task is next:
After you generate 20 random numbers and read informations from file tombula.txt which contains names of users and their 9 numbers,print the first user (his/her name) who has 3 numbers from own array equal to generated numbers.
This is my part of code where i generate numbers and read from file but I don't know how to find that first person who has 3 numbers from array equal to generated numbers,if you know how to write that please help:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include <time.h>
typedef struct
{ char name[50];
int num[8];
}someone;
void generating(int[]);
int check(int[], int);
int main(void)
{
someone *pK = NULL;
int i, j, count = 0, tip;
FILE *F;
int generated[30];
int brojac[5];
srand(time(NULL));
generating(generated);
for (int j = 0; j < 20; j++)
printf("%d ", generated[j]);
printf("\n\n\n");
F = fopen("tombula.txt", "r");
if (F == NULL)
{
printf("error!");
exit(1);
}
i = 0;
while (feof(F) == 0)
{
pK = ((someone *)realloc(pK, (i + 1)*sizeof(someone)));
fscanf(F, "%s", pK[i].name);
for (j = 0; j < 8; j++)
fscanf(F, "%d", &pK[i].num[j]);
i++;
count++;
}
i--;
count--;
for (int z = 0; z < count; z++){
printf("%s ", pK[z].name);
for (int k = 0; k < 8; k++){
printf("%d ", pK[z].num[k]);
}
printf("\n");
}
return 0;
}
void generating(int numbers[])
{
int i, tmp;
for (i = 0; i < 20; ++i)
{
tmp = rand() % 50 + 1;
if (check(numbers, tmp))
{
--i;
continue;
}
numbers[i] = tmp;
}
}
int check(int b[], int a){
int i;
int n = 8;
for (i = 0; i < 20; ++i)
{
if (b[i] == a)
return 1;
}
return 0;
}
1.You opened file in r mode.
2.In a loop (loop must work until EOF) read data stored in file using fscanf() .Store name into char array and number into integer array (As you defined in struct).
3.Inside loop check if the 3 numbers matches with the numbers generated and if they do print the persons name and use break to come out of loop.
4.After this close the file.

(C) Radix Sort array from text file

I am attempting to get this queue-based radix sort to work, but I can't seem to figure out what's wrong with it. It uses a text file as the input medium and throws tons of errors when I try to compile it and run it with the text file.
Any advice would be helpful at this point.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
#define SHOWPASS
//Compiled Using GNU GCC Compiler
void radixsort(int *a[], int n)
{
int i, b[MAX], m = *a[0], exp = 1;
for (i = 0; i < n; i++)
{
if (*a[i] > m)
m = a[i];
}
while (m / exp > 0)
{
int queue[10] =
{ 0 };
for (i = 0; i < n; i++)
queue[*a[i] / exp % 10]++;
for (i = 1; i < 10; i++)
queue[i] += queue[i - 1];
for (i = n - 1; i >= 0; i--)
b[--queue[*a[i] / exp % 10]] = *a[i];
for (i = 0; i < n; i++)
*a[i] = b[i];
exp *= 10;
#ifdef SHOWPASS
printf("\nPASS : ");
radixsort(a, n);
#endif
}
}
int main( int argc, char *argv[] )
{
if ( argc != 3 )
{
printf("Need two input parameters in the following order: \n 1. Input file path \n 2. Number of elements in file\n");
return 0;
}
int num_elements = atoi(argv[2]);
int *input_arr = (int*) calloc (num_elements, sizeof(int));
int i;
FILE *fin; //File pointer to read input file
fin = fopen(argv[1], "r"); //Initialize file pointer
for(i=0; i<num_elements; i++)
{
fscanf(fin, "%d", &(input_arr[0]));
}
radixsort(input_arr[0], i);
printf ( "\nArray before sorting: \n") ;
for ( i = 0 ; i < num_elements ; i++ )
printf ( "%d\t", input_arr[0] ) ;
printf ( "\n\n");
return 0;enter code here
}
There are plenty of errors in your code. Firstly, the way you are taking input is incorrect.
fscanf(fin, "%d", &(input_arr[0]));
While taking input, the array input_arr is filled with a single input value at input_arr[0]. The rest of the input is over-written at input_arr[0].
Replace it with, fscanf(fin, "%d", &(input_arr[i]));.
Even you are displaying output in incorrect way.After sorting, the same output will be displayed num_elements times because of the following incorrect statement:
printf ( "%d\t", input_arr[0] ) ;
Again replace the above statement with printf ( "%d\t", input_arr[i] ).
As an impact of following incorrect statement,
fscanf(fin, "%d", &(input_arr[i])); ,
your program experiences a Segmentation fault, since in function radixsort, you are iterating from 0 to n-1(Number of elements).
for (i = 0; i < n; i++)
{
if (*a[i] > m)
m = a[i];
}
As only a[0] is filled with input value and rest of the array(from a[1] to a[n-1]) contains a garbage value, you will get a runtime error while executing your code.
There are lot of other bugs too, which i had fixed. This is the perfect running code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define MAX 10
// #define SHOWPASS
// Compiled Using GNU GCC Compiler
void radixsort(int a[], int n)
{
int i, b[MAX], m = a[0], exp = 1;
for (i = 0; i < n; i++)
{
if (a[i] > m)
m = a[i];
}
while (m / exp > 0)
{
int queue[10] = { 0 };
for (i = 0; i < n; i++)
queue[a[i] / exp % 10]++;
for (i = 1; i < 10; i++)
queue[i] += queue[i - 1];
for (i = n - 1; i >= 0; i--)
b[--queue[a[i] / exp % 10]] = a[i];
for (i = 0; i < n; i++)
a[i] = b[i];
exp *= 10;
#ifdef SHOWPASS
printf("\nPASS : ");
radixsort(a, n);
#endif
}
}
int main(int argc, char *argv[])
{
if (argc != 3)
{
printf
("Need two input parameters in the following order: \n 1. Input file path \n 2. Number of elements in file\n");
return 0;
}
int num_elements = atoi(argv[2]);
int *input_arr = (int *)calloc(num_elements, sizeof(int));
int i;
FILE *fin; // File pointer to read input file
fin = fopen(argv[1], "r"); // Initialize file pointer
for (i = 0; i < num_elements; i++)
{
fscanf(fin, "%d", &(input_arr[i]));
}
radixsort(input_arr, i);
printf("\nArray before sorting: \n");
for (i = 0; i < num_elements; i++)
printf("%d\t", input_arr[i]);
printf("\n\n");
return 0;
}

Resources