Search an array - replace values with values from another array in C - c

I am new to programming and I trying to build different kinds of fun little applications in order to understand the basics. I have started with C to really start out at the bottom, so the below refers to C.
So basically I have to arrays a[] and replace[], which are both 200 long filled with random numbers.
I want to search a[] for the value 32 (ele) and replace any occurrence of that value with the corresponding value in replace[].
E.g. if: a[22] = 32, replace[22] = 78 => a[22]=78
At the same time I would like it to 'record' the index number (22) and log that to a file.
I can't get it to go through a[] multiple times and replace every instance. It only replaces 1 instance and then breaks.
I have no error msg. for below code. Hope you can help a newbie out.
If you have the answer, please also take a minute to explain how/why.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
FILE *ifp, *ofp;
int ix;
int ik;
int i;
int change;
int count = 0;
int ele = 32;
int num = 200;
int a[200];
int replace[200];
void swap(int a[], int replace[], int change)
{
int temp = replace[change];
a[change] = replace[change];
a[change] = temp;
ifp = fopen("/Users/kjaerolsen/tmp/ilog.txt", "a+");
fprintf(ifp, "%d\n", change);
fclose(ifp);
}
int main(int argc, char *argv[]) {
// creates array with random numbers to draw new numbers from.
srand(time(NULL));
for (int ik = 0; ik < 200; ik++)
{
rand();
replace[ik] = rand() % 200; // / rand_max;
}
for (int ik = 0; ik < 200; ik++)
{
fprintf(ifp, "%d\n", replace[ik]);
}
// creeates main array with random numbers.
srand(time(NULL));
for (int ix = 0; ix < 200; ix++)
{
rand();
a[ix] = rand() % 200; // / rand_max;
}
for (int ix = 0; ix < 200; ix++)
{
printf("plads %d i array: %d\n",ix, a[ix]);
}
// Looks for number 32 (ele) in array
i = 0;
for (int i =0; i < 200; i++)
{
change++;
swap(int a[], int replace[], int change)
count++;
}
if (count == 0)
printf("%d is not present in array.\n", ele);
else
printf("%d is present %d times in array.\n", ele, count);
// Opens the file and rewrites the new array.
ifp = fopen("file1.txt", "w+");
for (int ix = 0; ix < 200; ix++)
{
fprintf(ifp, "%d\n", a[ix]);
}
fclose(ifp);
printf("very done...");
return (0);
}

Must fopen ifp before the second loop and fclose it after. Your current code goes segmentation fault:
ifp = fopen( ... );
for (int ik = 0; ik < 200; ik++)
{
fprintf(ifp, "%d\n", replace[ik]);
}
fclose( ifp );
Also, you can swap with three XOR:
a ^= b;
b ^= a;
a ^= b;
and no temp variables;

A tremendous thanks for all your help. I finally succeeded in making it work - and it is beautiful. I moved it out of an actual function and in to the loop, since there was no reel need to call a function. Secondly, I was missing the top IF. But most important #micarelli your suggestions with XOR did the trick.
Maybe not much for a couple of hardcore coders like yourself, but it was really satisfying.
I posted the final snippet of code below.
i = 0;
for (int i =0; i < 200; i++)
if (a[i] == ele)
{
a[i] ^= replace[i];
count++;
}
if ( count == 0 )
printf("%d is not present in array.\n", ele);
else
printf("%d is present %d times in array.\n", ele, count);
// Opens the file and rewrites the new array.
ifp = fopen("/Users/kjaerolsen/tmp/file1.txt", "w+");
for (int ix = 0; ix < 200; ix++)
{
fprintf(ifp, "%d\n", a[ix]);
}
fclose(ifp);

Related

Finding Prime and Composite Elements in an array. Print primes in ascending order and composite in descending order

I am successful in identifying prime and composite from an array. But my qsort function seem to not have any effect when I print the output. I need the primes to be ascending and composite to be descending. When I run the code, it does not sort the output, though it identifies primes and composites.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void) {
int a = *(int *)a_void;
int b = *(int *)b_void;
return b - a;
}
int main() {
int i = 0, n, x, p, c, z, w, j = 0, k = 0, cmpst, null;
int prm;
int prime[50], composite[50], input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &n);
printf("Enter the numbers.\n", n);
for (i = 0; i < n; i++) {
scanf("%d", &input[i]);;
}
for (i = 0; i < n; i++) {
if (input[i] % 2 != 0) {
prime[p++] = input[i];
prm = p;
} else
if (input[i] >= 2 && input[i] % 2 == 0) {
composite[c++] = input[i];
cmpst = c;
}
}
printf("Prime Numbers:");
qsort(prime, prm, sizeof(int), compare_Asc);
for (i = 0; i < p; i++) {
printf("%d", prime[p]);
}
printf("Composite Numbers:");
qsort(composite, cmpst, sizeof(int), compare_Desc);
for (i = 0; i < c; i++) {
printf("%d", composite[c]);
}
return 0;
}
There are some major issues, in the posted code, worth mentioning.
Variables
Declaring all the variables at the beginning of the scope, instead of just before where they are used, can hide bugs.
Uninitialized variables, are an even worse source of errors, because their values are indeterminated.
int i=0, n, x, p, c, z, w, j=0, k=0, cmpst, null;
// ^ ^ ^^^^ ?
// ... Later, in the code:
prime[p++] = input[i];
// ^^^ What value is incremented?
// Where is [p++]? Is it inside the prime array?
A correct initialization would prevent undefined behavior.
int p = 0, c = 0;
int composite[50], input[50];
for(int i = 0; i < n ; ++i) {
if ( is_prime(input[i]) ) { // <-- More on this, later.
prime[p++] = input[i];
}
else {
composite[c++] = input[i];
}
}
Loops
This happens a couple of times, just because the code itself is duplicated (another code smell):
for(i=0;i<p;i++){
// ^^^^^^^^^^^ We want to iterate over [0, p).
printf("%d",prime[p]);
// ^ But this always prints the element one past the end
}
Even if it's just a simple loop, it could be a good idea to write a (testable and reusable) function
void print_arr(size_t n, int arr[n])
{
for (size_t i = 0; i < n; ++i) {
printf("%d ", arr[i]);
} // ^
putchar('\n');
}
// ... Later, in main:
print_arr(p, prime);
print_arr(c, composite);
Primes or composite
I am successful in identifying prime and composite from an array
Well, no. Not with this code, I'm sorry.
if (input[i]%2 != 0) { // Those are ALL the ODD numbers!
prime[p++]=input[i];
}
else if(input[i]>=2 && input[i]%2==0){ // Those are the EVEN numbers greater than 0
composite[c++]=input[i];
}
// What about 0 and the even numbers less than 0?
Not all the odd numbers are prime number (it's a little more complicated than that) and 2 itself is a prime, not a composite.
It's unclear to me if this is a terminology issue or if the snippet is only a placeholder for a proper algorithm. In any case, there are multiple examples of primality test functions in SE sites (I'm quite confident some are posted almost every day).
Overflow risk
See chux - Reinstate Monica's comment:
return a-b; risks overflow when a, b are large int values.
Consider return (a > b) - (a < b); for a full range solution.
Single letter variables names are to be avoided... except for i, j and k used in for() loops only.
You're not updating the index of the arrays c and p as the numbers are being printed out. The arrays are being sorted fine.
In the code below I also remove redundant variables, and rename n to input_count, c to compo_count and p to prime_count.
#include <stdio.h>
#include <stdlib.h>
int compare_Asc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return a - b;
}
int compare_Desc(const void *a_void, const void *b_void)
{
int a = *(int *) a_void;
int b = *(int *) b_void;
return b - a;
}
int main ()
{
int i = 0;
int input_count = 0;
int prime_count = 0;
int compo_count = 0;
int prime[50];
int composite[50];
int input[50];
printf("How many inputs are you be working with?\nNote: 50 Maximum Inputs\n");
scanf("%d", &input_count);
printf("Enter the %d numbers.\n", input_count);
for (i = 0; i < input_count; i++)
{
scanf("%d", &input[i]);
}
for (i = 0; i < input_count; i++)
{
if (input[i] % 2 != 0)
{
prime[prime_count] = input[i];
prime_count += 1;
}
else if (input[i] >= 2 && input[i] % 2 == 0)
{
composite[compo_count] = input[i];
compo_count += 1;
}
}
printf("Prime Numbers:");
qsort(prime, prime_count, sizeof(int), compare_Asc);
for (i = 0; i < prime_count; i++)
{
printf("%d ", prime[i]); // <<-- HERE, not [p]
}
printf( "\n" );
printf ("Composite Numbers:");
qsort(composite, compo_count, sizeof(int), compare_Desc);
for (i = 0; i < compo_count; i++)
{
printf("%d", composite[i]); // <<-- HERE, not [c]
}
printf( "\n" );
return 0;
}

Reading digits into an array and sorting it

The task is as follows: to fill the file with numbers using the generation() function - an array cannot be used here. Then read the digits into the array by the read_file() function into the array and sort it using the quick sort method. Output to the console.
I wrote the code as I logically understood it myself, but a set of values is output to the console after sorting, as it is output in case of an error with a lack of memory, random numbers with cons sometimes. Maybe it's worth filling in a dynamic array? And why, if I know a specific number of elements?
Please help me figure it out.
#include <stdio.h>
#include <stdlib.h>
#define N 10
#define A -25000
#define B 25000
void generation();
void read_file();
void method_simple_sort();
int main(void) {
generation();
method_simple_sort();
return EXIT_SUCCESS;
}
void generation() {
FILE *file;
int i;
file = fopen("index.txt", "w");
srand(time(0));
for (int i = 0; i < N; i++) {
fprintf(file, "%d\n", A + rand() % (A - B + 1));
}
fclose(file);
}
void read_file() {
FILE *file;
int i, a[N] = { 0 };
file = fopen("index.txt", "r");
for (i = 0; i < N; i++) {
fscanf(file, "%d ", &a[i]);
}
fclose(file);
for (int i = 0; i < N; i++)
printf("%d ", a[i]);
}
void method_simple_sort() {
int a[N], i = 0, k = 0, ind_max = 0, temp = 0;
read_file();
for (k = 0; k < N - 1; k++) {
ind_max = k;
for (i = 1 + k; i < N; i++) {
if (a[i] > a[ind_max]) {
ind_max = i;
}
}
temp = a[k];
a[k] = a[ind_max];
a[ind_max] = temp;
}
// вывод результатов в файл
printf("\n\nПростого выбора: ");
for (int i = 0; i < N; i++) {
printf("%d ", a[i]);
}
printf("\n\n\n\n");
}
The function method_simple_sort defines a local array variable int a[N].
It then calls read_file(), but read_file() does not fill this local array variable defined in method_simple_sort.
Instead it fill its own local array variable (called also int a[N], but it's a different one than the one in method_simple_sort).
The bottom line is that when method_simple_sort attempts to sort a it sorts an array containing uninitialized data.
Hence the "garbaged" values that you see printed at the end.
The array used by the methods read_file and method_simple_sort aren't the same. When you declare anything inside a function it is translated at low level in space to allocate on the stack when you call the function.
You should transform read_file(void) into read_file(int *a) without declaring another instance of an array inside read_file.
By doing that you can pass a reference to the array declared inside method_simple_sort.
In particular:
void read_file(int *a) {
FILE *file;
int i;
/* a[N] = { 0 };*/
...
}
void method_simple_sort() {
int a[N], i = 0, k = 0, ind_max = 0, temp = 0;
read_file(a);
...
}

in bubble sort how do i implement if the value changed its position then change/assign the previous text name to change its position also

I have a text file where it contains all the data i need then i will read the data and do a bubble sort for Total Vaccines available and using bubble sort i arranged it in descending order but i need help with how to change the Vaccine_Code according the newly arranged Total_Vaccines. Please Help
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct dist
{
char Name_Vaccine[5][15];
char Vaccine_Code[5][10];
char Producing_Country[5][15];
int Dosage_Required[5];
float Population_Covered[5];
float Total_Vaccines[5];
char distcode[100][100];
float distvalue[100];
};
int main()
{
struct dist sort[20];
int i, j, n=5,m;
float a,b;
FILE *f = fopen("vaccine.txt", "r");
FILE *fp = fopen("dist.txt","r");
//For Vaccine.txt
for (int i = 0; i < 5; i++)
{
fscanf(f,"%s",sort->Name_Vaccine[i]);
fscanf(f,"%s",sort->Vaccine_Code[i]);
fscanf(f,"%s",sort->Producing_Country[i]);
fscanf(f,"%d",&sort->Dosage_Required[i]);
fscanf(f,"%f",&sort->Population_Covered[i]);
fscanf(f,"%f",&sort->Total_Vaccines[i]);
}
fclose(f);
//Original Order
printf("The numbers arranged in Original order for Vaccine.txt are given below\n");
for (i = 0; i < n; ++i)
{
printf("%s %.4f\n",sort->Vaccine_Code[i], sort->Total_Vaccines[i]);
}
// sorting begins ... //
for (i = 0; i < n; ++i)
{
for (j = i + 1; j < n; ++j)
{
if (sort->Total_Vaccines[i] < sort->Total_Vaccines[j])
{
a = sort->Total_Vaccines[i];
sort->Total_Vaccines[i] = sort->Total_Vaccines[j];
sort->Total_Vaccines[j] = a;
}
}
}
printf("The numbers arranged in Descending order for Vaccine are given below\n");
for (i = 0; i < n; ++i)
{
printf("%s %9.4f\n",sort->Vaccine_Code[i], sort->Total_Vaccines[i]);
}
return 0;
}
Instead of moving your data it's probably better to just move pointers to your data. Basically you initialize an array of size n with the numbers 0, ..., n - 1. Then you sort the array using the comparison function that compares the values behind the index.
It should look something like the modified code below. But beware, I didn't test it.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define ARRAYSIZE 5
struct dist
{
char Name_Vaccine[5][15];
char Vaccine_Code[5][10];
char Producing_Country[5][15];
int Dosage_Required[5];
float Population_Covered[5];
float Total_Vaccines[5];
char distcode[100][100];
float distvalue[100];
};
int main()
{
struct dist sort[20];
int i, j, n=ARRAYSIZE,m;
int idxArray[ARRAYSIZE];
float a,b;
FILE *f = fopen("vaccine.txt", "r");
FILE *fp = fopen("dist.txt","r");
//For Vaccine.txt
for (int i = 0; i < ARRAYSIZE; i++) {
fscanf(f,"%s",sort->Name_Vaccine[i]);
fscanf(f,"%s",sort->Vaccine_Code[i]);
fscanf(f,"%s",sort->Producing_Country[i]);
fscanf(f,"%d",&sort->Dosage_Required[i]);
fscanf(f,"%f",&sort->Population_Covered[i]);
fscanf(f,"%f",&sort->Total_Vaccines[i]);
idxArray[i] = i; // piggyback initialization of the index array
}
fclose(f);
//Original Order
printf("The numbers arranged in Original order for Vaccine.txt are given below\n");
for (i = 0; i < n; ++i) {
printf("%s %.4f\n",sort->Vaccine_Code[i], sort->Total_Vaccines[i]);
}
// sorting begins ... //
for (i = 0; i < n; ++i) {
for (j = i + 1; j < n; ++j) {
if (sort->Total_Vaccines[idxArray[i]] < sort->Total_Vaccines[idxArray[j]]) {
a = idxArray[i];
idxArray[i] = idxArray[j];
idxArray[j] = a;
}
}
}
printf("The numbers arranged in Descending order for Vaccine are given below\n");
for (i = 0; i < n; ++i) {
printf("%s %9.4f\n",sort->Vaccine_Code[idxArray[i]], sort->Total_Vaccines[idxArray[i]]);
}
return 0;
}
Obviously, with an array size of 5 the exact method doesn't play that much of a role. It would even be acceptable to search for the smallest element, greater than the last written element, for each line printed in the last loop.

How to read in string input from the user and allocate it?

So I've been working on this code for a while now and I can't figure out why it's not working. Basically I'm suppose to create a program using functions to read in string input from the user which is the filename for “data.txt”. I need a function to determine the number of rows that are in the file in order to allocate an array of character pointers. Then my program should print out the strings read from the file. Finally the program should free the allocated memory.
This is my non-working code.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX_WIDTH 144
void getFileName(char* array1);
int getLineCount(FILE* data, int max);
char** createArryOfPtrs(int rows);
int main(void)
{
int max = 0;
int rows;
char array1[MAX_WIDTH];
FILE* data = fopen(array1, "r");
getFileName(array1);
getLineCount(data, max);
createArryOfPtrs(rows);
fclose(data);
return 0;
}
void getFileName(char* array1)
{
printf("Enter filename: ");
fscanf(stdin, "%144[^\t]", array1);
}
int getLineCount(FILE* data, int max)
{
int i = 4;
char *array1[MAX_WIDTH];
if(data != NULL)
{
while(fgets(*array1, MAX_WIDTH, data) != NULL)
{
i+=1;
}
}
return i;
}
char** createArryOfPtrs(int rows)
{
int r = 4, c = 9, i, j, count;
char *array1[r];
for(i =0; i < r; i++)
{
array1[i] = (char*)malloc(c * sizeof(char));
}
count = 0;
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
array1[i][j] = ++count;
}
}
for(i = 0; i < r; i++)
{
for(j = 0; j < c; j++)
{
printf("%c", array1[i][j]);
}
}
return 0;
}
This is the text file.
larry snedden 123 mocking bird lane
sponge bob 321 bikini bottom beach
mary fleece 978 pasture road
hairy whodunit 456 get out of here now lane
I'm still new to C so I'm very confused. Appreciate any help I can get.
Order matters! You get the name of the file to open after you call fopen. That means the data in array1 will be uninitialized and indeterminate (and seem random).
You need to read the name of the file first.
This issue should have been very clear if you did a little rubber duck debugging.

Segmentation Fault on Last Iteration

I am trying to randomly fill a 2d array with values then multiply them, but for some odd reason when I run my code, on the last iteration, I get a segmentation fault. I have tried decreasing the number I am passing it and everything, but the fault still persists. Here is the code I am trying to execute, any help is much appreciated, thanks.
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
FILE *matrixFile;
int n = atoi(argv[1]); // the number of matrices
int i, j; // must declare outside of for loop due to resolve C99 mode error
double arrA[n][n];// = CreateRandomMatrix(n);
double arrB[n][n];
double sumArr[n][n];
matrixFile = fopen("home/acolwell/Documents/CPE631_HW2_Number1/results.txt", "w+");
printf("Usage: %s <size of nxn matrices>\n", argv[1]);
// randomly populate arrA and arrB
for(i = 0; i < n; i++)
{
printf("%d\n", i);
for(j = 0; j < n; j++)
{
printf("%4d", j);
arrA[i][j] = (double)rand()/(double)RAND_MAX;
arrB[i][j] = (double)rand()/(double)RAND_MAX;
}
}
printf("Exiting Matrix randomization");
// multiply the matrices and write them to the file
for(i = 0; i < n; i++)
{
for(j = 0; j < n; j++)
{
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix ");
fprintf(matrixFile, "%0.3lf\n", sumArr[i][j]);
}
}
if(matrixFile)
{
fclose(matrixFile);
}
matrixFile = NULL;
return 0;
}
This error is going to come down to writing off the end of your array or failure to open your file. I would suggest running gdb to check out your program when it is running, but from a quick glance I wonder if you don't mean to have
"/home/acolwell/Documents/CPE631_HW2_Number1/results.txt"
as the file to write instead of
"home/acolwell/Documents/CPE631_HW2_Number1/results.txt"
I would suggest checking the result of your fopen call before calling fprintf.
If n is large enough, you'll generate a stack overflow using VLAs. I've verified this experimentally with your code (e.g. use n of 5000).
So, you'll need to use malloc to allocate from heap. But, that would require a bit of a rewrite.
Here's a way to use heap allocation and get the benefit of a VLA [using some slight trickery]:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define C(_arr) (double (*)[(size_t)(n)]) _arr
void
docalc(FILE *fout,int n,double arrA[n][n],double arrB[n][n],double sumArr[n][n])
{
// must declare outside of for loop due to resolve C99 mode error
int i,
j;
// randomly populate arrA and arrB
for (i = 0; i < n; i++) {
printf("%d\n", i);
for (j = 0; j < n; j++) {
printf("%4d", j);
arrA[i][j] = (double) rand() / (double) RAND_MAX;
arrB[i][j] = (double) rand() / (double) RAND_MAX;
}
}
printf("Exiting Matrix randomization");
// multiply the matrices and write them to the file
for (i = 0; i < n; i++) {
for (j = 0; j < n; j++) {
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix\n");
fprintf(fout, "%0.3lf\n", sumArr[i][j]);
}
}
}
int
main(int argc, char *argv[])
{
FILE *matrixFile;
int n = atoi(argv[1]); // the number of matrices
printf("Usage: %s <size of nxn matrices>\n", argv[1]);
matrixFile = fopen("/tmp/results.txt", "w+");
if (matrixFile == NULL) {
perror("fopen");
exit(1);
}
double *arrA = malloc(sizeof(double) * n * n);
double *arrB = malloc(sizeof(double) * n * n);
double *sumArr = malloc(sizeof(double) * n * n);
docalc(matrixFile,n,C(arrA),C(arrB),C(sumArr));
if (matrixFile)
fclose(matrixFile);
matrixFile = NULL;
return 0;
}
I just compiled and tested your code. The file name you are giving is incorrect; you need a "/" in front of "home".
Not sure what the requirements are, but write your matrixFile like a matrix: add a new line after each row of the matrix is "multiplied", not after every element:
for(i = 0; i < n; i++) {
for(j = 0; j < n; j++) {
sumArr[i][j] = arrA[i][j] * arrB[i][j];
printf("Writing matrix ");
fprintf(matrixFile, "%0.3lf ", sumArr[i][j]);
}
fprintf(matrixFile, "\n");
}
Also, take Craig Easley's comment seriously. Stack Overflow can happen, even off the premises this website ;) Consider allocating your matrix dynamically on the heap.

Resources