CLion recommends to use 'strtol' instead of 'scanf' - c

#include <stdio.h>
int main(int argc, char** argv) {
int num = 0;
printf("Input: ");
scanf("%d", &num); <<<
printf("%d\n", num);
return 0;
}
scanf("%d", &num);
Clang-Tidy: 'scanf' used to convert a string to an integer value, but function will not report conversion errors; consider using 'strtol' instead
I wrote a very simple code with CLion and it recommends me 'strtol' instead of 'scanf'.
But I'm using only integer variable and there is no strings. I can't figure out why the inspection message pops up.
How do I modify this code?

How do I modify this code?
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
enum { INPUT_SIZE = 30 };
int main () {
char *ptr;
long ret;
char str[INPUT_SIZE];
fgets(str, INPUT_SIZE, stdin);
ret = strtol(str, &ptr, 10);
if( ret == LONG_MAX || ret == LONG_MIN ) {
perror("!! Problem is -> ");
}
else if (ret) {
printf("The number is %ld\n", ret);
}
else {
printf("No number found input is -> %s\n", ptr);
}
return(0);
}
If successful, strtol() returns the converted long int value.
If unsuccessful, strtol() returns 0 if no conversion could be
performed. If the correct value is outside the range of representable
values, strtol() returns LONG_MAX or LONG_MIN, according to the sign
of the value. If the value of base is not supported, strtol()
returns 0.
If unsuccessful strtol() sets errno to one of the following values:
Error Codes:
EINVAL The value of base is not supported.
ERANGE The conversion caused an overflow.
Source : IBM
Can you check overflow using scanf() for example?
Input: 1234 stackoverflow
Output: The number is 1234
Input: 123nowhitespace
Output: The number is 123
Input: number is 123
Output: No number found input is -> number is 123
Input: between123between
Output: No number found input is -> between23between
Input: 9999999999999999999
Output: !! Problem is -> : Result too large
Maybe off-topic but, Jonathan Leffler says in his comments(in another topics) that handle warnings just as errors.

Related

How to check if user input is not an int value in C

I need to check if a user input value is not an int value. I've tried different combinations of what I know but I either get nothing or random errors
If the user inputs any char it'll raise a warning message
this is what ive written
#include <stdio.h>
//C program to perform addition, subtraction, multiplication, division + - * /
int main()
{
int num1,num2;
char alpha[30]
printf("enter numbers:\n\n");
printf("number 1: ");
scanf("%d",&num1);
printf("number 2: ");
scanf("%d",&num2);
// write a funcntion that when a char is entered to display an error
if (num1//and num2 == alpha)
printf("error");
else {
printf("Rezultat: \n");
printf("sborut im e: %d\n",num1+num2);
printf("ralikata im e: %d\n",num1-num2);
printf("proizvedenieto im e: %d\n",num1*num2);
printf("ralikata im e: %d\n",num1/num2);
}
return 0;
}
Scanf has a return value for a reason.
1-3) Number of receiving arguments successfully assigned (which may be zero in case a matching failure occurred before the first receiving argument was assigned), or EOF if input failure occurs before the first receiving argument was assigned.
4-6) Same as (1-3), except that EOF is also returned if there is a runtime constraint violation.
Here is an example program using that information:
#include <stdio.h>
int main(int argc, char **argv) {
int inputInteger;
printf("Please provide some input.\n");
if(scanf("%d", &inputInteger) == 1) {
printf("You inputted an integer\n");
} else {
printf("You did not enter an integer\n");
}
return 0;
}
Output:
./a.out
1[Enter]
You inputted an integer
./a.out
hello[Enter]
You did not enter an integer.
Note: I feel obliged to inform you that scanf() is not the best way to get input. See this answer for more details.
EDIT: I changed if(scanf("%d", &inputInteger)) to if(scanf("%d", &inputInteger) == 1) so that EOF will not output that an integer was found (pointed out by chux in the comments).
a try/catch approach works, with casting to int the test is caught by the compiler
std::string input;
std::getline(std::cin,input);
int input_value;
try {
input_value=boost::lexical_cast<int>(input));
} catch(boost::bad_lexical_cast &) {
// process bad input here
}

Prompt for input and print a response with only one printf()?

C-code only: Ask user if they are married or not. User must input 0 for false. User must input any other character for true. Do it using only one printf.
Ok, so I always turn to stackoverflow as a last resort, because I am trying to figure it out. This, is what I came up with but I get errors and I have done other things like take out scanf("%f", &t), because that is essentially unnecessary. I also made char married[3]; char married[] ="; instead but that doesn't work.
Here is my code:
#include <stdio.h>
#include <string.h>
int main()
{
char married[3];
unsigned long t;
int f;
scanf("%f", &t);
scanf("%d", &f);
printf(" For the following question: Enter 0 if false. Enter anything but 0 if true. Are you married? %s", married);
if (f == 0)
{
married == "no";
}
else
married == "yes";
return 0;
}
Thanks the help is appreciated. Please go easy on me just learning...
I'm not sure you are interpreting the question correctly. It says to print whether the person is married or not. So that's the expected output. It suggests you can do that with one printf. It does not mean the whole program only has one printf so you are allowed to have another printf for the user prompt. It just means avoid using two printfs for the output (one for YES and another for NO). One way to do this is to use the ? operator.
For example:
#include <stdio.h>
#include <string.h>
int main(void)
{
int married = 1;
printf(" For the following question: Enter 0 if false. Enter anything but 0 if true. Are you married?");
scanf("%d", &married);
printf("You %s married\n", married ? "ARE" : "ARE NOT");
return 0;
}
#include <stdio.h>
#include <string.h>
int main() {
char married[4]; //Space for 'yes' + the NUL-terminator
//unsigned long t; Why do you have this?
int f = 1; //Initialize variables
//scanf("%f", &t); ??
//scanf("%d", &f); Wrong place
printf(" For the following question: Enter 0 if false. Enter anything but 0 if true. Are you married?"); //Remove %s and the argument. You are trying to print an uninitialized array
scanf("%d", &f); //scan input after printing
if (f == 0)
strcpy(married, "no");
else
strcpy(married, "yes"); //Copy strings using strcpy function
return 0;
}

Input validation of an Integer using atoi()

#include "stdafx.h"
#include <stdlib.h>
void main()
{
char buffer[20];
int num;
printf("Please enter a number\n");
fgets(buffer, 20, stdin);
num = atoi(buffer);
if(num == '\0')
{
printf("Error Message!");
}
else
{
printf("\n\nThe number entered is %d", num);
}
getchar();
}
The above code accepts a number in the form of a string and converts it to integer using atoi. If the user inputs a decimal number, only the bit before the decimal is accepted. Moreover, if the user enters a letter, it returns 0.
Now, I have two queries:
i) I want the program to detect if the user entered a number with decimal point and output an error message. I don't want it to take the part before the decimal point. I want it to recognize that the input is invalid.
ii) If atoi returns 0 in case there are letters, how can I validate it since the user can enter the number 0 as well?
Thanks.
atoi is not suitable for error checking. Use strtol or strtoul instead.
#include <errno.h>
#include <limits.h>
#include <stdlib.h>
#include <string.h>
long int result;
char *pend;
errno = 0;
result = strtol (buffer, &pend, 10);
if (result == LONG_MIN && errno != 0)
{
/* Underflow. */
}
if (result == LONG_MAX && errno != 0)
{
/* Overflow. */
}
if (*pend != '\0')
{
/* Integer followed by some stuff (floating-point number for instance). */
}
There is the isdigit function that can help you check each character:
#include <ctype.h>
/* ... */
for (i=0; buffer[i]; i++) {
if (!isdigit(buffer[i])) {
printf("Bad\n");
break;
}
}

How to prevent users from inputting letters or numbers?

I have a simple problem;
Here is the code :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
scanf("%d",&input);
}
I want the user to only enter numbers ...
So it has to be something like this :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
do{
scanf("%d",&input);
}while(input!= 'something');
}
My problem is that I dont know what to replace in 'something' ... How can I prevent users from inputting alphabetic characters ?
EDIT
I just got something interesting :
#include<stdio.h>
main(){
int input;
printf("Choose a numeric value");
do{
scanf("%d",&input);
}while(input!= 'int');
}
Adding 'int' will keep looping as long as I enter numbers, I tried 'char' but that didnt work .. surely there is something for alphabets right ? :S
Please reply !
Thanks for your help !
The strtol library function will convert a string representation of a number to its equivalent integer value, and will also set a pointer to the first character that does not match a valid number.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
...
int value;
char buffer[SOME_SIZE];
char *chk;
do
{
printf("Enter a number: ");
fflush(stdout);
if (fgets(buffer, sizeof buffer, stdin) != NULL)
{
value = (int) strtol(buffer, &chk, 10); /* assume decimal format */
}
} while (!isspace(*chk) && *chk != 0);
If chk points to something other than whitespace or a string terminator (0), then the string was not a valid integer constant. For floating-point input, use strtod.
You can't prevent the user from entering anything he wants -- you can only ignore anything s/he enters that you don't "like".
A typical pattern is to read a string with fgets, then scan through the string and check that all the input was digits with isdigit. If it was all digits, then convert to an integer; otherwise, throw it away and get the input again.
Alternatively, use strtol to do the conversion. It sets a pointer to the end of the data it could convert to a number; in this case you (apparently) want it to point to the end of the string.
If you don't mind some non-portable code, you can read one character at a time, and throw away anything but digits (e.g. with getch on Windows).
You should not use scanf to read in numbers - see http://www.gidnetwork.com/b-63.html
Use fgets instead.
However, if you must use scanf, you can do this:
#include <stdio.h>
int main() {
char text[20];
fputs("enter some number: ", stdout);
fflush(stdout);
if ( fgets(text, sizeof text, stdin) ) {
int number;
if ( sscanf(text, "%d", &number) == 1 ) {
printf("number = %d\n", number);
}
}
return 0;
}
Personally, I would read the input into a buffer and scan that string for my number.
char buffer[100];
float value;
do {
scanf("%s", buffer);
} while ( sscanf(buffer,"%f", &value) != 1 )
This will loop until the first thing the user enters on the line is a number. The input could be anything but will only get past this block when the first thing entered is a number.
example input:
43289 (value is 43289)
43.33 (value is 43.44)
392gifah (value is 392)
ajfgds432 (continues to loop)

How to format input to only accept integer values

input value 123 -- this value is integer, and valid
input value 1b23a -- this value is invalid
How do I detect which values are valid and not?
Here is my code:
#include <stdio.h>
#include <conio.h>
void main()
{
char str1[5],str2[5];
int num,num1,i;
num=0;
clrscr();
printf("Enter the Number ");
scanf("%s",str1);
for(i=0;str1[i]!='\0';i++)
{
if(str1[i]>=48&&str1[i]<=56)
num=num1*10+(str[i]-48);
else
{
printf("The value is invalid ");
}
}
printf("This Number is %d",num);
getch();
}
Please see this answer regarding use of strtol(). It is a safe way to convert arbitrary input that should be a string representation of an integer, while also saving 'garbage' bytes for additional analysis.
Using it, your code would look something like this:
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#ifdef LINUX_VERSION
#include <curses.h>
#else
#include <conio.h>
#endif
#define BUFF_SIZE 1024
int main(void)
{
char str1[BUFF_SIZE], *garbage = NULL;
long num = 0;
printf("Enter the Number ");
scanf("%s",str1);
errno = 0;
num = strtol(str1, &garbage, 0);
if (errno) {
printf("The number is invalid\n");
return 1;
}
printf("You entered the number %ld\n", num);
if (garbage != NULL) {
printf("Additional garbage that was ignored is '%s'\n", garbage);
}
getch();
return 0;
}
This doesn't fix everything that is questionable about what you posted, but it should help you get off to a better start.
Output is:
tpost#tpost-desktop:~$ ./t
Enter the Number 1234abdc
You entered the number 1234
Additional garbage that was ignored is 'abdc'
Compiled via:
gcc -Wall -DLINUX_VERSION -o t t.c -lcurses
I'm not sure what platform you are using, so additional fixes to the code may be needed.
#include<stdio.h>
#include<conio.h>
void main()
{
char str1[5],str2[5];
int num,num1,i;
num=0;
clrscr();
printf("Enter the Number ");
scanf("%s",str1);
for(i=0;str1[i]!='\0';i++)
if(str1[i]>=48&&str1[i]<=56)
num=num1*10+(str[i]-48);
else
{
printf("The value is invalid ");
}
}
printf("This Number is %d",num);
getch();
}
One way is to use sscanf and check that there are no characters following the number. This is done most easily by adding a %c on the end and testing the return code, like this:
const char *yourString = ...;
int theValue, dummy;
if (sscanf(yourString, "%d%c", &theValue, &dummy) == 1) {
// Was a pure number, parsed into 'theValue'
} else {
// Either no number or had junk after it
}

Resources