Print numbers until a negative number is entered - c

My problem is not related to scanf();
For example: input -> 542-4Output -> 5,4,2,-4
I mean, print until negative number with negative number. It's okey until negative number, but I want to print negative number too. How can I do ? Please help me. I used getchar(), isdigit(), int a=x-'0'
char x =getchar();
while(isdigit(x)){
int a=x-'0';
printf("%d,",a);
x=getchar();
}

isdigit(x) will not be true for '-', so you need to test for that separately.
Since you want to stop after the first negative number, you need to set a flag when you read the -, so you don't keep reading other negative numbers.
int neg = 0;
char x = getchar();
while (isdigit(x) || x == '-') {
if (x == '-') {
neg = 1;
} else {
int a = x - '0';
if (neg) {
a = -a;
}
printf("%d", a);
if (neg) {
break;
}
x = getchar();
}

getchar() reads a single character at a time. You will get '5', '4', '2', and '-'.
isdigit(x) doesn't work for the '-', so the loop terminates there.

What about this:
#include <stdio.h>
int main(int argc, char *argv[])
{
char x = getchar();
int a;
while (x != '\n')
{
if (isdigit(x))
{
a = x - '0';
printf("%d,", a);
}
else
printf("%c", x);
x = getchar();
}
printf("\n");
return 0;
}

Related

How to test input is sane

Consider the following simple C program.
//C test
#include<stdio.h>
int main()
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
How do you check the values entered are actually two integers in some sensible range? Currently, if you just enter "a" and then return you get the output "Sum of entered numbers = 32767".
Examples of incorrect input I would like to prevent.
2 3 4 (wrong number of numbers)
apple (not a number)
11111111111111111111111111 1111111111111111111111111111111111111 (numbers out of range)
Or should I be using fgets and sscanf or even strtol ?
User input is evil. Parse per:
(optional whitespace)[decimal int][whitespace][decimal int](optional whitespace)
strtol() and family have better error handling than scanf().
Coda: Best to handle user input in a helper function. Break into 2 parts: I/O and parsing.
#include <ctype.h>
#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
// return 1 (success), -1 (EOF/IOError) or 0 (conversion failure)
int Readint(const char *prompt, int *dest, size_t n) {
char buf[n * 21 * 2]; // big enough for `n` 64-bit int and then 2x
fputs(prompt, stdout); // do not use printf here to avoid UB
fflush(stdout); // per #OP suggestion
if (fgets(buf, sizeof buf, stdin) == NULL) {
return -1;
}
const char *p = buf;
while (n-- > 0) {
char *endptr;
errno = 0;
long l = strtol(p, &endptr, 10);
if (errno || (p == endptr) || (l < INT_MIN) || (l > INT_MAX)) {
return 0;
}
*dest++ = (int) l;
p = endptr;
}
// Trailing whitespace OK
while (isspace((unsigned char) *p)) p++;
// Still more text
if (*p) return 0;
return 1;
}
int main() { // for testing
int Result;
do {
int dest[2] = { -1 };
Result = Readint("Enter two numbers to add\n", dest, 2);
printf("%d %d %d\n", Result, dest[0], dest[1]);
} while (Result >= 0);
return 0;
}
You can use like:
if( scanf("%d%d",&a,&b) == 2)
{
//two integer values has been read successfully
//do your stuff here
}
else
{
//Wrong input
}
Also you can do this to prevent anything after second number
int a,b;
char c;
if( scanf("%d%d%c", &a, &b, &c) == 3) {
if (c == '\n') {
puts("good");
}
} else {
puts("bad");
}
return 0;
}
You can use the following macro
#define SCAN_ONEENTRY_WITHCHECK(FORM,X,COND) \
do {\
char tmp;\
while(((scanf(" "FORM"%c",X,&tmp)!=2 || !isspace(tmp)) && !scanf("%*[^\n]"))\
|| !(COND)) {\
printf("Invalid input, please enter again: ");\
}\
} while(0)
and you call it in this way in the main
int main()
{
int a, b, c;
printf("Input first integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&a,(a>=0 && a<=10));
printf("Input second integer, valid choice between 0 and 10: ");
SCAN_ONEENTRY_WITHCHECK("%d",&b,(b>=0 && b<=10));
c = a + b;
printf("Sum of entered numbers = %d\n",c);
return 0;
}
for more detail concerning this macro please refer to: Common macro to read input data and check its validity
A simple way would be,
int a=0, b=0, c=0;
initialise them to 0
Additionally, the check suggested by Midhun is good to check if there are two inputs.
you can test this one.
#include <stdio.h>
int main(void)
{
int a, b, c;
printf("Enter two numbers to add\n");
scanf("%d%d",&a,&b);
if(scanf("%d%d",&a,&b) == 2)
{
c = a + b;
printf("Sum of entered numbers = %d\n",c);
}
return 0;
}

Convert to negative integer by reading characters

This is a program which reads data character by character until it finds a character digit and converts it into an integer.
#include <stdio.h>
int main(void) {
char ch = getchar();
printf("Type some data including a number");
while(ch < '0' || ch > '9') //as long as the character is not a digit.
{
ch = getchar();
}
int num = 0;
while(ch >= '0' && ch <= '9') //as long as we get a digit
{
num = num * 10 + ch - '0'; //convert char digit to integer
ch = getchar();
}
printf("Number is %d\n",num);
}
This program only finds positive integers. I want the program to find negative integers aswell or floating point number. How do i make the program to do that? I tried using if statement inside the while loop that looks for a digit but that didnt work for me.
It appears as though fscanf will be a better solution
E.g
#include <stdio.h>
#include <ctype.h>
int main(void) {
//input format ([^0-9]*-)?[0-9]+
int ch, sign = 1;
while(!isdigit(ch=getchar())){
if(ch=='-'){
ch=getchar();//one character look-ahead
if(isdigit(ch)){
sign = -1;
}
ungetc(ch, stdin);//push back
}
}
int num;
for(num=0;isdigit(ch);ch = getchar()){
num = num * 10 + ch - '0';
}
num *= sign;
printf("Number is %d\n",num);
return 0;
}

How to extract numbers from string in c?

Say I have a string like ab234cid*(s349*(20kd and I want to extract all the numbers 234, 349, 20, what should I do ?
You can do it with strtol, like this:
char *str = "ab234cid*(s349*(20kd", *p = str;
while (*p) { // While there are more characters to process...
if ( isdigit(*p) || ( (*p=='-'||*p=='+') && isdigit(*(p+1)) )) {
// Found a number
long val = strtol(p, &p, 10); // Read number
printf("%ld\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
p++;
}
}
Link to ideone.
A possible solution using sscanf() and scan sets:
const char* s = "ab234cid*(s349*(20kd";
int i1, i2, i3;
if (3 == sscanf(s,
"%*[^0123456789]%d%*[^0123456789]%d%*[^0123456789]%d",
&i1,
&i2,
&i3))
{
printf("%d %d %d\n", i1, i2, i3);
}
where %*[^0123456789] means ignore input until a digit is found. See demo at http://ideone.com/2hB4UW .
Or, if the number of numbers is unknown you can use %n specifier to record the last position read in the buffer:
const char* s = "ab234cid*(s349*(20kd";
int total_n = 0;
int n;
int i;
while (1 == sscanf(s + total_n, "%*[^0123456789]%d%n", &i, &n))
{
total_n += n;
printf("%d\n", i);
}
here after a simple solution using sscanf:
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char str[256]="ab234cid*(s349*(20kd";
char tmp[256];
int main()
{
int x;
tmp[0]='\0';
while (sscanf(str,"%[^0123456789]%s",tmp,str)>1||sscanf(str,"%d%s",&x,str))
{
if (tmp[0]=='\0')
{
printf("%d\r\n",x);
}
tmp[0]='\0';
}
}
Make a state machine that operates on one basic principle: is the current character a number.
When transitioning from non-digit to digit, you initialize your current_number := number.
when transitioning from digit to digit, you "shift" the new digit in:
current_number := current_number * 10 + number;
when transitioning from digit to non-digit, you output the current_number
when from non-digit to non-digit, you do nothing.
Optimizations are possible.
If the numbers are seprated by whitespace in the string then you can use sscanf(). Since, it's not the case with your example,
you have to do it yourself:
char tmp[256];
for(i=0;str[i];i++)
{
j=0;
while(str[i]>='0' && str[i]<='9')
{
tmp[j]=str[i];
i++;
j++;
}
tmp[j]=0;
printf("%ld", strtol(tmp, &tmp, 10));
// Or store in an integer array
}
#include<stdio.h>
#include<ctype.h>
#include<stdlib.h>
void main(int argc,char *argv[])
{
char *str ="ab234cid*(s349*(20kd", *ptr = str;
while (*ptr) { // While there are more characters to process...
if ( isdigit(*ptr) ) {
// Found a number
int val = (int)strtol(ptr,&ptr, 10); // Read number
printf("%d\n", val); // and print it.
} else {
// Otherwise, move on to the next character.
ptr++;
}
}
}
Or you can make a simple function like this:
// Provided 'c' is only a numeric character
int parseInt (char c) {
return c - '0';
}

Not getting correct variable assignment from getchar in C

I'm writing a simple calculation program, however the only string handling functions I can use are getchar and putchar. Right now I'm just trying to assign the numbers from input to variables, but when I print the variable it's some random number. For example, I entered 3 into the console and the output was 505110. Any help would be appreciated. Thank you.
#include <stdio.h>
#include "math.h"
int addFunction( int, int);
int subtractFunction(int, int);
int multiplyFunction(int, int);
int modulusFunction(int, int);
float divideFunction(float, float);
int main(int argc, const char * argv[])
{
int iochar = 0;
char num1 = 0, num2 = 0, continuePrompt, operator = 0;
do {
iochar = getchar();
getchar();
if ((iochar >= 0) && (iochar <= 20000)) {
num1 = iochar;
}
if ((iochar == '+') || (iochar == '-') || (iochar == '*') || (iochar == '/') || ( iochar == '%')) {
operator = iochar;
}
if ((num1 >= 0) || ((iochar >= 0) && (iochar <= 20000))){
num2 = iochar;
}
switch (operator) {
case '+':
iochar = addFunction(num1, num2);
break;
case '-':
iochar = subtractFunction(num1, num2);
break;
case '*':
iochar = multiplyFunction(num1, num2);
break;
case '%':
iochar = modulusFunction(num1, num2);
break;
case '/':
iochar = divideFunction(num1, num2);
break;
}
putchar(iochar);
printf("Would you like to make another calulation? (y or n)");
scanf("%c", &continuePrompt);
} while (continuePrompt != 'n');
return 0;
}
int addFunction(int x, int y){
return x + y;
}
int subtractFunction(int x, int y){
return x - y;
}
int multiplyFunction(int x, int y){
return x * y;
}
int modulusFunction(int x, int y){
return x % y;
}
float divideFunction(float x, float y){
return x / y;
}
The code is working exactly correct. When you enter a "3" in ASCII that's really the hex value 0x33, you're printing the value in dec (%d) thus you'll see a 51 on the output.
Now you're failing to consume the newline character that was entered, so getchar() is skipping the input on the second pass and is assuming you passed in a '\n' ASCII, which is hex 0xa and thus 10 is printed next.
You don't print any newlines or spaces so on the output you'll see:
3 (I entered that)
5110 (the output from '3''\n')
To fix the main problem, consume the new line character:
int main(int argc, const char * argv[]) {
int iochar, num1, num2;
char continuePrompt = 0, operator;
do {
iochar = getchar(); // Get input from user
getchar(); //Consume new line character
When you're printing the values, you're going to get ASCII values back, so if you want the dec, you're good, if you want it in character:
printf("%c", num1);
if you wanted it in hex (0x??)
printf("%#x", num1);
Also I'd print a new line or spaces or something more helpful then just a string of output to help find problems like this.
Finally this condtion:
while (continuePrompt != 'no');
Is wrong. That can't happen, check against 'n', you can't have 'no' in a single character.
Use %c instead of %d
i.e.
printf("%c", num1);
Also,you should initialize the variables.
i.e
int iochar=0, num1=0, num2=0;
char continuePrompt = 0, operator=0;
Since you're only allowed to use putchar and getchar, I assume that you're not allowed to use printf in order to present the result. In order to use an actual number with putchar you'll have to take each digit and transform it to the correct ASCII value.
Fortunately this is very simple, since
digitRepresentationASCIIValue == singleDigitValue + '0';
However, this will only work on a single digit. So you'll have to get the length of a number and use putchar for each digit. This is very simple:
void putNumber(int num){
int order = 1; // even zero has at least one digit
int tmp = num; // even zero has at least one digit
while(tmp /= 10)
order *= 10; // count digits
if(num < 0)
putchar('-'); // sign
while(order > 0){
// put a single digit, see above how to calculate the ASCII value
putchar('0' + ( ( num / order ) % 10));
order /= 10;
}
}
In order to actually read values you would have to do the exact opposite: check whether the character provided by getchar is a digit, and modify your current number:
int num[2] = {0,0};
int currentNum = 0;
int iochar = getchar();
while(!isNewline(iochar) && iochar != EOF){
if(isDigit(iochar)){
num[currentNum] = num[currentNum] * 10 + iochar - '0';
}
else if(isOperator(iochar)){
if(currentNum == 1)
num[0] = operate(num[0],num[1],operator);
else
currentNum = 1;
operator = iochar;
num[1] = 0;
}
iochar = getchar();
}
isDigit, isNewline and isOperand are left for exercise, all three are very simple but they will give you a better idea of ASCII values. operate contains your switch statement.
Note that I used int num[2] = {0,0};. This enables (in addition to currentNum) to write something like
3 + 3 + 3 / 9
Note that all operators are evaluated from left to right, as such the result of the example above will be 1 and not 6.3333333.
Exercises:
Don't publish your solution here, but do them for yourself as they should help you to improve your ASCII/char skills. For some exercises an ASCII table might be helpful.
Explain why the digit representation is so simple. Hint: Where and in which order are numbers defined in ASCII? What happens if you increase the value of a char?
Implement the missing isDigit, isNewline and isOperand.
The code for the input isn't commented, especially this line is missing a comment:
num[currentNum] = num[currentNum] * 10 + iochar - '0';
What exactly happens there? If num[currentNum] is too complicated for you at the moment just use num1 and print the value before you read the second one. Hint: Have a look at exercise #1.
Even if the operators would be evaluated in the right order (multiplication before addition), the result wouldn't be 6.333333 but 6. Why is that? What would you have to change in your current program?
First, you need to cast the input from "getchar", since it is an ascii input.
iochar = atoi(getchar());
then you can compare it against an integer value.
To start with, return value of getchar is char, promoted to int. So, please use an char variable to store it.
Secondly, to convert the input char to int, use something like:
int num1 = iochar - '0';

A basic/ manual way to check that a value entered by the user is numeric

I've searched in and out of these forums but am still having trouble. My understanding of C is still very basic. I'm creating a small program that takes 3 numerical values entered by the user and then calculates the highest. I nailed that.
I now want to ensure that the user enters only integer values. I managed to get the prog to keep prompting the user to re-enter the value until it is within the specified numerical range (for example, any number between 1 and 1000 inclusive, piece of cake) but that's not good enough. I used 3 while loops to test each value, but this only works as long as the input is of type integer.
The trick is I cant use built in functions. It needs to be manual (sorry, poor choice of words) I tried to use char variables and x = getchar(); to get the ASCII value and test it in a condition but I can't get it working in a loop. (while/ do-while)
I also tried using a "for loop" and array variables but once again am struggling to get it to keep prompting the user.
I've also tried to test the value returned by scanf to see if its integer but my knowledge level of correct C syntax is level: noob. Either my loops don't loop or they loop infinitely.
Here is some sample code:
int x, y, z =0;
printf("Enter the first number:\n");
scanf("d", &x);
while (condition) /* Here is where I need to determine that the entered val is false */
{
printf("Wrong input. Re-enter a valid value.\n");
x =0;
scanf("%d", &x); /*user re-prompted */
}
I'm getting the idea that I'll have to use ASCII and a loop, but I just can't get to it. Also, the values entered get sent to a function for comparing and are then returned.
Could someone give me some advice and a few tips please?
Much thanks
You would have to use something like fgets, and strtol:
long someValue;
char *bufEnd = NULL;
char buf[128]; // max line size
do {
printf("enter a value: ");
fgets(buf, 128, stdin);
someValue = strtol(buf, &bufEnd, 10); // base 10
} while (bufEnd == buf || *bufEnd != '\n');
printf("got value: %li", someValue);
What we are doing here is we are tapping into strtol's capability to tell us where it stopped parsing, by passing in bufEnd.
Then, we are making sure that bufEnd doesn't point to the beginning of buf (in which case, it didn't start with a number), and also checking to make sure that bufEnd points to \n, or the end of the line (making sure that the user didn't enter something like 123abc, which strtol would interpret as 123). You may wish to trim buf of whitespace characters first, however.
You're absolutely on the right track with "scanf()". Just check the return value. If you don't get the expected #/values, then you got invalid input:
char found = FALSE;
int ival;
double x;
while (!found)
{
printf("Please enter a valid integer: ");
if (scanf("%d", &ival) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
printf("Please enter a valid floating point number: ");
if (scanf("%lf", &x) !=1) {
printf ("Invalid! Please re-enter!\n");
continue;
}
found = TRUE;
}
Here's my solution. It safe against buffer overflow and straightforward .
#include <stdio.h>
#define LEN 10
int main() {
int a;
char str[LEN];
fgets( str, LEN, stdin );
while ( !sscanf( str, "%d", &a ) )
fgets( str, 10, stdin );
printf("Num is : %d\n", a);
return 0;
}
#include <stdio.h>
#include <limits.h>
#include <ctype.h>
int getInteger(int* err){
int ch;
int n;//int32
int takeNum, sign;
long long int wk;//long long int as int64
wk=0LL;
*err = 0;
takeNum = 0;//flag
sign = 1;//minus:-1, other:1
/* //skip space character
while(EOF!=(ch=getchar()) && (ch == ' ' || ch == '\t' || ch == '\n'));
ungetc(ch, stdin);
*/
while(EOF!=(ch=getchar())){
if(ch == '-'){
if(takeNum != 0){//in input number
*err = 1;
break;
}
if(sign == -1){//already sign
*err = 2;
break;
}
sign = -1;
continue;
}
if(ch >= '0' && ch <= '9'){//isdigit(ch) in ctype.h
if(takeNum == 0)
takeNum = 1;
wk = wk * 10 + (ch - '0')*sign;
if(INT_MAX < wk || INT_MIN > wk){//overflow
*err = 3;
break;
}
continue;
}
if(ch != '\n'){//input other [-0-9]
*err = 4;
}
break;
}
if(takeNum == 0){//not input number
*err = 5;
} else {
n=wk;
}
while(ch != '\n' && EOF!=(ch=getchar()));//skip to newline
return n;
}
int getValue(const char* redoprompt, int low, int high){
int num, err=0;
while(1){
num = getInteger(&err);
if(err || low > num || high < num)
printf("%s", redoprompt);
else
break;
}
return num;
}
#define max(x,y) ((x)>(y))? (x) : (y)
int main(){
const char *error_message = "Wrong input. Re-enter a valid value.\n";
int x, y, z, max;
x = getValue(error_message, 1, 1000);
y = getValue(error_message, 1, 1000);
z = getValue(error_message, 1, 1000);
max = max(max(x,y), z);
printf("max:%d\n", max);
return 0;
}

Resources