Explain the result values of c program relevant with printf - c

I was tried to print values of a float array with 7 elements. I assigned only 3 values and they are belong to float, double and integer.
Code:
#include <stdio.h>
int main(){
float array [7];
float f = 3.24;
double d = 23.5;
int i = 4;
array[0] = f;
array[1] = i;
array[2] = d;
int n = sizeof(array)/sizeof(float);
printf("Number of Elements : %d \n\n\n",n);
for(int j = 0; j < n ; j++){
printf("%.2f ,",array[j]);
}
printf("\b ");
}
I got an output as follows :
Number of Elements : 7
3.24 ,4.00 ,23.50 ,-1.#R ,96627196995476105000000000000000.00 ,96629547147269436000000000000000.00 ,0.00
I want to clear is my code correct? And why last four values are different to each other. What are these values?

The last values are known as garbage values in C.
If you do not initialize a variable explicitly in C, it's value could be anything before you explicitly assign something to it. This anything could be garbage; the language standard does not specify what it should be.
You can read this blog for How C compiler decides garbage values: http://blog.aditech.info/2008/02/how-c-compiler-decides-garbage-values.html.

First.
Yes, your code is correct (add return 0 command at the end of your main() function though). However, it needs to be more specific, which leads to your second question.
Second.
C is a language that allows a programmer to do lots of things, but it also requires the programmer to do lots of manual coding.
So, when you declare an array of 7 items, C compiler marks a region of memory to accommodate those items (in this case of the type of float). But it doesn't actually check what that region of memory contains until you explicitly assign the values. In your case the last four values (which you have not assigned yourself) are just garbage left in the region of memory marked for your array.
Once again, compiler does not clear the memory for you when you declare the array, it just marks the region of memory. It's your responsibility to assign default values to the array.
Your possible solution is to manually initialize all of the elements of your array to some default value (for example, a 0), like this:
float array[7] = {0}

Related

Determinant of the matrix — recursive function

I wrote a program which returns a determinant of a matrix. I have a problem, actually; it always returns the "0" value. I notice that my determinant always stays as 0 even though I add numbers to it.
I wrote an English translation in the comments to understand my program better. I use a method in which we select one number and then crossed the element from the column and line of the selected number and then calculate the determinant of the uncrossed elements.
#include<stdio.h>
#include<stdlib.h>
float wznmacierz(float*macierz, int rozmiar)/*"macierz" means a matrix and "rozmiar" is a size of matrix */
{
if (rozmiar == 1)
return *macierz;
float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); // making a second matrix for uncrossed elements.
int wyznacznik = 0; // wyznacznik is the determinant of matrix
for(int element_S = 0; element_S <rozmiar; element_S++) //element s is a number from first line
{
for (int w = 1 ; w < rozmiar; w++ ) //line of checking element
{
for(int kolumna = 0; kolumna < rozmiar; kolumna++)//column of chcecking element
{
if(kolumna == element_S)
continue;
*podmacierz = macierz[(rozmiar*w)+(kolumna)];
podmacierz++;
}
}
wyznacznik += macierz[element_S]*( element_S % 2 ? -1: 1)* wznmacierz(podmacierz, rozmiar-1);
}
return wyznacznik;
}
void main()
{
float a[2][2]={{1,3},{9,8}};
printf("%d", wznmacierz(a,2));
}
Change void main to int main, because main returns an int.
In printf("%d", wznmacierz(a,2)); , change %d to %g, because %d is for formatting an int, but wznmacierz returns a float. %g will format a float. Also add \n after %g to complete the line being output.
In printf("%d", wznmacierz(a,2));, change a to *a because wzmacierz expects a pointer to a float, not a pointer to an array of float. This is a kludge to get your program “working” quickly; see Notes below.
You cannot use podmacierz both to hold the start address of the allocated array and to increment to places within the array. Inside the loop on element_S, put float *p = podmacierz; to make a second pointer, and change the uses of podmacierz inside that loop to p.
Before returning from the function, use free(podmacierz); to release the allocated space.
Notes
In main, a is declared as float a[2][2]. This makes it an array of 2 arrays of 2 float. In the call wznmacierz(a,2), a is automatically converted to a pointer to its first element. That produces a pointer to an array of 2 float. However, wznmacierz is declared with a parameter float*macierz, which is a pointer to a float.
One way to fix this is to pass *a. Once a is converted to a pointer to its first element, a pointer to an array of float, then applying * produces the thing that pointer points to, an array of float. Then that array of float is automatically converted to a pointer to its first element, producing a pointer to a float. You could also write wznmacierz(&a[0][0], 2).
This produces a pointer of the correct type for wznmacierz, which then access the array by calculating element locations, using macierz[(rozmiar*w)+(kolumna)]. This nominally calculates correct addresses for the array elements, since arrays are laid out in memory contiguously, but it is bad style unless necessary, and some people might consider it not to conform to the C standard in a pedantic sense.
One fix would be to define a in main as float a[2*2] = {1, 3, 9, 8};. Then the matrix is implemented as single flat array of float everywhere it is used.
Another fix would be to upgrade wznmarcierz to use two-dimensional arrays. A number of changes are needed to do this. I have not tested them, but I think they are at least:
Change wznmacierz(a,2) to wznmacierz(2, a).
Change the declaration of wznmacierz to float wznmacierz(int rozmiar, float macierz[rozmiar][rozmiar]).
Change the use of macierz inside the function from macierz[(rozmiar*w)+(kolumna)] to macierz[w][kolumna].
Change float *podmacierz = malloc((rozmiar-1)*(rozmiar-1)*sizeof(float)); to float (*podmacierz)[rozmiar-1] = malloc((rozmiar-1) * sizeof *podmacierz);.
Remove the float *p = podmaciarz; that I told you to insert above.
Inside the loop using w, insert float *p = podmacierz[w];.
Change macierz[element_S] to macierz[0][element_S].
Change wznmacierz(podmacierz, rozmiar-1) to wznmacierz(rozmiar-1, podmacierz).

How do I find the number of element of an array which have their size previously undefined

I'm trying to make an array which have it's element coming from a user input. This array would first have it's size undefined since we don't know how much int would the user input, but then I'm not able to find the amount of element in the array like this unless I put a counter on the loop function.
Here is the code that I've made:
int cross[] = {0};
int k;
for (k = 0; k >= 0; k++){
scanf("%d", &cross[k]);
if (cross[k] == -1){
break; //stop the user from inputing numbers if user input -1
}
int p = sizeof(cross) / sizeof(cross[0]);
If I were to do printf("%d", p), it would always give me 1 as a result. I'm wondering if there is any other way of doing this other than putting a counter on the for loop.
Thanks!!
This phrase from your question is both wrong and dangerous: "This array would first have it's size undefined".
The following line of code defines a fixed-size array that has exactly one element:
int cross[] = {0};
The compiler knows it's one element because you supplied one initializer value {0}. If you supplied this {0, 5, 2}, it would allocate 3 integers, and so on.
This means when you store into cross[k] and k is larger than zero, you're actually exceeding the bounds of your allocated array, which C doesn't catch at compile time, but could cause nasty problems at run time.

local and global arrays and segmentation fault

I'm having trouble with the following: I want to take a large number (cca. 15-digit) and turn it into individual digits and store them in an array. I will need these digits further on in the code. The problem is, if I declare the array outside the while loop, it stores the first four values, but then I get a segmentation fault. If I declare it within the loop, the code works as I want it to, but then I don't know how to move the array out of that loop, so that I could use it further. How can I solve this? This is what I've compiled:
unsigned long long card_num;
printf("Enter your credit card number:\n");
scanf("%llu", &card_num);
int count = 0;
while (card_num != 0)
{
int digits[count]; //declaring array into which digits will be stored
digits[count] = card_num%10; // get last digit, store it in array
card_num = card_num/10; //remove last digit
printf("Digit[%i] = %i\n", count, digits[count]);
printf("Number of digits: %i\n", count);
count ++;
}
In your code, for the very first iteration
int digits[count];
count is 0, which violates the constraints mentioned in spec. As per C11, chapter 6.7.5.2,
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. [....]
and
If the size is an expression that is not an integer constant expression: if it occurs in a declaration at function prototype scope, it is treated as if it were replaced by *; otherwise, each time it is evaluated it shall have a value greater than zero
So, this is not a valid code.
As already mentioned, what you are doing is plain wrong.
There is several ways to solve this issue. The easiest would be to allocate an array at the beginning of your program with enough space for all your usecases with something like :
#define MAX_DIGIT 50
int digits[MAX_DIGIT];
Then you just have to check you are not going over this array by checking that count < MAX_DIGIT.
Another way would be using dynamic memory allocation using an int pointer int *digits and malloc (I let you google that) once you know the size of the array you'll need. You'll have to change a bit your code to know the number of digits before starting to get the digits as you need to allocate the memory before starting to store digits.
You could use realloc to keep a code similar to what you already have, but I wouldn't advise it as it is not efficient to realloc memory for each value that you add.
Your logic is fine.
What went wrong is that you tried to increase the length of a fixed-length array while iterating which is not allowed.
You should never change the length of a fixed-length array anywhere in the program.
However if you want to change the length of an array during runtime you must use the malloc and realloc functions to do so.
Check out this example:
//declarations
int *storeNum;
storeNum = (int *)malloc(1 * sizeof(int));
//logic
while(num != 0) {
if(i > 0)
storeNum = realloc(storeNum, (i+1) * sizeof(int));
storeNum[i] = num % 10;
num = num/10;
++i;
}
Here first I declared the array size initially as one and later incremented it using realloc function.
You also have the array size stored in i which you can use later in your code in loops.
But keep in mind that the digits will be stored in your array in reverse order.
Also, you shouldn't declare an array within a loop.
Since you have "declared" the array, each time the compiler enters the loop while iterating it will consider the array-declaration as a new array. That is all.

Code to change an array element changes a different variable

I'm quite puzzled by why my variable NumberOfArrays changes the second time through the for loop in my code. Can anyone help me out?
#include <stdio.h>
#include <cs50.h>
int main(int argc, string argv[])
{
//variable declarations
int NumberOfArrays = 0;
int arrayRack[0];
//Get number of arrays
printf("Key in the number of arrays you'd like to have\n");
NumberOfArrays = GetInt();
//Get number for each element in arrayRack[]
for(int i = 0; i < NumberOfArrays; i++)
{
printf("give me an int for the %i th array\n", i + 1);
arrayRack[i] = GetInt();
// *** on the second pass, my "NumberOfArrays" gets adjusted to my GetInt number here. Why?
}
//print out numbers stored in respective arrays
for(int j = 0; j < NumberOfArrays; j++)
{
printf("{%i}<-- number in %ith array\n", arrayRack[j], j + 1);
}
return 0;
}
Because you declared arrayRack as an empty array ([0]). Try int arrayRack[100]; or some other number, and make sure that NumberOfArrays is less than that number before you use it.
Explanation: (edit note that this may vary by compiler) your variables are most likely stored on the stack in nearby memory addresses. So arrayRack points somewhere close to NumberOfArrays in memory. C doesn't generally check if you've run off the end of an array, so accessing arrayRack[1] doesn't cause a compiler error in this situation. However, arrayRack[1] isn't part of your array, so accessing it actually accesses something else — in this situation, NumberOfArrays.
Edit gcc permits length-0 arrays but does not allocate space for them per this. However, length-0 arrays are prohibited by the C standard (e.g., see this, the answers to this, and this). Given the behaviour you've seen, it looks to me like the compiler is allocating one int's worth of space on the stack, pointing arrayRack to that space, and packing that space right next to NumberOfArrays. As a result, &(arrayRack[1]) == &NumberOfArrays. In any event, using variable-length arrays as suggested by #dasblinkenlight is a cleaner way to handle this situation.
In general, given int arrayRack[N];, you can only safely access arrayRack[0] through arrayRack[N-1].
You declared the array too early. Move the declaration to after the call of GetInt(), like this:
printf("Key in the number of arrays you'd like to have\n");
int NumberOfArrays = GetInt();
int arrayRack[NumberOfArrays];
Note: NumberOfArrays is not an ideal name for the variable, because it denotes the number of array elements, not the number of arrays; your code has only one array.

C ints and chars. Strange behavior

I am learning C language and I am facing a problem I don't seem to be able to resolve on my own.
I have a simple loop where I add up ascii values of all characters in each word.
char char_array[100];
int lexicographical_values[20];
int i, j = 0;
for( i = 0; i <strlen(char_array); i++) {
if(char_array[i] == ' ')
j++;
lexicographical_values[j] += (int)char_array[i];
}
Then, if I output the lexicographical_values array in a loop
printf("%d word is: %d \n", i, lexicographical_values[i]);
I get correct figures for each word (ex: dd = 200 and so on)
But if I actually look at each element's value in the array, I get big numbers that are far from being correct.
The question is, how do I get correct values and how does printf obtain the correct values?
Thanks
You have not initialized the lexicographical_values array. You can initialize it by doing:
int lexicographical_values[20] = {};
Every time you see big numbers in the output, check for uninitialized variables.
You're starting with uninitialized memory.
man memset
You have not initialized the char_array with anything, so most likely it has garbage (depends on compiler options and platforms) so, you do a strlen(char_array) and at this point we're not sure what we're going to get out of it. If you initialize it with 0s (like: char char_array[100] = {0}; then strlen will return 0 and you'll never enter the loop.
Maybe you're looking for sizeof() here?
Oh, yes, forgot to mention that you need to initialize the second array also as was already pointed out.

Resources