I'm trying to calculate HCF in C with pointers.
int-type-Pointer ptr points to an array of integers.
The inputs that i have given are 30,60,18,a. And here "a" is to terminate the list of integers and breaks off the "while".
I tried the debug mode, and found the values:
*ptr = 30
*(ptr+1)= -1163005939 //the garbage that i'm talking of.
*(ptr+2)= 60
*(ptr+3)= 30
while what i should get are 30, 60,18.
#include<stdio.h>
void main(){
int* ptr=(int*) malloc( sizeof(int)* 50);
int input=0;
int smallest;
printf ("Enter the numbers (press any alphabet when you're done )\n");
while (1)
{ input++;
if (input==1 && scanf("%d", ptr)) // the first number is stored in smallest
{smallest = *ptr; continue;}
if (!scanf("%d",ptr+input )) // if the input is a character , scanf says 0,
{input--; //! makes it 1, and we jump out of the loop
break;}
if (smallest > *(ptr+input)) // swapping
{ smallest += *(ptr+input);
*(ptr+input) = smallest- *(ptr+input);
smallest= smallest- *(ptr+input);
}
}
// code for determining the HCF
char c;
if (smallest <=0)
{
printf("", scanf("%c",&c ), printf("Answer is 0")); // it will print that the answer
exit(0); //is 0 then waits for you to
} //press any key and then it exits
//if smallest greater than 0
int i=2;
int HCF=1;
int j;
for (; i<smallest/2; i++)
{ for (j=0; j<=input;j++)
// this is where the problem is suspected
//as i ve seen in the debug mode
//it gives results divides the garbage value to i
{if (! (*(ptr+j)%i == 0)) // if the number stored in the location is not
break; //divisible by i, then leave that number i
} //and check for the next i
if (j>input)
HCF *= i;
}
printf( "", scanf("%c", c), printf("The HCF is %d ", HCF));
free(ptr);
}
So what is the problem?
And i didnt want to allocate the 50 ints memory. I wanted to just use the pointer wildly without any allocation. I know its bad practice but i just want to apply it . Is that any harm to other programs? How?
It's garbage because you never write anything to it. Look at this code
while (1)
{ input++;
if (input==1 && scanf("%d", ptr)) // the first number is stored in smallest
{smallest = *ptr; continue;}
if (!scanf("%d",ptr+input )) // if the input is a character , scanf says 0,
{input--; //! makes it 1, and we jump out of the loop
break;}
//code that doesn't assign values to ptr
}
by the time you get to scanf("%d",ptr+input ), input will be 2 if scanf("%d", ptr) returned a truthy value. That's because of this if statement:
if (input==1 && scanf("%d", ptr)) // the first number is stored in smallest
{smallest = *ptr; continue;}
notice how you continue here when input is equal to 1? that means that the while loop will skip everything else and begin again from the beginning, and the first thing that it's going to do is increment input from 1 to 2.
Related
I have a weird issue. I ask a user to enter a number between 1 and 15. Then I would ask the user would the like to get the factorial value of the number using either recursive or a for loop.
When they answer that question the inputted value goes to 0. If I remove the question for testing purpose the value stays the value the user inputted.
#include <stdio.h>
int recursive(int);
int nonRecursive(int);
int main()
{
/* Variables */
int numberSelected, returnedValue;
char answer;
do
{
/* Request a number between 1 and 15 */
printf("Please enter a number between 1 and 15: ");
scanf("%d", &numberSelected);
printf("%d\n", numberSelected); /* This prints out the user's number */
}while(numberSelected < 1 || numberSelected > 15); /* Loops if the value is not between 1 and 15 */
/* Ask user if they want to return a recursive value or a value calculated manually */
printf("Would you like a recusive value of the number you entered? Y or N: ");
scanf("%s", &answer);
if(answer == 'y' || answer == 'Y')
{
printf("%d\n", numberSelected); /* Here it resets to 0 */
returnedValue = recursive(numberSelected); /* Returns the recursive value */
printf("The recursive value of %d is %d\n", numberSelected, returnedValue);
}
else
{
printf("%d\n", numberSelected); /* Here it resets to 0 also*/
returnedValue = nonRecursive(numberSelected); /* Returns the value from for loop */
printf("The non recursive value of %d is %d\n", numberSelected, returnedValue);
}
return 0;
}
/* Get value using recursive */
int recursive(int n)
{
if (n == 0)
return 1; // Base case
else
return n * recursive(n - 1);
}
/* Get value using for loop */
int nonRecursive(int n)
{
int i;
int fact = 1;
for(i = 1; i <= n; i++)
{
fact *= i;
}
return fact;
}
Thank you for the help
scanf("%s", &answer);
is wrong. %s is for reading strings (null-terminated sequence of characters), but answer has only room for 1 character, so out-of-bound write will occur when strings with one or more characters is read. It may break data around that.
The line should be
scanf(" %c", &answer);
Use %c, which reads single character.
Add a space before %c to have scanf() ignore whitespace characters.
I'm trying to find the frequency of digit into given string,which contain digit and letters. When i run the same program i get different result, look like random output. where is the problem ?
int main() {
char num[1001];
int digit[10];
int j,i;
int count;
scanf("%s",num);
for(i=48;i<=57;i++)
{
count = 0;
for(j=0; num[j] != EOF;j++)
{
if(num[j] == i)
{
count++;
}
}
printf("%d ",count);
}
return 0;
}
You have missed an & in the line with scanf before num. Correct code should be:
scanf("%s", &num);
When you are scanning for the value, you need to provide the address of the variable. That is you let your program know where to put the value. &num points to the address of the variable num. But if you just write scanf("%s",num) you are providing value of the num variable, which you don't care at all. You'll be overwriting that value anyway.
At the end of the string, computer puts a null character \0 whose ASCII value is 0, to denote that this is the end of the string. Kind of like a '.' but for a computer. So you check until you find the null character in the for loop like: num[j] != '\0' [Not EOF]
I don't see any issue here, it seems output is not readable properly
so try printing correctly like
printf("%c=>%d ",i, count);
so that you can read what number how many times. if you find wrong frequency,
post the input for which you are getting wrong output.
It seems like you're trying to compare a char element with an integer type.
for example:
char num[7] = {"ABC123");
if (num[3] == 1)
{
printf("True\n");
}
else
{
printf("False\n");
}
return 0;
// This will return False, even though the element at index 3 is "1".
I've ran your code, and it seems like the output is the same given the same input.
Edit:
We wanted to compare a two digit number to a char data type - which is essentially a character - a one digit number/case.
When we take a number N and modulo by 10, we get the last digit, example:
48 % 10 = 8
To get the first digit we simply divide by 10, and take the quotient, example:
48 / 10 = 4 (remainder 8).
With this knowledge, we can compare the n-th char with first digit, and the n+1-th char with the last one (given that we only compare two digits, we'll stop at n+1-th).
Tip: a number char can be turned into a int using char = char - '0'
char num[1001];
int digit[10];
int j,i;
int count;
scanf("%s",num);
for(i=48;i<=57;i++)
{
count = 0;
for(j=0; num[j] != EOF;j++)
{
if(num[j] - '0' == i / 10 && num[j+1] - '0' == i % 10)
{
printf("%c", num[j] - '0');
count++;
}
}
printf("%d: %d \n",i, count);
}
printf("\n");
return 0;
// This code will print the digits and the frequency in a new line:
48: n times
49: n times
.
.
.
57: n times
I've been experimenting with C a little bit. I usually use PHP and javascript.
I did "Hello World" and then I typed in this, which I copied from a website somewhere...
#include <stdio.h>
#include <stdlib.h>
#define MAX 20
int intcmp(const void*v1, const void *v2){
return (*(int *)v1 - *(int *)v2);
}
main(){
int arr[MAX], count, key , *ptr;
printf("Enter %d integer values; press enter after each\n", MAX);
for (count = 0; count < MAX; count++)
scanf("%d", &arr[count]);
puts("Press a key to sort the values");
getc(stdin);
qsort(arr, MAX, sizeof(arr[0]), intcmp);
for(count=0; count < MAX; count++)
printf("\narr[%d] = %d.", count, arr[count]);
puts("\nPress a key to continue");
getc(stdin);
printf("Enter a val to search for");
scanf("%d", &key);
ptr = (int * )bsearch(&key, arr, MAX, sizeof(arr[0]), intcmp);
if(ptr != NULL){
int fred = (ptr - arr);
printf("%d found at arr[%d]", key ,fred);
}else{
printf("%d not found", key);
}
}
So far so good. I'm trying to understand what all the stars do, but it's falling into place (ha ha - falling stars :)
However, if I type in a float e.g. 21.45 when it asks me for 20 integers, it rushes through to "Enter a val to search for" having filled the 20 array values with weird numbers.
Have I created some sort of buffer overflow? I realise that input should be checked - but I'm interested to know what I've done. Could I use my program to run arbitrary code? (Well, no, not with my knowledge... but could someone?)
However, if I type in a float e.g. 21.45 when it asks me for 20 integers, it rushes through to "Enter a val to search for" having filled the 20 array values with weird numbers
If you enter a value such as 21.45 the call to scanf("%d") will fail, as it is not an int, and will leave the .45 in stdin (the 21 will be extracted as a valid int) to be processed again. This causes the loop to re-read this value again and again (as it fails every time). The weird numbers are due to the elements of the array being uninitialised.
Check the return value of scanf() which returns the number of assignments made and if it fails skip whatever is in stdin:
int count = 0;
while (count < MAX)
{
if (1 == scanf("%d", &arr[count]))
{
count++; /* OK, so get next. */
}
else
{
/* !OK, skip invalid input. */
int c;
while ((c = fgetc(stdin)) != EOF && c != '\n');
}
}
If you fill the standard input with something that's not in the right format (in this case a float), the extraction of the value will fail. However, the broken data won't get extracted from the input stream. This means that scanf will fail repeatedly. As such, your arr[0...MAX-1] is not filled at all by scanf.
If you want to get a float, then in the scanf you need to have:
scanf("%f", &arr[count]);
Additionally, you need to declare your array as float arr[MAX]
I am trying to get both parts of this program to work as you can see I have split it with first part (question 1) and second part (question 2). The problem is first part runs fine just when the second part starts I can not input any string and it just seems to skip through the code without letting me input the string.
If I delete the first part (question 1) of the program then everything works fine and I can input the string. What interrance is causing this issue.
int main()
{
first();
second();
}
//Question 1
int first()
{
/* dataarray.c */
float data[20] = {
50.972438, 93.765053, 9.252207, 1.851414, 16.717533,
71.583113, 97.377304, 20.352015, 56.309875, 0.072826,
23.986237, 36.685959, 80.911919, 86.621851, 53.453706,
96.443735, 29.845786, 18.119300, 31.079443, 52.197715 };
/* The number of elements in the data array */
int data_size = 20;
int pos;
int j;
int i;
int k;
printf("Question 1\n");
for(i=0;i<data_size;i++)
{
printf("\nArray %i is %f ",i,data[i]); //Initial arrays print statement
}
printf("\n\nArray number to delete:"); //User Choose one to delete
scanf("%i",&pos);
k =0;
for(j = 0; j< pos;j++)
{
printf("\n Array %i is now %f ",k,data[j]);
k++;
}
k=pos;
for(j=pos+1;j<data_size;j++)
{
printf("\n Array %i is now to %f ",k,data[j]); //Shows array changed to
k++;
}
data_size = data_size - 1; //Decreases data size
}
//Question 2
int second()
{
printf("\n\nQuestion 2\n");
int a,b,check=0;
char str[20];
printf("\nEnter a String:\n"); //User inputs word to check if its palindrome
gets(str);
for(b=0;str[b]!=0;b++); //Starts at 0 increment till the last length
b=b-1;
a=0;
while(a<=b)
{
if(str[a]==str[b]) //String a is forwards b is backwards
{
a=a+1;
b=b-1;
check=1; //If check = 1 then a palindrome
}
else
{
check=0; //If check = 0 then it not a plaindrome
break; //Loop break
}
}
if(check==1)
printf("It is a Palindrome:"); //Statement printed if check = 1
else
printf("It is not a Palindrome\n"); // Else if 0 this statement is printed
}
When you call scanf in part one, I presume you enter a number followed by a newline. scanf consumes the number, but the newline is left in the buffer. The gets() in part 2 then sees the newline and returns a blank line. An easy solution is to do
scanf( "%i\n", &pos );
BTW, never use gets. Use fgets instead.
Im trying to make a simple game, http://pastebin.com/BxEBB7Z6, in c. The goal is to beat the computer by getting as close to 21 as possible by getting random numbers.
For each round the players name and sum is presented, but for some reasons it only works that first time? Something like this:
Player John has sum 0.
Player has sum 9.
Player has sum 11.
And so on.
Why does the the player's name get showed once, but not any other prints after that? I dont do a reassign somewhere :-)
I use the function void PrintPlayerSum(struct Player *p) to print it out, it works the first time, but only that.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
struct Player
{
char name[256];
int sum;
};
void PrintPlayerSum(struct Player *p)
{
printf("Player %s has sum %d\n", p->name, p->sum);
}
void wait ( int seconds )
{
clock_t endwait;
endwait = clock () + seconds * CLOCKS_PER_SEC ;
while (clock() < endwait) {}
}
int main()
{
struct Player *player = malloc(sizeof(*player));
strcpy( player->name, "John");
player->sum = 0;
while(1)
{
PrintPlayerSum(player);
printf("Do you want another number? (y/n, q for quit) ");
char ch;
scanf("%s", &ch);
if( ch == 'q' )
break;
if( ch == 'y' )
{
srand(time(NULL));
int rnd = rand() % 13 + 1;
player->sum += rnd;
printf("Player got %d\n", rnd);
}
if( ch == 'n' || player->sum > 21)
{
if( player->sum > 21 )
{
printf("\n*** You lost the game, please try again... ***");
}
else
{
printf("\nCPU's turn\n");
int cpusum = 0;
while( 1 )
{
if( cpusum > 21 )
{
printf("\n*** CPU lost the game with the score %d, you win! ***", cpusum);
break;
}
if( cpusum > player->sum )
{
printf("\n*** CPU won the game with the score %d, please try again ***", cpusum);
break;
}
wait(1);
srand(time(NULL));
int rnd = rand() % 13 + 1;
cpusum += rnd;
printf("CPU got %d, sum is %d\n", rnd, cpusum);
}
}
break;
}
printf("\n\n");
}
/* Cleanup ******************/
free(player);
/****************************/
printf("\n\n\n");
system("PAUSE");
return 0;
}
I suspect the problem is your use of scanf. You say you want to read a zero-terminated string, but you stuff it into a single char. The way the variables are laid out on the stack causes the terminating zero-byte to end up as the first char in player->name.
Try typing "buffer overflow" instead of "y", and you should get "player uffer overflow go ...".
If you want to stick with scanf, you want to make sure you pass it a proper string and set a limit on the size of the target buffer. For reading one char, try fgetc.
Edit:
The above is of course not quite right... It is a buffer overflow, but it is the pointer of the player struct that is being overwritten. By lucky coincidence you get to a valid address that points to a zero-byte. By typing more, you will most likely get a crash instead.
Your scanf call is likely the problem:
scanf("%s", &ch);
You seem to want a single character, but you're reading a string. It'll put the first character in ch, but keep going from there and overwrite whatever's next on the stack.
You should probably just use fgetc(stdin) or another function that reads a single character, if a single character is what you want.
shouldn't it be
struct Player *player = malloc(sizeof(struct Player));
Weird thing like that are usually caused by writing to unallocated memory. (Usually writing beyond the end of an array.)
I didn't look at your code, but search for things like that. Then run your program under valgrind.
At a first glance i can see you have done:
scanf("%s", &ch);
Which will use the address of ch to input a string, and therefore result in a buffer overflow. You need to do
ch = getchar ();
scanf ("%c", &ch);
etc.