Confusion in arrays - arrays

Recently I was learning about arrays passing to functions (by passing their base address to a pointer defined as parameter in function and then using pointer arithmetic for extracting the whole array subsequently)
For practice I was asked to calculate the average marks of a class of 70 students with their marks listed in an array named "marks" and was asked to define a variable with parameter as a pointer
and calculate average from there.
The data given to me was that student 1 scored 40 , student 2 scored 41, student 3 scored 42....and so on.
Here is my attempt at it:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <time.h>
float average(int *b)
{
int sum = 0;
for (int i = 1; i <= 70; i++)
{
sum = sum + *b;
b = b + 1;
}
printf("the value of sum is %d\n", sum); // this value is changing every time I run the program
return (((float)sum) / 70);
}
int main()
{
int marks[70];
marks[0] = 40;
for (int i = 0; i < 68; i++)
{
marks[i + 1] = marks[i] + 1;
}
printf("the value of marks of 10th child is %d\n", marks[9]); // Just for checking if I am correct!(yes! the ans does come out to be 49!)
printf("the value of average marks of the class is %f\n", average(&marks[0]));
return 0;
}
to my surprise the value kept changing every time I ran it. Can anyone give a hint where am I wrong?

I was asked to calculate the average marks of a class of 70 students with their marks listed in an array named "marks"
In the posted code, we can find the following declaration
int marks[70];
The size is correct, but note that it's uninitialized, so that the values of its elements are undeterminated. The code, though, tries to assign the correct values immediately after.
marks[0] = 40; // "student 1 scored 40, student 2 scored 41, student 3 scored 42...
// and so on."
for (int i = 0; i < 68; i++)
{ // ^^^^^^
marks[i + 1] = marks[i] + 1;
} // ^^^^^
The last mark assigned is marks[67 + 1], which leaves marks[69] (the actual last element of the array) undeterminated.
There are many ways to achive the correct result, some may find the following appropriate.
int marks[70] = { 40 };
for (int i = 0; i + 1 < 70; ++i)
{ // ^ ^^^^^^^^^^
marks[i + 1] = marks[i] + 1;
}
I was learning about arrays passing to functions (by passing their base address to a pointer defined as parameter in function and then using pointer arithmetic for extracting the whole array subsequently)
Using indices often yields more readable code, so I won't use "pointer arithmetic" in the following snippet.
I'd suggest to always pass the size of the array, not only the pointer.
Note how many "magic" numbers, like 70 and the wrong 68, are spread (and repeated) throughout the posted code, limiting its generality and rising the chances of errors.
I'd also extract the logic of the previous snippet into a separate function, easily modifiable and testable.
#include <stdio.h>
double average(size_t n, int *marks)
{
long sum = 0;
for (size_t i = 0; i < n; ++i)
{
sum += marks[i];
}
return (double)sum / n;
}
void fill_linear(size_t n, int *arr, int first_value)
{
for (size_t i = 0; i < n; ++i)
{
arr[i] = first_value++;
}
}
int main(void)
{
enum { n_students = 70 };
int marks[n_students];
fill_linear(n_students, marks, 40);
printf("Average: %.1f\n", average(n_students, marks)); // Average: 74.5
return 0;
}

You're problem is related to the fact (as mentioned in my comment) that your array is uninitialized.
The memory for it has been allocated but its still random jumble data.
Luckily you overwrite that data for all entries in the array, except for the last one. The last entrance is basically a random value at this point.
So thats the reason the output keeps changing, your actuall bug is a bit simpler.
In the for loop where you calculate the sum, you iterate from i = 0 to i = 67. So with the +1 offset you change all the entries from 1 to 68, so the last entrance (marks[69]) doesn't get touched.
Fixed code:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
float average(int *b) {
int sum = 0;
for (int i = 1; i <= 70; i++) {
sum = sum + *b;
b = b + 1;
}
printf("the value of sum is %d\n",
sum); // this value is changing every time I run the program
return (((float)sum) / 70);
}
int main() {
int marks[70];
marks[0] = 40;
for (int i = 0; i < 68; i++) {
marks[i + 1] = marks[i] + 1;
}
printf("the value of marks of 10th child is %d\n",
marks[9]); // Just for checking if I am correct!(yes! the ans does come
// out to be 49!)
printf("the value of average marks of the class is %f\n", average(&marks[0]));
return 0;
}
PS:
In the average function ,you use pointer arithmetic to loop over the input array, which is considered bad practice by a lot of people. Also, youre basiaclly not using the for-loop incrementor variable you create (int i). A easier and safer way to do this is :
float average(int *b) {
int sum = 0;
for (int i = 0; i < 69; i++) {
sum += b[i];
}
printf("the value of sum is %d\n",
sum); // this value is changing every time I run the program
return (((float)sum) / 70);
}

Related

C program to find integer closest to 10

I am writing a program that will take any number of integers. The program will end when the terminal 0 has been entered. It will then output the number closest to 10 (except for the terminal character). If there are several numbers closest to 10 then it should output the last number entered.
My current code does read the numbers from the input stream, but I don't know how to implement the logic so that the program will give me the number that is closest to 10.
I know, that I need to keep track of the minimum somehow in order to update the final result.
#include <stdio.h>
int main() {
int n = 1;
int number = 1;
int numberArray[n];
int resultArray[n];
int min;
int absMin;
int result;
int finalResult;
while (number != 0) {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
for (int i = 0; i < n; i++) {
min = 10 - numberArray[i];
if (min < 0) {
absMin = -min;
}
else {
absMin = min;
}
resultArray[i] = absMin;
result = resultArray[0];
if (resultArray[i] < result) {
finalResult = resultArray[i];
}
}
printf("%d\n", finalResult);
return 0;
}
here's a simple code I wrote
One thing I must say is you can't simply declare an array with unknown size and that's what you have done. Even if the no. of elements can vary, you either take input the number of elements from the user OR (like below) create an array of 100 elements or something else according to your need.
#include <stdio.h>
#define _CRT_NO_WARNINGS
int main() {
int n = 0;
int number = 1;
int numberArray[100];
int resultArray[100];
int minNumber;
int *min;
do {
scanf("%d", &number);
numberArray[n] = number;
n++;
}
while (number != 0);
resultArray[0] = 0;
min = &resultArray[0];
minNumber = numberArray[0];
for (int i = 0; i < n-1; i++) {
if(numberArray[i]>=10){
resultArray[i] = numberArray[i] - 10;
}
if(numberArray[i]<10){
resultArray[i] = 10 - numberArray[i];
}
if(resultArray[i] <= *min){
min = &resultArray[i];
minNumber = numberArray[i];
}
}
printf("\n%d",minNumber);
return 0;
}
I have improved your script and fixed a few issues:
#include <stdio.h>
#include <math.h>
#include <limits.h>
int main()
{
int n;
int number;
int numberArray[n];
while (scanf("%d", &number) && number != 0) {
numberArray[n++] = number;
}
int currentNumber;
int distance;
int result;
int resultIndex;
int min = INT_MAX; // +2147483647
for (int i = 0; i < n; i++) {
currentNumber = numberArray[i];
distance = fabs(10 - currentNumber);
printf("i: %d, number: %d, distance: %d\n", i, currentNumber, distance);
// the operator: '<=' will make sure that it will update even if we already have 10 as result
if (distance <= min) {
min = distance;
result = currentNumber;
resultIndex = i;
}
}
printf("The number that is closest to 10 is: %d. It is the digit nr: %d digit read from the input stream.\n", result, resultIndex + 1);
return 0;
}
Reading from the input stream:
We can use scanf inside the while loop to make it more compact. Also, it will loop one time fewer because we don't start with number = 1 which is just a placeholder - this is not the input - we don't want to loop over that step.
I used the shorthand notation n++ it is the post-increment-operator. The operator will increase the variable by one, once the statement is executed (numberArray entry will be set to number, n will be increased afterwards). It does the same, in this context, as writing n++ on a new line.
Variables:
We don't need that many. The interesting numbers are the result and the current minimum. Of course, we need an array with the inputs as well. That is pretty much all we need - the rest are just helper variables.
Iteration over the input stream:
To get the result, we can calculate the absolute distance from 10 for each entry. We then check if the distance is less than the current minimum. If it is smaller (closer to 10), then we will update the minimum, the distance will be the new minimum and I have added the resultIndex as well (to see which input is the best). The operator <= will make sure to pick the latter one if we have more than one number that has the same distance.
I have started with the minimum at the upper bound of the integer range. So this is the furthest the number can be away from the result (we only look at the absolute number value anyway so signed number don't matter).
That's pretty much it.

What is Segmentation Core dump? And how do I fix it? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 3 years ago.
Improve this question
I am trying to write a code that will take an input of 20 integers from the user and manipulate it to find the mean, max, min, and standard deviation. Everything I have found online says to pass an array by address, which I think I did correctly, but may be my issue.
I keep getting "Segmentation fault (core dumped)" after I enter in the 20 numbers and don't know why. I also get this warning "hw06.c:38: warning: format '%d' expects type 'int', but argument 2 has type 'int **'" and I don't know how to fix that either.
After these errors are fixed, I don't think my loop for max/min and possible standard deviation are correct.
I have tried many different things. I finally got rid of the errors I was previously having, for not passing my array by address but I don't even know how to tackle this error. I pasted my entire code below:
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#define SIZE 20
void getInput(int score[SIZE]);
double getMean(int *score[SIZE]);
void getCalc(int *score[SIZE], double avg);
int main()
{
int score[SIZE] = {0};
double avg;
getInput(score[SIZE]);
avg = getMean(&score[SIZE]);
getCalc(&score[SIZE], avg);
return 0;
}
void getInput(int score[SIZE])
{
int count = 0;
printf("Enter 20 integer values -> ");
for (count = 0; count < SIZE; count++)
{
scanf("%d ", &score[count]);
printf("%d", score[count]);
}
return;
}
double getMean(int* score[])
{
int count = 0;
int totalNum = 0;
double avg;
printf("\nData set as entered: ");
for (count = 0; count < SIZE; count++)
{
totalNum = totalNum + *score[count];
printf("%d, ", *score[count]);
}
avg = ((double)totalNum / 20.0);
printf("\nMean: %.2lf", avg);
return avg;
}
void getCalc(int* score[], double avg)
{
int count = 0;
double deviation;
double standard;
int max;
int min;
for (count = 0; count < SIZE; count++)
{
deviation += (*score[count] - avg);
//printf("%lf", deviation);
if (*score[count] > *score[count - 1])
{
max = *score[count];
}
else
{
min = *score[count];
}
}
standard = (double)deviation / 20.0;
printf("\nMean Deviation: %.2lf ", standard);
printf("\nRange of Values: %d, %d", min, max);
return;
}
The code should get an array of 20 values from the user, then pass it to the next function where it will print the numbers (this time separated by commas and that last one doesn't need one but I'm not sure how to get rid of that). It then needs to find the average, which was working correctly before but I have changed things since then.
Next it needs to pass the average to the standard deviation function where it calculates standard deviation (the sum of each value - average divided by 20) and finds the max/min of the array.
I am currently just getting an error.
You made a very good attempt at the program, so I have edited it with extensive comments. The fundamental problem was trying to work with an array of pointers, instead of an array of values.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h> // added a library for integer range
#include <math.h>
#define SIZE 20
void getInput(int score[]); // revised these function protoypes
double getMean(int score[]);
void getCalc(int score[], double avg);
int main(void) // added void for modern definition
{
int score[SIZE] = {0}; // change to array of int not pointers
double avg;
getInput(score); // you were passing a out-of-bounds element
avg = getMean(score); // ditto
getCalc(score, avg); // ditto
return 0;
}
void getInput(int score[]) // passing an array of int not pointers
{
int count = 0;
printf("Enter 20 integer values -> ");
for (count = 0; count < SIZE; count++)
{
scanf("%d", &score[count]); // removed a space from scanf, added the &
//printf("%d", score[count]); // removed the & but commented out
}
return;
}
double getMean(int score[]) // passing an array of int not pointers
{
int count = 0;
int totalNum = 0;
double avg;
printf("\nData set as entered: ");
for (count = 0; count < SIZE; count++)
{
totalNum = totalNum + score[count]; // removed the *
printf("%d, ", score[count]); // ditto
}
avg = ((double)totalNum / 20.0);
printf("Mean: %.2lf\n", avg); // repostioned the newline
return avg;
}
void getCalc(int score[], double avg) // passing an array of int not pointers
{
int count = 0;
double deviation = 0; // initialise this to 0
double standard;
int max = INT_MIN; // initialise these two
int min = INT_MAX;
for (count = 0; count < SIZE; count++)
{
deviation += score[count] - avg; // removed the *
//printf("%lf", deviation);
if (score[count] > max) // removed the *s, changed the comparison
{ // it was indexing out-of-bounds
max = score[count]; // removed the *
}
if (score[count] < min) // replaced the else with this line
{
min = score[count]; // removed the *
}
}
standard = (double)deviation / 20.0;
printf("Mean Deviation: %.2f\n", standard); // repostion \n, remove `l` from `lf`
printf("Range of Values: %d, %d\n", min, max); // ditto
return;
}
Program output:
Data set as entered: 1, 3, 5, 2, 5, 8, 9, 1, 2, 3, 4, 5, 5, 1, 1, 7, 3, 7, 9, 0,
Mean: 4.05
Mean Deviation: 0.00
Range of Values: 0, 9

What is wrong with my hash function?

I'm trying to create a hash table. Here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define N 19
#define c1 3
#define c2 5
#define m 3000
int efort;
int h_table[N];
int h(int k, int i)
{
return (k + i*c1 + i*i*c2) % N;
}
void init()
{
for (int i = 0; i < N; i++)
h_table[i] = -1;
}
void insert(int k)
{
int position, i;
i = 0;
do
{
position = h(k, i);
printf("\n Position %d \n", position);
if (h_table[position] == -1)
{
h_table[position] = k;
printf("Inserted :elem %d at %d \n", h_table[position], position);
break;
}
else
{
i += 1;
}
} while (i != N);
}
void print(int n)
{
printf("\nTable content: \n");
for (int i = 0; i < n; i++)
{
printf("%d ", h_table[i]);
}
}
void test()
{
int a[100];
int b[100];
init();
memset(b, -1, 100);
srand(time(NULL));
for (int i = 0; i < N; i++)
{
a[i] = rand() % (3000 + 1 - 2000) + 2000;
}
for (int i = 0; i < N ; i++)
{
insert(a[i]);
}
print(N);
}
int main()
{
test();
return 0;
}
Hash ("h") function and "insert" function are took from "Introduction to algorithms" book (Cormen).I don't know what is happening with the h function or insert function. Sometimes it fills completely my array, but sometimes it doesn't. That means it doesn't work good. What am I doing wrong?
In short, you are producing repeating values for position often enough to prevent h_table[] from being populated after only N attempts...
The pseudo-random number generator is not guaranteed to produce a set of unique numbers, nor is your h(...) function guaranteed to produce a mutually exclusive set of position values. It is likely that you are generating the same position enough times that you run out of loops before all 19 positions have been generated. The question how many times must h(...) be called on average before you are likely to get the value of an unused position? should be answered. This may help to direct you to the problem.
As an experiment, I increased the looping indexes from N to 100 in all but the h(...) function (so as not to overrun h_table[] ). And as expected the first 5 positions filled immediately. The next one filled after 3 more tries. The next one 10 tries later, and so on, until by the end of 100 tries, there were still some unwritten positions.
On the next run, all table positions were filled.
2 possible solutions:
1) Modify hash to improve probability of unique values.
2) Increase iterations to populate h_table
A good_hash_function() % N may repeat itself in N re-hashes. A good hash looks nearly random in its output even though it is deterministic. So in N tries it might not loop through all the array elements.
After failing to find a free array element after a number of tries, say N/3 tries, recommend a different approach. Just look for the next free element.

How do I print out 100 numbers in an array then add them using C

I'm trying to print out 100 numbers from an array using a loop and then add them all together. So far I have:
#include <stdio.h>
#include <stdlib.h>
int main(){
int* number = malloc(101 * sizeof(int));
int num = 0;
number[num] = 1;
while (number[num] <= 100){
printf(" %d\n ", number[num]);
num = num +1;
number[num] = number[num]+1;
}
return 0;
}
but this just prints 1 once.
number[num] = number[num]+1;
You only properly set number[0]. Now you are trying to take whats in number[1] and add to it, in the first iteration. You didn't set it to anything though, leaving it uninitialised. This is undefined behaviour. What you most likely wanted to do is
number[num] = number[num-1]+1;
To add one to the previous number before after printing it. Now it will print fine.
To add them up, simply do
for (int a = 0; a < 100; a++) {
number[100] += number[a]; // add number[a] to result
}
printf("%d\n",number[100]);
Also, don't forget to free your dynamically allocated array at the end.
Try this:
#include <stdio.h>
int main () {
int n[ 100 ]; /* n is an array of 100 integers */
int i,j;
int sum = 0;
/* initialization */
for ( i = 0; i < 100; i++ ) {
n[ i ] = i + 100; /* set element at location i to i + 100 */
}
/* output each array element's value */
for (j = 0; j < 100; j++ ) {
printf("Element[%d] = %d\n", j, n[j]);
sum += n[j];
}
printf("Sum of Elements = %d\n", sum);
return 0;
}
Remember that you should declare an array, then initialize it, print it out and after all print out the sum
You can just print out 1 to 100, then you could quickly use some maths to get the count of all numbers added together, for example, one of Gauss' algorithms, specifically http://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/
There’s a popular story that Gauss, mathematician extraordinaire, had a lazy teacher. The so-called educator wanted to keep the kids busy so he could take a nap; he asked the class to add the numbers 1 to 100.
Here's what I would do: -
int i = 0;
for (i = 1; i <= 100; i++) {
printf("%d", i);
}
// gauss technique 100(100 + 1) / 2
int count = (100 * 100 + 100 * 1) / 2;
printf("all numbers added: %d", count);

C Array of Counters

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int main()
{
int i; //Counting Variable for loop
int sales[30]; //Array for sales people
//Creates Gross for 30 Indiviudals
for (i = 0; i < 30; i++)
{
sales[i] = ( rand() % 15000) + 1;
}
printf("Original List\n");
for (i = 0; i < 30; i++)
{
printf("%d\n", sales[i]);
}
return 0;
}
Im tying to make a program that takes 30 random numbers between 0 and 15000, then applies the equation (100+a*0.09), then sorts the answers from highest to lowest. Im getting stuck on how to apply the equation to the values founded in the array since they are program generated.
you can just loop through the array again and assign them again just like you looped through the two previous times
for (i=0; i < 30; i++){
sales[i] = 100 + sales[i] * .09;
}
You mean:
for (i = 0; i < 30; i++)
{
printf("%f\n", 100 + (float)sales[i] * 0.09);
}
?
You can also store it in an other array (of float/double). Not sure to understand correctly as it seems very simple!
Edit: if you need to sort it you would have to store it in an array (float vals[30]; let say) and then have a look to 'qsort(…)' function in order to order the values.

Resources