scanf confusion with type error - c

I just make a program to guess some random pairs in an array,if guess right, delete this pair.
I met a problem that I can only type integer number.Everytime I tried to type like * ,the program will crash. I use a condition like:
if (scanf("%d",&temp)==1)
to try to fix my problem, but it really does'nt work.
here is my code and please give me some help:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int r[4]; //random
int s[8]; //store
char c[8]; //cover
int g[8]; //guess
int i;
int round=0;
int left = 4;
int point = 0;
int clear_index[2];
int temp;
// generate random number
for (i=0;i<4;i++)
{
r[i] = (rand()%10)+1;
s[i] = r[i];
s[i+4] = r[i];
}
// show the default number
printf("[show] ");
for (i=0;i<8;i++)
{
printf("%d ",s[i]);
c[i] = '*';
}
printf("\n");
while(left>0)
{
// print left
printf("[cover] ");
for (i=0;i<8;i++)
printf("%c ",c[i]);
printf("\n");
//guess
printf("[guess] ");
for(i=0;i<8;i++)
{
if (scanf("%d",&temp)==1)
g[i] = temp;
if (g[i] == s[i])
{
printf("v\n");
clear_index[point] = i;
point++;
}
}
if (point == 2)
{
for (i=0;i<2;i++)
c[clear_index[i]]=' ';
left-=1;
point = 0;
}
round+=1;
//left-=1;
}
printf("you won in %d round",round);
}

You get the segmentation fault, because, in case, you did not enter an integer, scanf will not return 1, and then, using g[i] will invoke undefined behavior.
FWIW, g is a local automatic array variable, and unless initialized explicitly, will have indeterminate value. Attempt to read the value will invoke the UB.
Solution:
Always initialize the local variables.
In case scanf() fails, you need to eat up the invalid input using some loop like while (getchar != '\n'); before you proceed to take the next input.

You are reading a number but the user can place a digit. To prevent this you can use the function atoi() from the library stdlib.h. It converts a string to a integer, if the integer is just number digits, it'll convert it to a integer. If it is a character it will return 0. So you just need to prevent the occurrence of a 0 after the atoi() function is called.

Related

Two integers and an operator. Error, not doing what it needs to do in other compiler

The problem here is that it works on vscode but it doesn't in onlinegdb.com. I think there's some error in my code that I overlook but I can't find so I am hoping someone out there would help me out. thank you very much.
btw there's no warning error in onlinegdb.com but when I try to run it, the result is not right so that's the issue.
#include <stdio.h>
#include <string.h>
//This is a FUNCTION PROTOTYPE :)
int check(char op);
int calculate(int a, int b, int c);
char * print_operators(int op);
int main()
{
// create a variable to store the integers.
int num1,num2;
// create a variable to store the operator that the user wants to use.
char operator;
//prompt for the first integer.
printf("Enter first Integer: ");
scanf("%d", &num1);
// prompt to enter the operator to be used.
do
{
printf("Enter operator, + as sum, - as difference, * as product, / as quotient: ");
scanf(" %s", &operator);
}
// keep prompting the user until he input the correct operator using the check function call.
while(check(operator) == -1);
// prompt for the second integer.
printf("Enter Second Integer: ");
scanf("%d", &num2);
// calculate the total result using the calculate function call and store it to a variable called total.
int total = calculate(num1, num2, check(operator));
// using the print_operators to know what is the operator being used to store it in variable operators in a string form.
char * operators = print_operators(check(operator));
//output of the result.
printf("The %s is: %d\n", operators, total);
return 0;
}
// this is function definition of check to verify if the input is valid and if it's valid then covert it to integer in an order.
int check(char op)
{
// creating a char array to store the symbol of the operators.
char operations[] = {'+', '-', '*', '/'};
// this variable is to be use in a for loop so that I don't need to use a magic number in for-condition.
int size = sizeof(operations);
// looping to convert the operator to integer from 0 to 3 and storing the operator in its ordered form.
// 0 representing +, 1 representing -, 2 representing *, and 3 representing /.
for (int i = 0; i < size; i++)
{
if(op == operations[i])
{
return i;
}
}
// else print invalid and return the value of -1 representing its not valid.
printf("INVALID\n");
return -1;
}
// this function definition of calculating is to calculate the two integers using the operator that is already converted to an integer.
int calculate(int a, int b, int c)
{
// create a variable to store the result of the calculation.
int equal;
// if the operator is 0 then do addition.... and so on.............
if (c == 0)
{
equal = a + b;
}
else if (c == 1)
{
equal = a - b;
}
else if (c == 2)
{
equal = a * b;
}
//else if its not 0, 1, or 2 then its difinitely 3.
else
{
equal = a / b;
}
// then return the result.
return equal;
}
/* This function definition of print_operators is to return the operator as a string so that I can use it in print without manually coding it. */
char * print_operators(int op)
{
char * operators[] = { "sum", "difference", "product", "quotient" };
int size = sizeof(operators);
for (int i = 0; i < size; i++)
{
if (i == op)
{
return operators[i];
}
}
// Some compiler needs a return value even if it didn't reach so I just did this just in case your compiler is different from mine.
//although this is not necessary for my compiler, I've checked it in the cloud server, and there's an error if this is not included.
char * total = "total";
return total;
}
/* Example if I want to output the 1+2 then my output is "The sum is: 3". Notice that the sum is not constant cuz maybe if I what to use subtraction then I want it to output as "The difference is: 1". */
First of all, scanf(" %s", &operator); should be scanf(" %c", &operator); operator because you are expecting a single character here, not a string. It can potentially corrupt the stack.
I guess that should fix your issue with onlinegdb.
There are also other issues and possible simplifications. Such as your print_operators function which may be written simply as:
char *print_operators(int op)
{
char *operators[] = { "sum", "difference", "product", "quotient" };
/* sizeof(array) gives the total size of your array in bytes, not the number of elements in your array, so divide it by the size of each element to get num of elements */
int count = sizeof(operators)/sizeof(char *);
/* Since you already have the operator converted to a number in your check() function, just use it directly as index here */
if(op < count)
return operators[op];
else
return "total";
}
"Some compiler needs a return value"
All compilers need a return value if you have specified that a function returns a value other than void. Some compilers, however, may not warn you that you are not returning a value and lead you into undefined behaviour, which is not what you want.

Decimal to binary using string in c....stuck with some conceptual error

#include<stdio.h>
char bin(int);
int main()
{
setbuf(stdout,NULL);
int num;
char res[50];
printf("Enter the number: ");
scanf ("%d",&num);
res=bin(num);
printf("%s",res);
return 0;
}
char bin(int num)
{
char str[50];
int i,val;
for(i=0;num>=0;i++)
{
val=num%2;
str[i]=val;
num=num/2;
}
return str;
}
I really cant understand the error in the usage of strings... to convert the decimal to binary. Whats the conceptual error Im not following?
char is a single character, so char bin(int) will not be able to return a string (i.e. a null-terminated array of characters). And you cannot "return" an an array of characters, because C does not allow to return any array as function result. You can just pass/return pointers to the begin of such arrays.
So I'd suggest to change the interface of bin to reicieve the result buffer as parameter. Don't forget to "close" the string, i.e. to write the string termination character after the last "actual" character:
void bin(int num, char* resultBuffer) {
...
resultBuffer[i] = '\0';
}
In main, you call it then like
bin(num, res);
Returning str amounts to returning a local variable, you can't do it, what you can do is to return a pointer to a previously allocated memory block that works as an array (as an alternative to the oher answer, which is a good solution).
To do this you can declare str as a pointer, allocate memory for it and return it, making sure the variable to which the value is assigned is also a pointer, all the rest can remain the same.
There are, however, problems with the bin function.
Consider the statement:
str[i] = val;
This will not work as expected you are assigning the int result of the operation, which will be 1 or 0, you need to convert this value to the respective character.
The loop for (i = 0; num >= 0; i++) is an infinite loop because num will never be negative, unless you provide it a negative number in which case it will break in the first iteration, that is to say this code only works with positive integers. You need > instead of >=.
Finally you need to null terminate the string when the conversion is complete.
Corrected code (Online):
#include <stdio.h>
#include <stdlib.h>
char *bin(int); //return pointer
int main() {
setbuf(stdout, NULL);
int num;
char *res; //use pointer to receive string assignment
printf("Enter the number: ");
scanf("%d", &num);
res = bin(num);
printf("%s", res);
return 0;
}
char *bin(int num) {
char *str = malloc(50); // allocate memory
int i, val;
for (i = 0; num > 0; i++) { // replacing >= with >
val = num % 2;
str[i] = val + '0'; // convert to character
num = num / 2;
}
str[i] = '\0'; //null terminate the string
return str;
}
Note that you should also check for the inputed value, if it is larger than what an int variable can hold it will result in undefined behavior.

Using a void function to calculate most frequent integer in an array in C

Hello! I am trying to create a program (school assignment) that asks the user to enter a sequence of integer numbers between 0 - 1000. The sequence stops when the user enters a negative integer or more than 100 integers.
Actually entering, saving and creating a "counter" array with the amount of times the integers have been entered is accomplished. However, a part of the assignment is creating a void function that uses pointer variables to return what integer occurred the most times and how many times it occurred.
#include <stdio.h>
#include <stdlib.h>
#define MAX_SEQ 100
void analyzeFrequencies(int mainArray[], int counter[], int* mOI, int* numOfOccurences);
int main()
{
int i=0, *mOI=0, *numOfOccurences=0, tempNum=0, mainArray[MAX_SEQ] = {0}, counter[MAX_SEQ] = {0};
printf("Please enter a integer between 0-1000.\nSequence will stop when you enter negative integer of after MAX_SEQ integers.\n\n");
do
{
if( scanf("%d", &tempNum) == 1)
{
if (tempNum <= 1000)
{
if (tempNum < 0)
{
printf("You decided to exit the sequence. Your array entered is:\n");
}
else
{
mainArray[i] = tempNum;
counter[tempNum]++;
++i;
}
}
else
printf("Please enter a number between 0-1000. Exit sequence by entering negative number.\n");
}
else
printf("\nError.\n");
} while(tempNum > 0 && i < MAX_SEQ);
analyzeFrequencies(mainArray, counter, mOI, numOfOccurences); //This is where the problem occurs.
if (i == 0)
{
printf("You entered no sequence.");
}
else
{
printf("\nSequence:\n");
for(int j=0; j<i; j++)
{
printf("[%d] %d\n", j, mainArray[j]);
}
printf("Most occurred item: %d\nOccurred %d times!", *mOI, *numOfOccurences);
}
return 0;
}
When I run my code, everything works fine until I execute the analyzeFrequencies() function. The program then stops working.
void analyzeFrequencies(int mainArray[], int counter[], int* mOI, int* numOfOccurences)
{
for(int i=0; i<MAX_SEQ; i++)
{
if(counter[i] > *numOfOccurences)
{
*mOI = i;
*numOfOccurences = counter[i];
}
}
}
I expect the function "void analyzeFrequencies" to return a pointer variable value through "mOI" and "numOfOccurences". mOI is the most occurred integer.
Instead, the program just stops working. I've been looking at my code for a while but can't seem to find what causes this. I might have been sitting for too long with my code and gone blind. Would appriciate any help to realize where I am going wrong!
P.S! I realize the code is not optimized at all and I would gladly receive any feedback, my main priority is however making the analyzeFrequencies function to start working!
int i=0, *mOI=0, *numOfOccurences=0, tempNum=0,
mainArray[MAX_SEQ] = {0}, counter[MAX_SEQ] = {0};
In your main funciton, you have mOI and numOfOccurences declared as pointer variables, both of which are initialized to 0, meaning they are NULL pointers. You then pass those NULL pointers into your function and dereference them. Dereferencing a NULL pointer invokes undefined behavior.
Declare these two variables as int instead of int * and pass their addresses to analyzeFrequencies.
So declare them like this:
int i=0, mOI=0, numOfOccurences=0, tempNum=0,
mainArray[MAX_SEQ] = {0}, counter[MAX_SEQ] = {0};
And call your function like this:
analyzeFrequencies(mainArray, counter, &mOI, &numOfOccurences)

C Convert string to integer using arrays

I'm making a program where user enters grades (1 to 5) and then the grade gets added to array for later inspection. When user enters letter "s", the program closes. When ran my program crashes, why?
#include <stdio.h>
#include <stdlib.h>
int i;
int grade[50];
char *num[20];
int enter();
int enter()
{
for (i=0; i<10; i++) {
printf("\nEnter grade:\nPress [s] to close program\n");
scanf("%s",&num[i]);
if (strcmp(num[i],"s") == 0) {
break;
} else {
grade[i] = atoi(num[i]);
}
}
}
int main()
{
enter();
for (i=0; i<10; i++) {
printf("\n%d",grade[i]);
}
return 0;
}
remove ' * ' from num[20] declaration, as you are declaring 20 character string pointers, so reading and comparing values with num[i] will cause error.
Besides, you just nead a simple string to get the grade.
The reason why program crashed is that num is a pointer array, the element of num can not pointer to valid memory which used to store the string you inputed.
you can change char *num[10] to char num[10][12] and 'scanf("%s", &num[i])to scanf("%s", num[i]), and that everything will be OK.
Of course, you can use malloc to dynamic alloc memory for each element in num, like:
`for(i = 0; i < 10; i ++){
num[i] = (char*)malloc(sizeof(char) * 12);
}
`
Even thought, you must change scanf("%s", &num[i]) to scanf("%s", num[i]);
Finally, you can not forget to free the memory you just dynamic malloc.

How to make a C program that finds the numbers in the array and then multiplies it?

I wanted to make a C program that finds the numbers in the input array and then multiplies it all together, I made the program but it got an issue that I don't know, can anybody help me with it!?
Here is the code!
#include <stdio.h>
#include <stdlib.h>
int main ()
{
char t[10];
int n, z;
n = 0;
printf ("please enter a code: \n");
scanf ("%s", t);
while (n != '\0')
{
if (isdigit (t[n] == 0))
{
n++;
}
else
{
z = t[n];
z *= z;
}
}
printf ("%d", z);
}
Here is updated code. There is a comment for each bug that needed correction.
(Note that the comment describes the intention of the corrected code, it doesn't describe the bug.)
int temp;
z=1; // Initialize z
printf ("please enter a code: \n");
scanf ("%s", n);
while (t[n] != '\0') { // While there are more characters in the string
if (isdigit (t[n])) { // Check if the character is a digit
temp = t[n] - '0'; // Convert character digit to corresponding number.
z *= temp;
}
n++;
}
Your first problem is that you don't actually use t in your while loop. Your while loop only uses n which is set to 0 and never modified.
Your second problem is that you may be better off to use scanf("%d", &number); to scan numbers straight away.
z should be initialized to 1. and remove "z = t[n];"
#include <stdio.h>
#include <string.h>
main()
{
char a[5] ;
int b=1, n=0,m=0;
scanf("%s",a);
while (n <5 )
{
if (!isdigit(a[n]))
{
n++;
m++;
}
else{
b *= (a[n]-'0');
n++;
}
}
if(m==5) b=0;
printf("%d\n",b);
}

Resources