Array giving different outputs in C? - c

Every time I execute my program which finds the average in a ten element array. I get slightly different results. Any idea why?
Here is my code:
#include "stdio.h"
int main()
{
float array[10];
for (int n=0; n<10;n++)
{
array[n] = n * 4.76;
printf("array[%i] = %.4f\n",n,array[n] );
}
float total;
for (int n=0; n<10; n++)
{
total = total + array[n];
}
printf("Average: %.4f\n", total/10 );
return 0;
}
and some sample results are:
array[0] = 0.0000
array[1] = 4.7600
array[2] = 9.5200
array[3] = 14.2800
array[4] = 19.0400
array[5] = 23.8000
array[6] = 28.5600
array[7] = 33.3200
array[8] = 38.0800
array[9] = 42.8400
Average: 21.2598
array[0] = 0.0000
array[1] = 4.7600
array[2] = 9.5200
array[3] = 14.2800
array[4] = 19.0400
array[5] = 23.8000
array[6] = 28.5600
array[7] = 33.3200
array[8] = 38.0800
array[9] = 42.8400
Average: 21.2826

When declaring variables in C, make sure they're initialised to a default value. Variables allocated on the stack are usually not initialised to their default values, rather, they are initialised with junk.
So, before starting summation, initialise your variable as
float total = 0.0f;
and you should get the same answer every time.

Related

Can I initialize integers in an array if the size of it is not given in advance in C?

I have a simple question. We know that we can set a particular limit to a string and initialize any words in it as long as the words does not exceed the limit of the string array.As an example:
str[100]="HELLO WORLD";
Here I didnt have to put 100characters.But can i do the same with an array of integers by using for loop and avoid garbage values?Like:
4-array size
2 2 3-given value
here i just want to assign some integer values to an array and the rest of the indices that are left unasiggned will be automatically assigned to 0. Then even if i the user does not give me the array size i can put the other indices to 0. As an example:
n=5.
number[5];
for(i=0;i<n;i++)
{
scanf(ā€œ%dā€,&number[i]);
//suppose user only assigned three integers which is
//number[0],number[1],number[2]
// the rest of the array number[3],number[4] are garbage values which i
//want to turn them to 0ā€™s.how?
}
You can use variable length arrays. However, such arrays cannot be initialized, so you have to zero them manually if you want to avoid garbage values.
int n = 5;
int arr[n];
memset(arr, 0, sizeof arr);
Or use dynamic allocation:
int n = 5;
int *arr = calloc(n, sizeof *arr);
Yes you can do this.
The following demonstrates this:
#include <stdio.h>
int main()
{
// char array of size 6 initialized with A,B and C in the first 3 elements
char str[6] = "ABC";
for (int i = 0; i < 6; i++)
{
printf("str[%d] = %d\n", i, str[i]);
}
// int array of size 6 initialized with 1, 2 and 3 in the first 3 elements
int array[6] = {1,2,3};
for (int i = 0; i < 6; i++)
{
printf("array[%d] = %d\n", i, array[i]);
}
}
Output:
str[0] = 65
str[1] = 66
str[2] = 67
str[3] = 0
str[4] = 0
str[5] = 0
array[0] = 1
array[1] = 2
array[2] = 3
array[3] = 0
array[4] = 0
array[5] = 0
All elements that have not been initialized have a default value of 0.

Why is p[0]++ different from *(p)++ in C

When I tried to execute these codes in C
#include <stdio.h>
int main(void)
{
int arr[] = {10, 20};
int *p = arr;
p[0]++; // *(p)++;
printf("arr[0] = %d, arr[1] = %d",arr[0], arr[1]);
return 0;
}
output: arr[0] = 11, arr[1] = 20
on replacing p[0]++; by *(p)++;
output : arr[0] = 10, arr[1] = 20
Please explain why this is. I know a[i] is equivalent to *(a + i)
The expression:
p[0]++;
basically increments the value at index 0.
While
*(p)++
Increments the pointer to the next address .
Example :
int arr = {10,20};
int *p = arr; // p points to the first element of array, i.e 10
*(p)++; // now p points to the next element i.e 20.
below code can be used:
p[0]++ means = p[0] + 1;
p[0]++ = 10 + 1;
p[0]++ = 11;
You can't do with this same thing with an array, so be careful.
I hope it helps!

Transferring values from a char array to an integer array in C programming

I am having the following problem. I have created a char array which represents a series of characters and numbers - this was designed to model a string read or got from a text file. I wish to then search this string using the "search" function defined below, pulling out only the numbers before 'H' and assigning to a separately defined integer array. I find when I use gdb, this function works fine. However, only part of the array is ever returned - the first 8 elements to be exact. Would anyone please be able to explain why this is from looking at the code below?
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void search(char buffer[], int size, int array[]);
int main (void)
{
char buffer[1000];
memset(buffer, 0, sizeof(buffer));
buffer[0] = 2;
buffer[1] = 'H';
buffer[2] = 3;
buffer[3] = 'H';
buffer[4] = 6;
buffer[5] = 'H';
buffer[6] = 4;
buffer[7] = 'H';
buffer[8] = 6;
buffer[9] = 'H';
buffer[10] = 7;
buffer[11] = 'H';
buffer[12] = 11;
buffer[13] = 'H';
buffer[14] = 12;
buffer[15] = 'H';
buffer[16] = 17;
buffer[17] = 'H';
int* array ;
array = malloc(sizeof(buffer) * sizeof(int));
search(buffer, sizeof(buffer), array);
for(int i = 0, n = sizeof(array); i < n; i++)
{
printf("array[%d] = %d\n", i, array[i]);
}
free(array);
}
void search(char buffer[], int size, int array[])
{
int position = 0;
for (int i = 0; i < size; i++)
{
if(buffer[i] == 'H')
{
*(array + position) = buffer[i-1];
position++;
}
}
}
The compiler outputs the following:
array[0] = 2
array[1] = 3
array[2] = 6
array[3] = 4
array[4] = 6
array[5] = 7
array[6] = 11
array[7] = 12
which as can be seen is missing the ninth position in the array - value 17. In fact, if I fgets into a buffer a much bigger set of numbers and 'H's, I am always returned an array of size 8. Why is this? Any help would be much appreciated.
The problem here is with
n = sizeof(array)
array being a pointer, sizeof(array) will give you the size of the pointer (as sizeof(array) here is essentially sizeof(int *), which seems to be 8 for your platform), not the cumulative size (or number of elements) in the array.
One possible way to get what you want will be the search() to return the count of element put into the array and use that return value in the for loop for printing the required elements from array.
Replace n = sizeof(array) with n = strlen(buffer) / 2 will do (you want n to be the number of filled elements in the array).
Btw,
You need to make sure the buffer always has correct pairs.
Would be safer to declare the buffer like this char buffer[1000] = "";
"I am always returned an array of size 8" - that's because sizeof(int) in 64b-machine is 8 bytes, which is what you got from sizeof(array) - as array here is pointer.

External function not working - but not sure why

I'm currently working on some code and, up to now, everything has compiled fine. The aim of the code is this:
read input from data file and assign values to an array.
"smooth the data" by taking average of the data on a given interval and replacing each value in that interval with the average.
It's the second part that causing me trouble. In the external function, for some reason it works when my 'for' loop looks like this:
for(i=t; i<t+z; i++)
But I don't want it to do that. I want it to do this:
for(i=t*z; i<(t+1)*z; i++)
When I try to compile, it just crashes out on me. Anyone know the reason why? It's been puzzling me for hours now. All the code is shown below by the way:
#include <stdio.h>
#include <stdlib.h>
float foo(float*, int, int);
int main(int argc, char* argv[])
{
FILE *input;
const char datafile[]="datainput.dat";
input=fopen(datafile, "r");
int i;
int N=0, t=0;
int z=100;
int M=10;
float *a, avg;
a=(float*)malloc(M*sizeof(float));
if((input!=(FILE*) NULL))
{
while(fscanf(input, "%e", &a[t++])==1)
{
if (t>=M)
{
M*=2;
a=(float *)realloc(a, M*sizeof(float));
}
N++;
}
float u[N];
for(t=0; t<N; t++)
{
avg = foo(a, z, t);
u[t] = avg;
}
fclose(input);
}
else
printf("Input file could not be opened.\n");
return(0);
}
float foo(float b[], int z, int t)
{
int i;
int k=0;
float avg;
float sum=0;
for(i=t*z; i<(t+1)*z; i++)
{
sum+=b[i];
k++;
}
avg = sum/(float)k;
return(avg);
}
side note: you'll probably notice the poor practise of defining float u[N] half way down the code. I don't really like this being there, but you'll note that N is a variable that counts the number of values in the input file (initially unknown) and is initally set to N=0, so I'm not sure how I get around that.
additionally, I asked the question earlier on here but my realloc has no clause if it fails. it's something i'm working on though but at the moment it compiles without it being there.
Also, all the data values are of the form float with seven decimal places and in scientific notation, hence the %e.
Thank you!
EDIT: here are some of the values from the data file. Even though the values on the left look ordered, they are actual values in the file and not there to denote the values on the right.
8.0800000e+00 7.0872796e-01
8.0900000e+00 7.1941101e-01
8.1000000e+00 2.1635408e+00
8.1100000e+00 -5.4200807e-01
8.1200000e+00 1.1046968e+00
8.1300000e+00 1.5833782e+00
8.1400000e+00 6.6122899e-01
8.1500000e+00 1.7922273e+00
8.1600000e+00 1.2446803e+00
8.1700000e+00 3.7869871e-01
8.1800000e+00 1.4793635e+00
8.1900000e+00 1.0508171e+00
8.2000000e+00 9.1012735e-01
8.2100000e+00 6.0967729e-01
8.2200000e+00 1.3834455e+00
8.2300000e+00 -5.2312924e-01
8.2400000e+00 9.2566688e-01
8.2500000e+00 7.8145188e-01
8.2600000e+00 4.1410150e-01
8.2700000e+00 1.9796986e+00
8.2800000e+00 5.9372874e-01
8.2900000e+00 1.8696331e+00
8.3000000e+00 2.3058409e+00
So I've been staring at this for awhile. This is what I came up with. The interval (i'm assuming is 100). for the sake of sanity I've changed it to 5 in the code that follows because your sample posted data is only 46 elements long. I must assume yours is much larger than this.
Some things to note:
foo() no longer relies on some whacky 'where do I compute my average' variables. The caller is responsible for passing the starting location and count of elements to average. This, as you will see, makes that code much simpler. This was fundamentally the heart of the problem to begin with, as your allocation loop was fine (save for not checking your realloc return value). There is no reason to complicate that function to try and compute an average somewhere in the middle of some larger array. Keep it simple. Just have the caller tell the function where to start and how many to average.
Though it wasn't specified, I believe z is your "interval" width. The thing to note in the code below is the interval-count calculation. The number of intervals is simply (N+(z-1))/z, which will result in the number of intervals to process, including the last interval which may only be a partial. From there, we simply walk through the original array, partitioning up in z-sized slices, calculating the average, then rewriting the interval we just averaged with the said-same average. The last interval, again, can be a partial, which requires a little bit of extra care.
I changed the data file to be a command line parameter argv[1]. Made it easier for me to test.
Sure hope this is what you were looking for. Thx for the fun, and don't forget to reset the z value in this code back to 100 if you plan on using it.
#include <stdio.h>
#include <stdlib.h>
float foo(float a[], int count);
int main(int argc, char* argv[])
{
if (argc !=2)
return EXIT_FAILURE;
FILE *input=fopen(argv[1], "r");
if (input != NULL)
{
int z=5,t=0;
int M=10,N=0;
float *a = malloc(M*sizeof(float));
while(fscanf(input, " %e", a + N) ==1 )
{
if (++N>=M)
{
void *tmp = realloc(a, (M*=2)*sizeof(float));
if (tmp != NULL)
{
a = tmp;
}
else
{
perror("Failed to allocate memory.");
exit(EXIT_FAILURE);
}
}
}
// compute number of intervals we will process. the last
// interval may be only a partial.
for (t=0;t<N;t+=z)
{
// how many we're doing in this interval
int count = (z < (N-t) ? z : (N-t)), k=0;
float avg = foo(a+t, count);
printf("Avg[%d] = %e\n", t/z, avg);
// smooth over original array with just-found svg.
for (k=0;k<count; a[t+k++] = avg);
}
fclose(input);
// dump the final array content
for (t=0;t<N;++t)
printf("a[%d] = %e\n", t, a[t]);
// release original array.
free(a);
}
else
{
perror("Input file could not be opened.");
}
return(0);
}
// find the average of the range of floats we're given.
float foo(float a[], int count)
{
float sum = 0;
int i = 0;
for(i=0; i<count; sum += a[i++]);
return (sum)/(float)(count);
}
Output (z=5)
Avg[0] = 5.139628e+00
Avg[1] = 3.791246e+00
Avg[2] = 5.332921e+00
Avg[3] = 3.949121e+00
Avg[4] = 5.420036e+00
Avg[5] = 3.866650e+00
Avg[6] = 5.024508e+00
Avg[7] = 3.941051e+00
Avg[8] = 5.466672e+00
Avg[9] = 2.305841e+00
a[0] = 5.139628e+00
a[1] = 5.139628e+00
a[2] = 5.139628e+00
a[3] = 5.139628e+00
a[4] = 5.139628e+00
a[5] = 3.791246e+00
a[6] = 3.791246e+00
a[7] = 3.791246e+00
a[8] = 3.791246e+00
a[9] = 3.791246e+00
a[10] = 5.332921e+00
a[11] = 5.332921e+00
a[12] = 5.332921e+00
a[13] = 5.332921e+00
a[14] = 5.332921e+00
a[15] = 3.949121e+00
a[16] = 3.949121e+00
a[17] = 3.949121e+00
a[18] = 3.949121e+00
a[19] = 3.949121e+00
a[20] = 5.420036e+00
a[21] = 5.420036e+00
a[22] = 5.420036e+00
a[23] = 5.420036e+00
a[24] = 5.420036e+00
a[25] = 3.866650e+00
a[26] = 3.866650e+00
a[27] = 3.866650e+00
a[28] = 3.866650e+00
a[29] = 3.866650e+00
a[30] = 5.024508e+00
a[31] = 5.024508e+00
a[32] = 5.024508e+00
a[33] = 5.024508e+00
a[34] = 5.024508e+00
a[35] = 3.941051e+00
a[36] = 3.941051e+00
a[37] = 3.941051e+00
a[38] = 3.941051e+00
a[39] = 3.941051e+00
a[40] = 5.466672e+00
a[41] = 5.466672e+00
a[42] = 5.466672e+00
a[43] = 5.466672e+00
a[44] = 5.466672e+00
a[45] = 2.305841e+00
Output (z=10)
Avg[0] = 4.465437e+00
Avg[1] = 4.641021e+00
Avg[2] = 4.643343e+00
Avg[3] = 4.482779e+00
Avg[4] = 4.939867e+00
a[0] = 4.465437e+00
a[1] = 4.465437e+00
a[2] = 4.465437e+00
a[3] = 4.465437e+00
a[4] = 4.465437e+00
a[5] = 4.465437e+00
a[6] = 4.465437e+00
a[7] = 4.465437e+00
a[8] = 4.465437e+00
a[9] = 4.465437e+00
a[10] = 4.641021e+00
a[11] = 4.641021e+00
a[12] = 4.641021e+00
a[13] = 4.641021e+00
a[14] = 4.641021e+00
a[15] = 4.641021e+00
a[16] = 4.641021e+00
a[17] = 4.641021e+00
a[18] = 4.641021e+00
a[19] = 4.641021e+00
a[20] = 4.643343e+00
a[21] = 4.643343e+00
a[22] = 4.643343e+00
a[23] = 4.643343e+00
a[24] = 4.643343e+00
a[25] = 4.643343e+00
a[26] = 4.643343e+00
a[27] = 4.643343e+00
a[28] = 4.643343e+00
a[29] = 4.643343e+00
a[30] = 4.482779e+00
a[31] = 4.482779e+00
a[32] = 4.482779e+00
a[33] = 4.482779e+00
a[34] = 4.482779e+00
a[35] = 4.482779e+00
a[36] = 4.482779e+00
a[37] = 4.482779e+00
a[38] = 4.482779e+00
a[39] = 4.482779e+00
a[40] = 4.939867e+00
a[41] = 4.939867e+00
a[42] = 4.939867e+00
a[43] = 4.939867e+00
a[44] = 4.939867e+00
a[45] = 4.939867e+00
It unlikely that sum+=b[i]; will access the array b between 0 and N-1.
You have allocated 10 block for floats which is passed as array parameter for function. In statement sum+=b[i], here b[i] will not ensure that you are not referring at the index out side the array size, as you have "i" which can go beyond 10 e.g. when z=100 and t=1.

Incrementing variables using pointers

I'm very new to dealing with pointers, and my C knowledge is fairly small. I'm trying to understand pointers. I wrote the following code to print a list of variables (a to f) like so:
0
1
2
3
4
5
I wrote the following code to do this:
#include <stdio.h>
int main(){
int a,b,c,d,e,f;
int *p;
int i;
a = b = c = d = f = 0;
p = &a;
for (i = 0; i < 5; i++){
*p += i;
printf("%d\n", *p);
p++;
}
return 0;
}
The idea was it works through the variables and increments each by an ever-increasing number (i). I am assuming that as you initialize the variables at the same time, they'd be placed next to each other in memory. However, I get the following output:
0
1
2
3
-1218283607
If I change the for loop to only go from 0 to 3 (i < 4), it works fine, printer 0 1 2 and 3. But when I wish to print the variable f as well, it doesn't seem to set it.
As I said, I'm very new to pointers so I've probably overlooked something silly, but I've been looking through my code over and over, trying to work it out.
Thanks in advance.
There is no guarantee that a, b, c, d, e and f will be adjacent in memory. If you want that sort of guarantee you need to use an array.
#include <stdio.h>
int main() {
int a[6];
int *p;
int i;
a[0] = a[1] = a[2] = a[3] = a[4] = a[5] = 0;
p = &a[0];
for (i = 0; i < 6; i++){
*p += i;
p++;
}
for(i = 0; i < 6; i++) {
printf("%d\n", a[i]);
}
return 0;
}
Here int a[6] is declaring an array named a that can hold six integers. These six integers can obtained via a[0], a[1], a[2], a[3], a[4] and a[5]. You are guaranteed that a[0], a[1], a[2], a[3], a[4] and a[5] are layed out contiguously in memory. Thus the line
p = &a[0];
sets p to the address of the first element. Each increment of this pointer moves us forward one position in the array.
The second for loop shows that first for loops correctly sets a[i] to i for i in {0, 1, 2, 3, 4, 5}. If you run this program you will see
0
1
2
3
4
5
on the console.
You forgot to initialize e. But yes, use a packed array.
It isn't safe to assume that stack variables are arranged in memory in any particular order.
You need to use an array, a struct or possibly a union to gurantee the ordering of your ints.
union {
int ary[6];
struct {
int a;
int b;
int c;
int d;
int e;
int f;
} s;
} u = {0};
p = &u.s.a;
for (i = 0; i < 5; i++){
*p += i;
printf("%d\n", *p);
p++;
}

Resources