Sorting gives inconsistent results, due to loop bound - c

Program Design, our first homework assignment was to take 4 integer values, add the 2 highest together and subtract the lowest two and square that result. Finally, compare the 2 values together to see if they are equal or not.
For example, if you were to enter: 20 10 60 40
You'd get
60 + 40 = 100
and
20 - 10 = 10 --> 10^2 = 100
So, 100 == 100
I wrote my program and tested it for various values which all returned correct results. My professor told me my program failed for all 10 test inputs and he sent me the results he got. The results he got aren't the same as mine, and I don't know what's going on. I emailed him, and he told me one of my for loops has incorrect bounds. He's right, but I still get the right results, so...?
Here's the code, any help would be appreciated!
/*
// Author: Jesse W
// Assignment 1
// Desciption:
// This program inputs four integer numbers a, b, c and d and
// determines if the sum of the two largest numbers is the same
// as the squared difference of the two smallest numbers
*/
#include <stdio.h>
/* Complete the code for this program below */
int main()
{
int a, b, c, d, f, k, swap;
int array_size = 4;
int return_val;
int sum, difference, square;
int small_1, small_2, large_1, large_2;
int array[array_size];
//Gather input
//printf("Enter integer values for a, b, c and d.\n");
return_val = scanf("%d %d %d %d", &a, &b, &c, &d);
//Validate input
if (return_val != 4)
{
printf("INVALID INPUT\n");
}
else
{
//Assign values to array
array[0] = a;
array[1] = b;
array[2] = c;
array[3] = d;
//Sort array
for (k = 0 ; k < ( array_size - 1 ); k++)
{
for (f = 0 ; f < array_size ; f++)
{
if (array[f] > array[f+1]) /* For decreasing order use < */
{
swap = array[f];
array[f] = array[f+1];
array[f+1] = swap;
}
}
}
//Assign sorted values to new variables
small_1 = array[0];
small_2 = array[1];
large_1 = array[2];
large_2 = array[3];
//Compute math
sum = large_1 + large_2;
difference = small_1 - small_2;
square = difference * difference;
//Compute logic
if(sum == square)
{
printf("%d equals %d.\n", sum, square);
}
else
{
printf("%d does not equal %d.\n", sum, square);
}
return 0;
}
}

f ranges up to array_size - 1
for (f = 0 ; f < array_size ; f++)
but in that case you access array[ f + 1 ] which is array[ array_size ]
array[f] = array[f+1];
array[f+1] = swap;
This results in undefined behavior. Since the value one past the end is effectively sorted as part of the array, whether the program works or not depends whether the uninitialized value is larger than all the input values.

The problem is indeed the upper bound on your inner for loop; it's causing you to read past the end of your array, which causes undefined behaviour.
It's entirely possible that the resulting program still prints the correct results on your machine, but there is no guarantee that it will work on anyone else's. Hence undefined.

Your inner loop will end up accessing array[4], which triggers undefined behavior. As soon as you trigger undefined behavior, you can't guarantee anything about the program after that point.
What's likely actually happening, though, is that on your computer, array[4] just happens to be larger than array[3] and you keep those in the same order. On your professor's computer, you swap them (probably corrupting some other variable), making array[3] be that undefined value.

Since your program's output depends totally on the value of array[4], where array is an array of length 4, its behavior is completely unpredictable: there's no way, from the source, to guess what value will happen to be in memory at location array + 4.
(In fact, it's even worse than that — your program invokes undefined behavior, which means that it's allowed to do absolutely anything at all, up to including sending your professor a vulgar and insulting e-mail that looks like it's from you. But in practice, it's likely to print one of its expected outputs, there's just really no way to guess which one.)

Change your sort loop to this
for (k = 0 ; k < array_size ; k++)
{
for (f = 0 ; f < (array_size -1) ; f++)
{
if (array[f] > array[f+1]) /* For decreasing order use < */
{
swap = array[f];
array[f] = array[f+1];
array[f+1] = swap;
}
}
}

Related

the largest palindrome made from the product of two 3-digit numbers. using c .whats wrong in my code?

Program not working, not giving output, I don't know what to do, where the problem is.
I'm trying to find out the largest palindrome made from the product of two 3-digit numbers.
#include <stdio.h>
main() {
int i, k, j, x;
long int a[1000000], palindrome[1000000], great, sum = 0;
// for multiples of two 3 digit numbers
for (k = 0, i = 100; i < 1000; i++) {
for (j = 100; j < 1000; j++) {
a[k] = i * j; // multiples output
k++;
}
}
for (i = 0, x = 0; i < 1000000; i++) {
// for reverse considered as sum
for (; a[i] != 0;) {
sum = sum * 10 + a[i] % 10;
}
// for numbers which are palindromes
if (sum == a[i]) {
palindrome[x] = a[i];
x++;
break;
}
}
// comparison of palindrome number for which one is greatest
great = palindrome[0];
for (k = 0; k < 1000000; k++) {
if (great < palindrome[k]) {
great = palindrome[k];
}
}
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
}
What do you mean with "not working"?
There are two things, from my point of view:
1) long int a[1000000], palindrome[1000000]
Depending on you compile configuration you could have problems compiling your code.
Probably the array is too big to fit in your program's stack address space.
In C or C++ local objects are usually allocated on the stack. Don't allocate it local on stack, use some other place instead. This can be achieved by either making the object global or allocating it on the global heap.
#include <stdio.h>
long int a[1000000], palindrome[1000000], great, sum = 0;
main() {
int i, k, j, x;
2) printf("\ngreatest palindrome of 3 digit multiple is : ", great);
I will change it by :
printf("\ngreatest palindrome of 3 digit multiple is %li: ", great);
Regards.
Compiling and running your code on an on-line compiler I got this:
prog.c:3:1: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
main() {
^
prog.c:34:61: warning: data argument not used by format string [-Wformat-extra-args]
printf("\ngreatest palindrome of 3 digit multiple is : ", great);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
2 warnings generated.
Killed
Both the warnings should be taken into account, but I'd like to point out the last line. The program was taking too much time to run, so the process was killed.
It's a strong suggestion to change the algorithm, or at least to fix the part that checks if a number is a palindrome:
for (; a[i] != 0;) { // <-- If a[i] is not 0, this will never end
sum = sum * 10 + a[i] % 10;
}
I'd use a function like this one
bool is_palindrome(long x)
{
long rev = 0;
for (long i = x; i; i /= 10)
{
rev *= 10;
rev += i % 10;
}
return x == rev;
}
Also, we don't need any array, we could just calculate all the possible products between two 3-digits number using two nested for loops and check if those are palindromes.
Starting from the highest numbers, we can store the product, but only if it's a palindrome and is bigger than any previously one found, and stop the iteration of the inner loop as soon as the candidate become less then the stored maximum. This would save us a lot of iterations.
Implementing this algorithm, I found out a maximum value of 906609.

Subtracting arbitrary large integers in C

Question:
I want to know the difference of number n and a, both stored in char
arrays in ALI structures. Basically, what I'm doing is initialising
two integers (temp_n and temp_a) with the current digits of n and a,
subtracting them and placing the result in a new ALI instance named
k. If the j-th digits of a is greater than the i-th digit of n, then
I add 10 to the digit if n, finish the subtraction, and in the next
turn, I increase temp_a by one. The value of number a certainly falls
between 1 and n - 1 (that's given). If a is shorter than n, as soon
as I reach the last digits of a, I put the remaining digits of n to
the result array k. And I do this all backwards, so the initialising
value of i would be the size of n -1.
Example:
I store a number in a structure like this:
typedef struct Arbitrary_Large_Integer
{
char digits[];
} ALI;
Requirements:
I know that it could be easier to use char arrays instead of a
structure with a single member which barely makes sense, but I'm
forced to put structures in my code this time (that's a requirement
for my assignment).
Code:
ALI *subtraction(ALI n, ALI a, int nLength, int aLength)
{
ALI *result;
result = (ALI*)malloc(nLength * sizeof(ALI));
if (result == NULL)
printf("ERROR");
int temp_n, temp_a, difference;
int i = nLength - 1; //iterator for number 'n'
int j = aLength - 1; //iterator for number 'a'
int k = 0; //iterator for number 'k', n - a = k
bool carry = false; //to decide whether a carry is needed or not the turn
for (i; i >= 0; i--)
{
//subtracting 48 from n.digits[i], so temp_n gets the actual number
//and not its ASCII code when the value is passed
temp_n = n.digits[i] - ASCIICONVERT;
temp_a = a.digits[j] - ASCIICONVERT;
//Performing subtraction the same way as it's used on paper
if (carry) //if there is carry, a needs to be increased by one
{
temp_a++;
carry = false;
}
if (temp_n >= temp_a)
{
difference = temp_n - temp_a;
}
//I wrote else if instead of else so I can clearly see the condition
else if (temp_a > temp_n)
{
temp_n += 10;
difference = temp_n - temp_a;
carry = true;
}
//placing the difference in array k, but first converting it back to ASCII
result->digits[k] = difference + ASCIICONVERT;
k++;
//n is certainly longer than a, so after every subtraction is performed on a's digits,
//I place the remaining digits of n in k
if (j == 0)
{
for (int l = i - 1; l >= 0; l--)
{
result->digits[k] = n.digits[l];
k++;
}
//don't forget to close the array
result->digits[k] = '\0';
break;
}
j--;
}
//reverse the result array
_strrev(result->digits);
return result;
}
Output/Error:
Output results
It seems like when the array is passed to the function, its value
changes for some reason. I can't figure out what's wrong with it.
Problems:
Non-standard C
The typedef is not a valid standard C structure. The Flexible Array Member(FAM) .digits must be accompanied by at least one more prior named member in addition to the flexible array member. Recommend to put .nLength as the first member.
// Not standard
typedef struct Arbitrary_Large_Integer {
char digits[];
} ALI;
malloc(0)??
Since code is using a non-standard C, watch out that nLength * sizeof(ALI) may be the same as nLength * 0.
No room for the null character
Code is attempting to use .digits as a string with _strrev(), themallloc() is too small by 1, at least.
Other problems may exist
A Minimal, Complete, and Verifiable example is useful for additional fixes/solutions

Project Euler Palindrome #4 with C

I found few posts regarding this problem using C. Most of the elements in my code work on their own but the iteration at the beginning is causing problems for some reason. First, I'm getting an "exited with non-zero status" error message. When I run the program with a smaller range for a and b, I don't get that message. I'm guessing there's a problem with the rev_array and for_array variables I created. I'm sure I'm doing something really dumb right here so I apologize in advance for that.
But when I use a smaller range for a and b (like 10 to 25), the program is still showing that all two-digit numbers (even 11, 22, 33, 44) are not the same forward and backward. I used printf to check for this.
I made a similar program that used fixed values for a and b instead of iterating over a range of values and it worked fine. But I couldn't figure out why this one isn't working.
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
int max;
int a;
int b;
int prod;
int m = 0;
int rev_array[10000];
int for_array[10000];
int c;
int d;
int same = 0;
int main(void)
{
// iterate over all 3 digit numbers in lines 19-21
for(a = 10; a <= 25; a++)
{
for(b = 10; b <= 25; b++)
{
max = 0;
prod = a * b;
/* thanks to Zach Scrivena for the following formula converting an integer to an array of integers posted on stackoverflow on February 5, 2009 under the subject "convert an integer number into an array"
*/
int n = prod;
while(n != 0)
{
rev_array[m] = n % 10;
n /= 10;
m++;
}
/* thanks to Jordan Lewis for the following int length formula posted to stackoverflow on June 18, 2010 in response to "Finding the length of an integer in C"
*/
int length = floor(log10(abs(prod))) + 1;
// create the forward array of the ints in prod
for(c = length - 1, d = 0; c >= 0; c--, d++)
{
for_array[d] = rev_array[c];
}
// compare the forward and reverse arrays to see if they match exactly
for(int e = 0; e < length; e++)
{
if(for_array[e] != rev_array[e])
{
// if they don't match then set same equal to 1 for following step
same = 1;
}
}
/* if prod is greater than max and the forward and reverse arrays are identical, then replace max with prod
*/
if(prod > max && same == 0)
{
max = prod;
}
// reset same and repeat the process
same = 0;
}
}
// print the final, greatest number that fits the preceding criteria
printf("new max: %i \n", max);
return 0;
}
Answers provided in comments:
You need to reset m to zero each time. – Johnny Mopp
You also don't need to calculate length, since m should contain the length after the while loop (but you need to reset it to 0 at the top). And all these variables should be local, and most of them (like m, n, prod) should be defined inside the inner loop, with a limited scope. max is the only one which needs to be preserved between iterations. – Groo

C Program compiles, but fails at runtime (too big of an array?). And 'checklist' suggestions?

I'm writing a program to look for the longest Collatz sequence starting under 1,000,000.
I was really proud of this code, it seemed so efficient and clean and well written... until I tried to run it. After a little debugging to get it to compile, I found that when I run the program, it crashes.
I have used both
int array[1000000];
and
int *array;
array = (int*)calloc(s, sizeof(int));
(where s=1000000)
to declare an array of 1,000,000 spaces.
So part A) of my question: Is it ridiculous or possible to declare an array of that size?
and part B) of my question: This is used for a 'checklist' of sorts, checking which numbers have already been seen. Is there a simpler or better or just different method of 'checking off' numbers that I should be using instead?
the code is as follows:
// This is a program to find the longest Collatz sequence starting under 1,000,000
#include <stdio.h>
#include <stdlib.h>
int main()
{
// Collatz sequence: IF EVEN n/2 :: IF ODD 3n+1
//define ints
int i;
int n;
int c; // counter of sequence length
int longestsequence = 0;
int beststart;
int s = 1000000; //size of array
//define int array
//int array[999999];
//define array using calloc
//define pointer for calloc int array
int *array;
// do your calloc thing
array = (int*)calloc(s, sizeof(int)); // allocates 1,000,000 spots (s) of size "int" to array "array"
//fill array
for(i = 0; i < 1000000; i++)
{
array[i] = i;
}
for(i = 999999; i > 500000; i--)
{
if(array[i] == 0) // skip if number has already been seen
goto done;
n = i;
c = 0;
//TEST
printf("Current starting number is: %d\n", i);
//TEST
while(n != 4) // run and count collatz sequence
{
//TEST
//printf("test1\n");
//TEST
if(n % 2 == 0) // EVEN
n = n/2;
else // ODD
n = 3 * n + 1;
//TEST
//printf("test2\n");
//TEST
c++;
//TEST
//printf("test3\n");
//TEST
if(n < 1000000 && array[n] != 0) // makes note of used numbers under 1000000
array[n] = 0;
//TEST
//printf("test4\n");
//TEST
}
if(longestsequence < c)
{
longestsequence = c;
beststart = i;
//TEST
printf("Current best start is: %d\n", beststart);
//TEST
}
done:
}
printf("the starting number that produces the longest Collatz sequence is...\n");
printf("%d\n", beststart);
getchar();
return 0;
}
Thanks for any and all help and suggestions! Links to helpful sources are always appreciated.
UPDATE!
1.My code now looks like this^^^^
and
2.The program runs, and then mysteriously stops at i value 999167
for(i = 999999; i > 4; i++)
You easily go beyond array boundary here. I guess what you meant was
for(i = 999999; i > 4; --i)
// ^^^
Also, as in your implementation, 1 million element is not enough.
Take n == 999999 as example. In the 1st step, you compute 3 * n + 1, which is obviously way larger than 1000000. A simple solution would be change
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
into
if(n < s && array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
which just disables result lookup when n is over array boundary.
You could use a simple linked list of numbers, which will reduce the memory requirements at the expense of "long" search times. I've always noticed a bit of repetition:
1
2 → 1 (already seen in 1, so link to the existing 1)
3 → 5 → 16 → 8 → 4 → 2 (already seen in 2, so link to the existing 2)
4 (link to existing after 8)
5 (link to existing after 5)
etc.
You would have a number A and possibly one more number B link to a number N for some numbers, but N would only link to one number C. For example:
A -> N -> C
3 -> 10 -> 5
20 -> 10 -> 5
B -> N -> C
Of course, you could optimize it by storing a length of the list and an extra pointer containing the next adjacent number, allowing you to implement a binary search using that length as a guide.
However, if you're only looking for the longest sequence length instead of the sequence itself, why aren't you merely storing the longest length found and comparing it to the length of the current sequence? Storing the numbers only for calculating the length seems like overkill. Something like the following pseudocode:
Longest := 0
For N = 1 To 1000000
Length := 1
X := N
While X != 1
Length := Length + 1
If IsEven(X) Then
X := 3 * X + 1
Else
X := X / 2
End If
End While
If Length > Longest Then
Longest := Length
End If
End For
Print("Longest sequence less than 1000000 is: ", Longest)
The line
n = 3 * n + 1;
ends up setting the value of n to be higher than the valid index. The highest valid index is 999999. You have to make sure that n is less than or equal to 1000000 before you access the array in:
if(array[n-1] != 0) // makes note of used numbers
array[n-1] = 0;
You don't check the array index [n-1] within the while loop to ensure it doesn't exceed the array bounds of 1,000,000. For example, in your first loop i = 999,999 which makes `n = 999999*3+1 = 2,999,998'.
Solution is to make sure n doesn't exceed your array size.

function to perform bubble sort in C providing unstable results

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.

Resources