When attempting this (code below), the console doesn't even request an input value, then spits out a random number (likely from a number previously stored at the location).
Why does this not work and how can i fix it?
int main( ) {
int arr[3];
for(int i = sizeof(arr); i <= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
}
There are two things that are wrong.
Assuming you want the number of elements in the array, it is done, using:
size_t len = sizeof(arr) / sizeof(*arr)
sizeof gives the actual size (number of bytes allocated for arr.
You should start with len - 1 and not len.
NOTE: Array indexing is 0 based not 1 based, so the array elements are indexed from 0 to 2 But you would have tried to access arr[3], which can result in undefined behaviour.
You wrote i <= 0. So, i starts from let's say 2, is 2 <= 0 ? NO!
Hence it will never go inside the loop. The correct condition is i >= 0
int len = sizeof(arr) / sizeof(*arr);
for(int i = len - 1; i >= 0; i--)
Well, I don't know why you are taking reverse order input, but a general convention is to take input using:
size_t len = sizeof(arr)/sizeof(*arr);
for (i = 0; i < len; i++)
{
// take input
}
EDIT:
From other comments it seems that you don't understand the for loop.
Have a look in this answer
Please comment for any further clarification.
i <= 0
the code can never enter the loop since the initial value of i is greater than zero.
It is important to note that in C, other than languages like Java/Python, you must explicitly know the length of the array, sizeof will NOT give you the amount of items in the array.
int main() {
int arr[3];
int itemsInArray = 3;
for(int i = itemsInArray-1; i >= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
};
Since i-- will decrease the value of i , and the condition for loop is i <=0 to start the loop the i must be 0 or negative.Since arr[3] will return 12(3 elements and each has 4 bytes(int has 4 bytes)), the value will be posivite,greater than 0 so we need to change the loop condition to check if i is positive
#include <stdio.h>
int main( ) {
int arr[3]={0};
int i = sizeof(arr)/sizeof(arr[0]) -1;
for(; i >= 0; i--) {
scanf("%d", &arr[i]);
}
printf("%d", arr[2]);
return 0;
}
There are a couple of issues with your code: first of all, sizeof(arr) won't return "3" as you probably thought; "arr" is a pointer to arr[0], so you are requesting the size of an int pointer.
Secondly, i <= 0 prevent the loop to even be executed.
Finally, please set array to zero while declarating, as best practice, ie:
int arr[3] = {0};
EDIT: i wrong-spelled my thoughts: you are requesting the size of the whole memory area allocated for the array.
Comments below are corrected though.
Related
I just started learning how to code in C.
I tried creating a program that finds the maximum of three integers using arrays, but I don't really understand why does it work.
Can anybody more experienced help explain to me; why do I need to let max = 0 in order for the program to function?
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
int main()
{
int size, max;
int arr[3];
for (int i = 0; i < 3; i++) {
printf("Please enter your integer:\n");
scanf("%d", &arr[i]);
}
max = 0;
for (int i = 0; arr[i] >= max; i++) {
max = arr[i];
}
printf("This is the max number: %d", max);
return 0;
}
Thanks for the help everyone.
The proper loop would be:
int max= INT_MIN;
for (int i = 0; i<3; i++)
if (arr[i]> max) max= arr[i];
First of all, your code won't find the right answer in all test cases, and that's because of how you wrote your second for loop. For example if you have an input like 3, 2, 4, after the first for iteration you'll have max = 3 and the for loop will stop because the next element (2) is less than the current max (3). But the max value of this array is 4, not 3. You should change the second for loop like this:
for (int i=0;i<3;i++) {
(if array[i]>max) max = array[i];
}
Also, take note that you can initialize max to 0 only if you don't have negative numbers in the array, otherwise you might have incorrect results. So, if you can't make assumptions about your input values I would suggest you to simply initialize max with the first element of the array and do a loop starting from the second one to the end (for(i=1;i<3;i++).
A variable must be initialized before it can be used. The first use of max is:
for (int i = 0; arr[i] >= max; i++) {
... ^^^^^^^^^^^^^
}
The boundary condition in a for loop (i.e. arr[i] >= max) is evaluated before every iteration of the loop. A value for max is therefore required before the body of the loop is ever executed.
Thus, you must assign some value to max outside the loop, and, as you discovered, max = 0 is a suitable initial value for some inputs.
However as mentioned by Paul in the comments, this is not a suitable boundary condition for the result you’re trying to achieve. You should instead iterate over the entire array, setting the max value only if each array element is greater than the existing max value:
max = 0;
for (int i = 0; i < 3; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
If it's just for three:
#define MAX_SIMPLE(a, b) (((a) > (b)) ?(a) :(b))
int a[3] = {3, 2, 1};
printf("max is: %d\n", MAX_SIMPLE(a[0], MAX_SIMPLE(a[1], a[2])));
EDIT:
I forgot to mention that I do not want to allocate another temporarily array.
I am trying to solve a problem in C, which is:
Suppose you were given an array a and it's size N. You know that all of the elements in the array are between 0 to n-1. The function is supposed to return 0 if there is a missing number in the range (0 to n-1). Otherwise, it returns 1. As you can understand, duplicates are possible. The thing is that its supposed to run on O(n) runtime.
I think I managed to do it but i'm not sure. From looking at older posts here, it seems almost impossible and the algorithm seems much more complicated then the algorithm I have. Therefore, something feels wrong to me.
I could not find an input that returns the wrong output yet thou.
In any case, I'd appreciate your feedback- or if you can think of an input that this might not work for. Here's the code:
int missingVal(int* a, int size)
{
int i, zero = 0;
for (i = 0; i < size; i++)
//We multiply the element of corresponding index by -1
a[abs(a[i])] *= -1;
for (i = 0; i < size; i++)
{
//If the element inside the corresponding index is positive it means it never got multiplied by -1
//hence doesn't exist in the array
if (a[i] > 0)
return 0;
//to handle the cases for zeros, we will count them
if (a[i] == 0)
zero++;
}
if (zero != 1)
return 0;
return 1;
}
Just copy the values to another array placing each value in its ordinal position. Then walk the copy to see if anything is missing.
your program works and it is in O(N), but it is quite complicated and worst it modify the initial array
can be just that :
int check(int* a, int size)
{
int * b = calloc(size, sizeof(int));
int i;
for (i = 0; i != size; ++i) {
b[a[i]] = 1;
}
for (i = 0; i != size; ++i) {
if (b[i] == 0) {
free(b);
return 0;
}
}
free(b);
return 1;
}
This problem is the same as finding out if your array has duplicates. Here's why
All the numbers in the array are between 0 and n-1
The array has a size of n
If there's a missing number in that range, that can only mean that another number took its place. Which means that the array must have a duplicate number
An algorithm in O(n) time & O(1) space
Iterate through your array
If the sign of the current number is positive, then make it negative
If you found a negative this means that you have a duplicate. Since all items are originally greater (or equal) than 0
Implementation
int missingVal(int arr[], int size)
{
// Increment all the numbers to avoid an array with only 0s
for (int i = 0; i < size; i++) arr[i]++;
for (int i = 0; i < size; i++)
{
if (arr[abs(arr[i])] >= 0)
arr[abs(arr[i])] = -arr[abs(arr[i])];
else
return 0;
}
return 1;
}
Edit
As Bruno mentioned if we have an array with all zeros, we could have run into a problem. This is why I included in this edit an incrementation of all the numbers.
While this add another "pass" into the algorithm, the solution is still in O(n) time & O(1) space
Edit #2
Another great suggestion from Bruno which optimizes this, is to look if there's more than one zero instead of incrementing the array.
If there's 2 or more, we can directly return 0 since we have found a duplicate (and by the same token that not all the numbers in the range are in the array)
To overcome the requirement that excludes any extra memory consumption, the posted algorithm changes the values inside the array by simply negating their value, but that would leave index 0 unchanged.
I propose a different mapping: from [0, size) to (-1 - size, -1], so that e.g. {0, 1, 2, 3, 4, ...} becomes {-1, -2, -3, -4, -5, ...}. Note that, for a two's complement representation of integers, INT_MIN = -INT_MAX - 1.
// The following assumes that every value inside the array is in [0, size-1)
int missingVal(int* a, int size) // OT: I find the name misleading
{
int i = 0;
for (; i < size; i++)
{
int *pos = a[i] < 0
? a + (-a[i] - 1) // A value can already have been changed...
: a + a[i];
if ( *pos < 0 ) // but if the pointed one is negative, there's a duplicate
break;
*pos = -1 - *pos;
}
return i == size; // Returns 1 if there are no duplicates
}
If needed, the original values could be restored, before returning, with a simple loop
if ( i != size ) {
for (int j = 0; j < size; ++j) {
if ( a[j] < 0 )
a[j] = -a[j] - 1;
}
} else { // I already know that ALL the values are changed
for (int j = 0; j < size; ++j)
a[j] = -a[j] - 1;
}
I have got an assignment and i'll be glad if you can help me with one question
in this assignment, i have a question that goes like this:
write a function that receives an array and it's length.
the purpose of the function is to check if the array has all numbers from 0 to length-1, if it does the function will return 1 or 0 otherwise.The function can go through the array only one.
you cant sort the array or use a counting array in the function
i wrote the function that calculate the sum and the product of the array's values and indexes
int All_Num_Check(int *arr, int n)
{
int i, index_sum = 0, arr_sum = 0, index_multi = 1, arr_multi = 1;
for (i = 0; i < n; i++)
{
if (i != 0)
index_multi *= i;
if (arr[i] != 0)
arr_multi *= arr[i];
index_sum += i;
arr_sum += arr[i];
}
if ((index_sum == arr_sum) && (index_multi == arr_multi))
return 1;
return 0;
}
i.e: length = 5, arr={0,3,4,2,1} - that's a proper array
length = 5 , arr={0,3,3,4,2} - that's not proper array
unfortunately, this function doesnt work properly in all different cases of number variations.
i.e: length = 5 , {1,2,2,2,3}
thank you your help.
Checking the sum and product is not enough, as your counter-example demonstrates.
A simple solution would be to just sort the array and then check that at every position i, a[i] == i.
Edit: The original question was edited such that sorting is also prohibited. Assuming all the numbers are positive, the following solution "marks" numbers in the required range by negating the corresponding index.
If any array cell already contains a marked number, it means we have a duplicate.
int All_Num_Check(int *arr, int n) {
int i, j;
for (i = 0; i < n; i++) {
j = abs(arr[i]);
if ((j >= n) || (arr[j] < 0)) return 0;
arr[j] = -arr[j];
}
return 1;
}
I thought for a while, and then i realized that it is a highly contrained problem.
Things that are not allowed:
Use of counting array.
Use of sorting.
Use of more than one pass to the original array.
Hence, i came up with this approach of using XOR operation to determine the results.
a ^ a = 0
a^b^c = a^c^b.
Try this:
int main(int argc, char const *argv[])
{
int arr[5], i, n , temp = 0;
for(i=0;i<n; i++){
if( i == 0){
temp = arr[i]^i;
}
else{
temp = temp^(i^arr[i]);
}
}
if(temp == 0){
return 1;
}
else{
return 0;
}
}
To satisfy the condition mentioned in the problem, every number has to occour excatly once.
Now, as the number lies in the range [0,.. n-1], the looping variable will also have the same possible range.
Variable temp , is originally set to 0.
Now, if all the numbers appear in this way, then each number will appear excatly twice.
And XORing the same number twice results in 0.
So, if in the end, when the whole array is traversed and a zero is obtained, this means that the array contains all the numbers excatly once.
Otherwise, multiple copies of a number is present, hence, this won't evaluate to 0.
I created a matrix of ints for example have {1 , 2 , 3 , 4 , 5}
and then I'm trying to store the sum of the matrix into a long variable:
#include<stdio.h>
#define m 5
int main (){
int i;
int matrix[m];
long matrix_sum;
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
for(i = 0; i < m ; i++) //adding ints to long
matrix_sum += matrix[i];
printf("%lo \n",matrix_sum);
return 0;
}
when I run this code I have "17" on output instead of "15" !!
Think about what happens on the first iteration of this loop:
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
Notice that you'll be reading from index -1 of this array (oops!) This leads to undefined behavior, which means that in principle anything can happen. Your program could get garbage data, get the wrong answer, or even outright crash!
It's up to you to decide how to avoid this case. Consider changing the loop indices so that you start at a higher index.
Also, look at the remaining variables in main. Are they initialized? If not, adding values to them will again result in undefined behavior and pretty much anything can happen to them.
Finally, look at how you're printfing things:
printf("%lo \n",matrix_sum);
The %lo specifier means "the argument is a long, and it should be printed in octal (base-8)." This means that you're not printing the value in decimal, so even if you'd expect to get the value 15dec, you'd instead see 17, the octal representation of the number.
I have not seen a matrix. It seems you mean an array or a vector.
For starters according to the C Standard the function main without parameters shall be declared like
int main( void )
The variable matrix_sum was not initialized.
In this loop
for(i = 0; i < m ; i++) //filling the matrix
matrix[i] = matrix[i-1]+1;
^^^^
there is an attempt to access memory beyond the array when the variable i is equal to 0.
And it looks like you wanted to use the conversion specifier %ld in this statement
printf("%lo \n",matrix_sum);
^^^
Otherwise the output will be as an octal number.
I think you mean the following. At least the program output is exactly equal to 15.:)
#include <stdio.h>
#define N 5
int main(void)
{
int a[N];
int i;
long sum;
for ( i = 0; i < N ; i++ ) a[i] = i + 1;
sum = 0;
for ( i = 0; i < N ; i++ ) sum += a[i];
printf( "%ld\n", sum );
return 0;
}
I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.