Array and while scanf crash - c

#define LEN 200
int main()
{
int arr[LEN],i;
for (i =0; i < LEN; i++)
while(scanf("%d", arr[LEN]) == 1){
if((arr[LEN] == arr[LEN]+1) || arr[LEN] < 0){
printf("Bad numbers.\n");
}
else if(arr[LEN] == 0){
break;
}
}
printf("Break");
return 0;
}
My point is if I'm writing numbers that are different and greater than 0 and arr[5] is different from a[12] or a[any other] it should save it into the array. But else if arr[LEN] == 0 it should stop scanf and save read numbers into the array and then continue with other stuff. After a few numbers, my code crashed. Can somebody help me?

Inside the for loop, you need to use arr[i] instead of arr[LEN]. Truly speaking, arr[LEN] declaration creates an array of name arr with index ranging from 0 to LEN-1. So arr[LEN] is out of range of your array.
In scanf, you need to use &arr[i] instead of arr[LEN].
In the if condition you need to write if(arr[i] == arr[i-1]) because you can compare presently input value only with previous value, not with next value which has not been entered yet. But make sure you handle this condition separately for i=0 because then i-1 will not be an element of array.
I think these changes will make your code work smoothly for all values.
Also, if you want to make sure that all array values are different then you have to compare present input value with all the previously stored values. Because current value might be different from just previous value but may be similar to value entered even before that.

Related

int variable changes to 1 after 'while' loop

I was trying to make a 'decimal to binary' program. It should convert from 0 to 255 only and it does.
I have two variables, 'n' and 'temp', when the user first enters the number I store it on 'n'. Then I assign 'n' to 'temp' (thus creating a copy, at least that's what I think I'm doing).
then I only use 'temp' in my code. I never use 'n', not until the end where I decide to print the number the user entered. And here comes the problem, if I enter a number greater than 255, the variable 'n' changes to 1.
I tried running my code through a couple C online compilers and all of them output the variable 'n' the right way, meaning that despite the binary not working when the numbers is greater than 255 (as intended) they print the entered value.
I found one online compiler where it doesn't print the 'n' variable if its greater than 255.
https://www.tutorialspoint.com/compile_c_online.php
If you run my code through this compiler, you'll see how the variable 'n' changes to 1 without it being used.
I know the 'binary part' won't work if you use a number greater than 255. I want to know why 'n' changes out of nowhere.
#include <stdio.h>
int main()
{
int bin[8] = {0, 0, 0, 0, 0, 0, 0, 0};
int arrSize = 7;
int n;
int temp;
scanf("%d", &n);
temp = n;
while(temp != 0)
{
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
printf(" Decimal: %d ----> binary: ", n);
for(int i = 0; i <= 7; i++)
{
printf("%d", bin[i]);
}
printf("\n");
return 0;
}
You've run through a "Buffer overflow".
A quick definition for that:
A buffer overflow occurs when a program or process attempts to write
more data to a fixed length block of memory, or buffer, than the
buffer is allocated to hold. Since buffers are created to contain a
defined amount of data, the extra data can overwrite data values in
memory addresses adjacent to the destination buffer unless the program
includes sufficient bounds checking to flag or discard data when too
much is sent to a memory buffer.
The error in your code remains in this while loop:
while(temp != 0){
//I added this line to make it clear
printf("inside loop\tarrSize=%d\n",arrSize);
bin[arrSize] = temp % 2;
temp = temp / 2;
arrSize = arrSize - 1;
}
For an input equals to 300 (The error will occur for each input > 255) you'll have this output:
inside loop arrSize=7
inside loop arrSize=6
inside loop arrSize=5
inside loop arrSize=4
inside loop arrSize=3
inside loop arrSize=2
inside loop arrSize=1
inside loop arrSize=0
inside loop arrSize=-1
inside loop arrSize=0
The problem is that we have an index equals to -1, You'll ask what will happen ? well in fact arrays are pointers to the address of the first element of the table + the offset (index * size of the type of the table) which means that for bin[-1] it is in fact arrSize, and bin[-2] is in fact n.
You can check this by verifying the addresses as it follows:
printf("# of bin[-1]:\t%p\n",(void*)&bin[-1]);
printf("# of arrSize:\t%p\n\n",(void*)&arrSize);
printf("# of bin[-2]:\t%p\n",(void*)&bin[-2]);
printf("# of n:\t\t\t%p\n",(void*)&n);
which with my compiler gave me:
# of bin[-1]: 0x7ffe00e32f9c
# of arrSize: 0x7ffe00e32f9c
# of bin[-2]: 0x7ffe00e32f98
# of n: 0x7ffe00e32f98
So you changes without knowing bin[-1] (or bin[-2] according to the value of n) which is in fact arrSize (or n)..
How you can fix this ? I advice you to verify the index every time you want to loop over an array (the condition of the loop must be in function of arrSize). Or you can if you want for this specific exemple to ignore that and focus on the logic: verify the input (in your case the input n must be: 0 <= n <= 255)
void *ieee2b(double value,char size,void *res){
char
*p0=res,
*p=p0;
vbreplacec(vbsprintf(p,"%*.*s",size,size," "),' ','0',p);
if((long)value!=value)
while(1){
double
tmp=value*2;
*p++='0'+(long)tmp;
if(tmp==1||tmp==0||p-p0>size)
break;
value=tmp-(long)tmp;
}
else{
p=p0+size-1;
while((long)value>1){
*p--='0'+((long)value%2);
value=(long)value/2;
}
*p--='0'+((long)value);
}
return res;
}

Why does my for loop go out of bounds?

I have a program to check if a sentence read on the keyboard is a pangram.
But when displaying the results (in the last for-loop), it goes out of the expected bounds. If you uncomment the printf statement, you can see that even thought i<26 is set as the loop condition, it runs upto i = 27 and the array of size 26 has elements cache[26] = garbage value and cache[27] = 0. What is wrong with my last for loop ?
int main() {
char* string = (char*)malloc(1024*sizeof(char));
fgets(string, 1024, stdin);
int i=0, cache[25]={0};
while(string[i]!='\0' ){
cache[(toupper(string[i])-'A')]++;
i++;
}
for( i=0; i<26; i++){
// printf("%d - %d\n",i,cache[i]);
if(!cache[i]){
printf("not pangram");
return(0);
}
}
printf("pangram");
return 0;
}
The problem is that your array is first too small for the 26 letters of the alphabet. It should be at least cache[26].
Then the following might go out of range for any non alphabetic chars (comma, space, etc...):
cache[(toupper(string[i])-'A')]++;
Going out of range will corrupt your memory (for example overwrite i or whatever else can happen when the behavior is undefined).
How to solve the issue?
You may consider protecting your cache increment:
if (isalpha(string[i]))
cache[(toupper(string[i])-'A')]++;
Note that some more exotic locale might consider some chars outside the range 'A'-'Z' as being alpha. So you may even want to be even stricter:
int letter=toupper(string[i])-'A';
if (letter>=0 && letter<26)
cache[(toupper(string[i])-'A')]++;

How do I fix this issue with the if statements inside this for loop?

#define MAX 100000
bool hasPair(int array[], int start, int end, int size, int number)
{
int i, temp;
bool binMap[MAX] = {0}; /*initialize hash map as 0*/
for(i = 0; i < size; i++)
{
temp = number - array[i];
if((temp>=0 && binMap[temp] == 1) && (temp != array[i]) && (array[i]>=start && array[i]<=end))
{
printf("The array contains at least one pair which sums up to %d.\n",number); // problem here
return true;
}
binMap[array[i]] = 1;
if(binMap[temp] == 0 && binMap[array[i]] == 0) //and here
{
printf("The array does not contain any pair which sums up to %d.",number);
return false;
}
}
}
I need to write a function which gets an array,its size,the range of its elements(start and end) and a random number as input and the output must be a statement whether there is a pair of different numbers inside the array that their sum equals that random number that we entered as input.I have a problem with the if statements,
because for example:-
an array of 10 elements and the range of these elements is 0-10 the random number is 18 and the arrays elements are:- 0,5,5,2,9,8,2,7,8,2.There wont be any combination of sum between two different numbers of this array which gives us 18
and it works fine in the functions I wrote.
The problem is that for example if we took the same array and this time we substituted 18 for 10 then there will be two different numbers that their sum will be equal to 10 but in my function if I enter this array with random number as 10 then it wont work and I think there is a problem with my If statement so if you can see it whats the problem here?
Your mistake is in the 2nd if condition. It's redundant. You are always invoking this case after the first iteration, and you don't go on for the next iterations.
You should remove the 2nd if condition entirely, and instead add AFTER the for loop a simple statement: return false;.
The idea is you should let the algorithm keep going to the next iterations, even if one was unseccesful. You only return false when you are done with the loop without finding matching elements during it - and only now you can tell no such elements exist.

Increasing intervals in an array, check

So I'm trying to check if an array that was previously inputted is increasing in intervals of 1, starting with the number 1 and ending with n (n being the array size).
Here's what I got so far:
for (int i =0; i<n;i++){
for (next=i;next<n;next++){
if(arr[i]+1 = arr[next]){
x = 1; //ignore this, it relates to the rest of the code.
}
else{
printf ("\nThis is not a permutation.");
break;
}
}
}
Now, my thinking is that this code would compare parameters that are next to each other, and if the following parameter is equal to the previous +1, then it is obviously increasing by 1. Problem is, when this is false, it wont print "This is not a permutation," and wont break the loop.
Any help would be appreciated.
Also, any insight as to checking if the array starts with the number 1 would be appreciated.
Thanks
Looks like in this line:
if(arr[i]+1 = arr[next]){
You intended comparison:
if(arr[i]+1 == arr[next]){
Have you tried if(arr[i]+1 == arr[next]) instead of if(arr[i]+1 = arr[next])??
If you need to check that a sequence is increasing, why are you comparing every element against the others? You should only need one for loop:
for (i = 1; i < n; i++)
{
if (arr[i - 1] + 1 == arr[i])
... // keep going
else
... // not a permutation
}
Basically, what your code does is check that every element after the i-th one is greater than that i-th one by one. Ultimately, this leads to an impossible case (as two numbers must be equal but must differ by one at the same time).
It sounds like you want to test if arr[0] == 1 and every subsequent array element is 1 greater than the previous element. Isn't that the same as checking your array for the values [1,2,3,...,n]?
for (int i = 0; i < n; ++n) {
if (arr[i] != i + 1) {
printf("\nThis is not a permutation.");
break;
}
}

Decrementing while loop in c

Is it possible to decrement the array size in a while loop in C by more than x--. For example, can you decrement an array by a third of the array size with each iteration?
int n = 10;
while (n < 0)
// do something
(round(n/3))-- // this doesn't work, but can this idea be expressed in C?
Thank you for the help!
You can use any expression:
int n = 10;
while (n > 0) // Note change compared with original!
{
// Do something
n = round(n/3.0) - 1; // Note assignment and floating point
}
Note that you can only decrement variables, not expressions.
You could also use a for loop:
for (int n = 10; n > 0; n = round(n/3.0) - 1)
{
// Do something
}
In this case, the sequence of values for n will be the same (n = 10, 2) whether you round using floating point or not, so you could write:
n = n / 3 - 1;
and you'd see the same results. For other upper limits, the sequence would change (n = 11, 3). Both techniques are fine, but you need to be sure you know what you want, that's all.
Yes, it is possible to add or subtract any number to your variable n.
Usually, if you want to do something a very predictable number of times, you would use a for loop; when you aren't sure how many times something will happen, but rather you are testing some sort of condition, you use a while loop.
The rarest loop is a do / while loop, which is only used when you want to execute a loop one time for certain before the first time the while check occurs.
Examples:
// do something ten times
for (i = 0; i < 10; ++i)
do_something();
// do something as long as user holds down button
while (button_is_pressed())
do_something();
// play a game, then find out if user wants to play again
do
{
char answer;
play_game();
printf("Do you want to play again? Answer 'y' to play again, anything else to exit. ");
answer = getchar();
} while (answer == 'y' || answer == 'Y');
There is no array in your code. If you wan't n to have a third of its value on each iteration, you can do n /= 3;. Note that since n is integral then the integral division is applied.
Just like K-Ballo said there is no array in your example code but here is an example with an integer array.
int n = 10;
int array[10];
int result;
// Fill up the array with some values
for (i=0;i<n;i++)
array[i] = i+n;
while(n > 0)
{
// Do something with array
n -= sizeof(array)/3;
}
But be careful in the example code you gave the while loop is checking if n is less than zero. As n is intialised to 10 the while loop will never be executed. I have changed it in my example.

Resources