Negative numbers are printed - c

This is a program on sorting integers.
#include <stdio.h>
int main(void) {
int n, i, j, k;
int nmbr[100];
printf("\n How many numbers ? ");
scanf("%d", &n);
printf("\n");
for (i = 0; i < n; ++i) {
printf(" Number %d : ", i + 1);
scanf("%d", &nmbr[i]);
}
for (i = 0; i < n; ++i) {
for (j = 0; j < n; ++j) {
if (nmbr[j] > nmbr[j + 1]) {
k = nmbr[j];
nmbr[j] = nmbr[j + 1];
nmbr[j + 1] = k;
}
}
}
printf("\n Numbers after sorting : \n");
for (i = 0; i < n; ++i) {
printf (" %d", nmbr[i]);
}
return 0;
}
It works fine, but when I enter some number that contains more than 2 digits, the first number that is printed is negative and really big. I don't also get the last integer too. I enter N as 4, then the numbers I entered were 25, 762, 588, and 34. The result I get is:
-1217260830 25 34 588
What seems to be the problem?

You are running the loop as for (j = 0; j < n; ++j) which means j will have values from 0 to n-1 which are valid array indices (or array elements with relevant values).
But, inside that loop you are accessing an element beyond the last. For instance, in
if (nmbr[j] > nmbr[j + 1])
you are accessing nmbr[j + 1]. If the current value of j in n-1, then you are accessing nmbr[n-1 + 1] i.e. nmbr[n] which will be a value outside the array and may contain a garbage value (which might as well be negative!).
If you are trying something like Bubblesort, you might want to run the inner loop like for (j = 0; j < n - 1; ++j).

There are multiple problems in your code:
You do not check the return values of scanf(). If any of these input operations fail, the destination values remain uninitialized, invoking undefined behavior and potentially producing garbage output.
You do not verify that the number of values provided by the user is at most 100. The reading loop will cause a buffer overflow if n is too large.
Your sorting logic is flawed: in the nested loop, you refer to nmbr[j + 1] which is beyond the values read from the user. This invokes undefined behavior: potentially causing a garbage value to appear in the output.
Here is a corrected version:
#include <stdio.h>
int main(void) {
int n, i, j, k;
int nmbr[100];
printf("\n How many numbers ? ");
if (scanf("%d", &n) != 1 || n > 100) {
printf("input error\n");
return 1;
}
printf("\n");
for (i = 0; i < n; ++i) {
printf(" Number %d : ", i + 1);
if (scanf("%d", &nmbr[i]) != 1) {{
printf("input error\n");
return 1;
}
}
for (i = 0; i < n; ++i) {
for (j = 0; j < n - 1; ++j) {
if (nmbr[j] > nmbr[j + 1]) {
k = nmbr[j];
nmbr[j] = nmbr[j + 1];
nmbr[j + 1] = k;
}
}
}
printf("\n Numbers after sorting :\n");
for (i = 0; i < n; ++i) {
printf (" %d", nmbr[i]);
}
printf("\n");
return 0;
}

Your Sorting Logic is wrong. It should be:
for (i = 0; i < n; ++i){
for (j = 0; j < (n-1); ++j){
if (nmbr[j] > nmbr[j + 1]){
k = nmbr[j];
nmbr[j] = nmbr[j + 1];
nmbr[j + 1] = k;
}
}
You are trying to access out of bounds of array, when you iterate in your second loop using j. This is causing the garbage value.
As per your example involving 4 elements, when you try to access j+1, it will try to access nmbr[3+1] in the last iteration of second loop which leads to out of bounds access.

Problem is with the sorting logic as suggested by fellow coders. But It is always good coding habit to initialize the variables. Also use the qualifier if are dealing with positive numbers only.
unsigned int n = 0 , i = 0, j = 0, k = 0;
unsigned int nmbr[100] = {0};
If you would have initialized them, out put of your program would be following, which might help you tracing the problem by yourself.
0 25 34 588

Related

How to stop the loop after printing one?

So here is the problem: Write a program that accept an integer n, print out the largest number but smaller or equal n that is the product of two consecutive even number. Example: Input: 12, Output: 8 ( 2x4 )
Here is my code :
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int i = n; i >= 0; i--)
{
for (int j = 0; j <= n; j = j + 2)
{
if ( i == j * (j+2) )
{
printf("%d ", i);
break;
}
}
}
return 0;
}
So if i input 20, it will print out 8 and 0 instead of 8, if i input 30, it will print out 24,8 and 0 instead of just 24. How do i make it stop after printing out the first number that appropriate ?
You need to stop an outer loop from processing, for example by using a boolean flag (meaning "solution found, we finish work") or a goto statement.
#include <stdio.h>
int main() {
int n;
scanf("%d", &n);
int solutionFound = 0;
for (int i = n; i >= 0; i--) {
// this could also be put into for's condition i.e. "i >= 0 && !solutionFound"
if (solutionFound) {
break;
}
for (int j = 0; j <= n; j = j + 2) {
if ( i == j * (j+2) ) {
printf("%d ", i);
solutionFound = 1;
break;
}
}
}
return 0;
}
EDIT: immediate return as noted in the comments is also a nice idea, if you don't need to do anything later.
Your problem is that you are nested - in a for loop which is inside another for loop - when you want to stop processing.
Some languages would let you code break 2; to indicate that you want to break out of 2 loops. Alas, C i snot such a language.
I would recommend that you code a function. That would serve a few porpoises: 1) your main should be "lean & mean" 2) as your programs get larger, you will learn the benefits of putting individual coding tasks into functions 3) you can use return; instead of break; and it will exit the function immediately.
Something like this:
#include <stdio.h>
void FindNeighbouringDivisors(int n)
{
for (int i = n; i >= 0; i--)
{
for (int j = 0; j <= n; j = j + 2)
{
if ( i == j * (j+2) )
{
printf("%d times %d = %d", j, j + 2, i);
return;
}
}
}
printf("There are no two adjacent even numbers which can be multiplied to give %d", n);
}
int main()
{
int n;
scanf("%d", &n); /* could get from comamnd line */
FindNeighbouringDivisors(n);
return 0; /* should be EXIT_SUCCESS */
}
Btw, when you have a problem with your code, ask a question here. When you have it working, consider posting it at our code review site where more experienced programmers can give you advice on how to improve it. It's a great way to learn
Break only breaks you out of immediate loop, so either use flags or just use return to terminate the execution. Or you can even use following code:
#include <stdio.h>
int main()
{
int n;
scanf("%d", &n);
for (int j = 0; j <= n; j = j + 2)
{
if ( n < j * (j+2) )
{
printf("%d ", j*(j-2));
break;
}
}
return 0;
}

Checking monotonic sequences - C programming

I am doing a problem about checking monotonic sequences. The problem is inputting a sequence and then print "YES" if it is monotonic, "NO" if it is not.
This is my code:
#include <stdio.h>
int main()
{
//Inputting the sequence
int n;
scanf("%d", &n);
int a[n];
for (int i = 1; i <= n; i++)
{
scanf("%d ", &a[i]);
}
//Checking monotonic sequence
for (int i = 1; i <= n; i++)
{
if ((a[i] > a[i-1]) && (a[i] > a[i+1]))
{
printf("NO");
return;
}
else if ((a[i] < a[i-1]) && (a[i] < a[i+1]))
{
printf("NO");
return;
}
}
printf("YES");
return 0;
}
I have failed 2 test case with sequences [1, 2, 3] and [10, 6, 4, 2, 1, -100]; and passed one test case with [1, 2, 3, 3, 2, 1]. Can anyone please point out the problem in my code? I would truly appreciate that. Thank you.
Remove trailing " ". It obliges additional input (or end-of-file) after the number is entered before scanf() returns.
// scanf("%d ", &a[i]);
scanf("%d", &a[i]);
In addition to index problems in 2 places, code needs to look for overall monotonic and not just local monotonic behavior.
bool up = true;
bool down = true;
// for (int i = 1; i <= n; i++)
for (int i = 1; i < n; i++) {
if (a[i] > a[i-1]) down = false;
if (a[i] < a[i-1]) up = false;
}
printf((up || down) ? "YES" : "NO");
Additional code to short-circuit loop.
// for (int i = 1; i < n; i++) {
for (int i = 1; i < n && (up || down); i++) {
Further there is lack of the coding goal clarity on tie cases. May need
if (a[i] >= a[i-1]) down = false;
if (a[i] <= a[i-1]) up = false;
a has indices from 0 to n-1; you code references a[0] (which never gets assigned to) and a[n] (which is outside the bounds of the array).
You are checking with invalid array index. here you are declaring an array size of n but you are checking with i+1 that means n+1 for the last case. This is out of bound for your array. First of all you are storing data in array from 1 to n . But when you declare a array size n then it has index from 0 to n-1.so you can store data from 0 to n and start the check from 1 and end in n-1.
this one will work for you:
#include <stdio.h>
int
main ()
{
//Inputting the sequence
int n;
scanf ("%d", &n);
int a[n];
for (int i = 0; i < n; i++)
{
scanf ("%d", &a[i]);
}
int inc = 0;
int dec = 0;
//Checking monotonic sequence
for (int i = 1; i < n ; i++)
{
if (a[i] > a[i - 1])
{
inc = 1;
}
else if (a[i] < a[i - 1])
{
dec = 1;
}
}
if (inc == 1 && dec == 1)
{
printf ("NO");
}
else
{
printf ("YES");
}
return 0;
}

Is it the efficeint program to rotate array in left direction?

#include<stdio.h>
#include<stdlib.h>
main()
{
int i,j,l,m,n;
j=0;
printf("\nenter 5 element single dimension array\n");
printf("enter shift rate\n");
scanf("%d",&n);
/* Here we take input from user that by what times user wants to rotate the array in left. */
int arr[5],arrb[n];
for(i=0;i<=4;i++){
scanf("%d",&arr[i]);
}
/* Here we have taken another array. */
for(i=0;i<=4;i++){
printf("%d",arr[i]);
}
for(i=0;i<n;i++){
arrb[j]=arr[i];
j++;
// These loop will shift array element to left by position which's entered by user.
}
printf("\n");
for(i=0;i<=3;i++){
arr[i]=arr[i+n];
}
for(i=0;i<=4;i++){
if(n==1 && i==4)
break;
if(n==2 && i==3)
break;
if(n==3 && i==2)
break;
printf("%d",arr[i]);
}
//To combine these two arrays. Make it look like single array instead of two
for(i=0;i<n;i++){
printf("%d",arrb[i]);
}
// Final sorted array will get printed here
}
Is it the efficeint program to rotate array in left direction?
Actually, very complicated, and some problems contained:
for(i = 0; i < n; i++)
{
arrb[j] = arr[i];
j++;
}
Why not simply:
for(i = 0; i < n; i++)
{
arrb[i] = arr[i];
}
There is no need for a second variable. Still, if n is greater than five, you get into trouble, as you will access arr out of its bounts (undefined behaviour!). At least, you should check the user input!
for(i = 0; i <=3 ; i++)
{
arr[i] = arr[i + n];
}
Same problem: last accessible index is 4 (four), so n must not exceed 1, or you again access the array out of bounds...
Those many 'if's within the printing loop for the first array cannot be efficient...
You can have it much, much simpler:
int arr[5], arrb[5];
// ^
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5];
This does not cover negative values of n, though.
arrb[i] = arr[(((i + n) % 5) + 5) % 5];
would be safe even for negative values... All you need now for the output is:
for(int i = 0; i < 5; ++i)
printf("%d ", arrb[i]);
There would be one last point uncovered, though: if user enters for n a value greater than INT_MAX - 4, you get a signed integer overflow, which again is undefined behaviour!
We can again cover this by changing the index formula:
arrb[i] = arr[(5 + i + (n % 5)) % 5];
n % 5 is invariant, so we can move it out of the loop:
n %= 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(5 + i + n) % 5];
Finally, if we make n positive already outside, we can spare the addition in the for loop.
n = ((n % 5) + 5) % 5;
for(int i = 0; i < 5; ++i)
arrb[i] = arr[(i + n) % 5]; // my original formula again...
Last step is especially worth considering for very long running loops.
I think you want to do something like this (you should check that 0 <= n <= 5, too):
int b[5];
int k = 0;
for(i=0; i<5; i++){
if (i < 5 - n)
b[i] = arr[i+n];
else
{
b[i] = arr[k];
k++;
}
}
Array b is used to save the rotated matrix.

adding a 0 char after every even number in an array C

I'm trying to create a program in C which, after every even number, will add a "0". But I have a problem. If I insert for example only even numbers (5 or more numbers) the program crashes.
Below is the program I have right now.
I would like some indications or a code sample to point out what I did wrong and how I can fix it.
void main()
{
int *a, i, n, m;
printf("dimensiune=");
scanf_s("%d", &n);
a = (int*)malloc(n*sizeof(int));
for (i = 0; i < n; i++)
{
printf("a[%d]=", i + 1);
scanf_s("%d", &a[i]);
}
for (i = 0; i < n; i++)
{
if (a[i] % 2 == 0)
{
n++;
a = (int*)realloc(a, n*sizeof(int));
for (m = n - 1; m > i;m--)
{
a[m + 1] = a[m];
}
a[i + 1] = 0;
i++;
}
}
printf("\n currently you have %d numbers in this string\n", n);
printf("your string \n");
for (i = 0; i < n; i++)
{
printf("a[%d]=%d\n", i + 1, a[i]);
}
}
Change:
for (m = n - 1; m > i;m--)
{
a[m + 1] = a[m];
}
to:
for (m = n - 1; m > i;m--)
{
a[m] = a[m-1];
}
I've just tested it, it's working for me, should work for you.
I see a problem with this loop:
for (m = n - 1; m > i;m--)
{
a[m + 1] = a[m];
}
When you start the loop, n is the number of element in the loop. During the first iteration, m is the index of the last element of the loop. So, m+1 is after the last element, creating a buffer overflow.
Thanks for all comments I solved the bug replacing void main() with int main(void) + the solution provided by Shady Programmer.

Input to Multi-Array in C

I am trying to assign user input into an array; however, the program below only picks up on the first element in each line of input. The ultimate goal of this program is to find the diagonal sums of integers and return the absolute value of their difference.
Example input (note that the first number gives the number of rows and columns (square array):
Input:
3
11 2 4
4 5 6
10 8 -12
Output:
Expected = 15
Actual = 10
I realize that the issue lies in the way that the array is setup. If I print the array out I get: 111555999
Any hints/help would be very appreciated.
int main() {
int n, i, c, multi_array[200][200], sum1 = 0, sum2 = 0;
scanf("%i", &n); //N = number of rows and number of columns (square 2D array)
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d ", &multi_array[c][i]); //enter integers to store in array
}
}
for (i = 0; i != n; i++) {
sum1 += multi_array[i][i]; //add up top left to bottom right diagonal
}
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n-i]; //add up top right to bottom left diagonal
}
printf("%i", abs(sum1 - sum2)); //print absolute value of the difference between diagonals
return 0;
}
Your major problem is here, where you go out of bounds:
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n - i]; // when i is 0, th
}
When i = 0, you are accessing multi_array[0][3], which is out of bounds when N = 3.
So change it to this:
multi_array[i][n - i - 1]
You should read your array like this:
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf(" %d ", &multi_array[i][c]);
}
}
since C stored its arrays in row-major order. What you have stores the array in column-major order. It's not wrong, but it's something you do only if you really have to.
Finally, change again the input part of your code to this:
scanf("%d", &n);
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d", &multi_array[i][c]);
}
}
so that you have to input exactly what you need to. With your initial code I have to type an extra random number when I had completed the input process.
Last but not least, I am posting the whole code, where I have wrote some extra printf()'s, which are actually for the programmer, so that he can see step-by-step if his code is acting as expected or not.
#include <stdio.h>
#include <stdlib.h> /* abs */
int main() {
int n, i, c, multi_array[200][200], sum1 = 0, sum2 = 0;
scanf("%d", &n);
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
scanf("%d", &multi_array[i][c]);
}
}
for (i = 0; i < n; i++) {
for (c = 0; c < n; c++) {
printf("|%d|", multi_array[i][c]);
}
printf("\n");
}
for (i = 0; i != n; i++) {
sum1 += multi_array[i][i];
}
printf("sum1 is %d\n", sum1);
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n - i - 1];
}
printf("sum2 is %d\n", sum2);
printf("%i", abs(sum1 - sum2));
return 0;
}
Output:
3
11 2 4
4 5 6
10 8 -12
|11||2||4|
|4||5||6|
|10||8||-12|
sum1 is 4
sum2 is 19
15
You are clearly going out of bounds here:
for (i = 0; i != n; i++) {
sum2 += multi_array[i][n-i]; //add up top right to bottom left diagonal
}
When i is equal to 0 the expression n-i will be equal to n, but the range of the array is from 0 to n-1. The code will read uninitialized values and cause undefined behavior.
The second array index should be 1 less.

Resources