Reading character-by-character - always reaching an invalid character - c

I'm new to C and to the programming world. I've been requested to get a reversed number in base 20 and print out his conversion to decimal.
I know it's not the most efficient code out there, but that's the best I managed to do with my current knowledge.
When I run this program and input a number, I'm always getting the default case...
What am I missing?
Thank you :)
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int main() {
char x;
int exponent= 1;
int sum = 0;
int flag = 0;
printf("Enter a reversed number is base 20\n");
scanf(" %c", &x);
while (x != "\n") {
switch (x) {
case '0':sum += 0;
break;
case '1':sum += 1 * exponent;
break;
case '2': sum += 2 * exponent;
break;
case '3':sum += 3 * exponent;
break;
case '4':sum += 4 * exponent;
break;
case '5':sum += 5 * exponent;
break;
case '6':sum += 6 * exponent;
break;
case '7':sum += 7 * exponent;
break;
case '8':sum += 8 * exponent;
break;
case '9':sum += 9 * exponent;
break;
case 'A':
case 'a': sum += 10 * exponent;
break;
case 'B':
case 'b':sum += 11 * exponent;
break;
case 'C':
case 'c' : sum += 12 * exponent;
break;
case 'D':
case 'd': sum += 13 * exponent;
break;
case 'E':
case 'e': sum += 14 * exponent;
break;
case 'F':
case 'f': sum += 15 * exponent;
break;
case 'G':
case 'g': sum += 16 * exponent;
break;
case 'H':
case 'h': sum += 17 * exponent;
break;
case 'I':
case 'i': sum += 18 * exponent;
break;
case 'J':
case 'j': sum += 19 * exponent;
break;
default:flag++;
break;
}
if (flag == 1) {
printf("Error! %c is not a valid digit in base 20", x);
break;
}
else {
exponent *= 20;;
scanf("%c", &x);
}
}
if (flag == 1)
return 0;
else
printf(sum);
return 0;
}

You should really read your compiler's warnings...:
<source>: In function 'main':
<source>:10:14: warning: comparison between pointer and integer
10 | while (x != "\n") {
| ^~
<source>:10:14: warning: comparison with string literal results in unspecified behavior [-Waddress]
<source>:77:16: warning: passing argument 1 of 'printf' makes pointer from integer without a cast [-Wint-conversion]
77 | printf(sum);
| ^~~
| |
| int
In file included from <source>:2:
/usr/include/stdio.h:332:43: note: expected 'const char * restrict' but argument is of type 'int'
332 | extern int printf (const char *__restrict __format, ...);
| ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~
You're comparing x to a an address - the address of the string constant "\n" (that is located in some section of your program's memory space). You probably meant to compare x to '\n'.
Also, the printf() function takes a format string before the argument, so it should be printf("%d\n", sum); (to also print a newline character).
PS 1: Always compile your code with more warnings turned on, e.g. gcc -W -Wall (and perhaps other warning flags) for a better chance catch these kinds of typos and minor errors.
PS 2: As #Jabberwocky notes, your program could be made much shorter (with no loss of readability); and, on the other hand, you should always check the return value of scanf() and similar functions which may fail due to user input:
#include <stdio.h>
#include <stdlib.h>
int main() {
char x;
int exponent = 1;
int sum = 0;
int num_scanned;
printf("Enter a reversed number is base 20\n");
num_scanned = scanf(" %c", &x);
if (num_scanned != 1) {
fprintf(stderr, "Invalid input\n");
exit(EXIT_FAILURE);
}
while (x != '\n') {
int digit;
if (x >= '0' && x <= '9') { digit = x-'0'; }
else if (x >= 'a' && x <= 'j') { digit = x-'a'; }
else if (x >= 'A' && x <= 'J') { digit = x-'A'; }
else {
fprintf(stderr, "%c is not a valid digit in base 20.", x);
exit(EXIT_FAILURE);
}
sum += digit * exponent;
exponent *= 20;
num_scanned = scanf("%c", &x);
if (num_scanned != 1) {
fprintf(stderr, "Invalid input\n");
exit(EXIT_FAILURE);
}
}
printf("%d\n",sum);
return EXIT_SUCCESS;
}

Related

How to turn integers into string in c programming? (eg. 0 => zero)

How to turn integers into string in c programming? (eg. 0 => zero)
Code Example:
https://onlinegdb.com/BygYM1L9V
#include <stdio.h>
#include <stdbool.h>
int main(int argc, const char * argv[]) {
int input, number, right_digit;
bool isNegative = false;
printf("Insert a number:\n ");
scanf("%d", &input);
// if keyed-in number is negative, make it positive, but remember it was negative
if ( input < 0 ) {
input = input;
isNegative = true;
}
if (isNegative == true){
printf("negative ");
}
number = 0;
// reversing the digits of input and store in number
while ( input ) {
// adds the last digit of input to value from right
number = 10 * number + input % 10;
input /= 10;
}
do {
right_digit = number % 10;
switch (right_digit) {
case 0:
printf("zero ");
break;
case 1:
printf("one ");
break;
case 2:
printf("two ");
break;
case 3:
printf("three ");
break;
case 4:
printf("four ");
break;
case 5:
printf("five ");
break;
case 6:
printf("six ");
break;
case 7:
printf("seven ");
break;
case 8:
printf("eight ");
break;
case 9:
printf("nine ");
break;
}
number = number / 10;
} while (number != 0 );
printf("\n");
return 0;
}
Expected result for entering 1230 is one two three zero.
However, this code provides 123 and omits the 0. How do I turn integers into strings?
However, is there a better way of doing it? Is there any other method? C coders, please help
I'd drop the switch for a look-up table. Regarding numbers having to be parsed with % operator "backwards" from ls digit and up, simply store them digit by digit in a separate temporary array to easily re-order them.
void stringify (unsigned int n)
{
const char* LOOKUP_TABLE [10] =
{
"zero", "one", "two", "three", "four",
"five", "six", "seven", "eight", "nine",
};
if(n == 0)
{
puts(LOOKUP_TABLE[0]);
return ;
}
int numbers[10]={0}; // assuming UINT_MAX = 4.29 billion = 10 digits
for(int i=0; i<10; i++)
{
numbers[10-i-1] = n%10;
n/=10;
}
bool remove_zeroes = true;
for(int i=0; i<10; i++)
{
if(!remove_zeroes || numbers[i]!=0)
{
remove_zeroes = false;
printf("%s ", LOOKUP_TABLE[numbers[i]]);
}
}
}
Out of your problem a typo in your code : input = input; must be input = -input;
It is easier to work on the number as a string, example :
#include <stdio.h>
int main() {
printf("Insert a number:\n ");
char s[32];
if (fscanf(stdin, "%31s", s) != 1) {
return -1;
}
char * p = s;
if (*p == '-') {
printf("negative ");
p += 1;
}
for (;;) {
switch (*p++) {
case 0:
case '\n':
if ((*s == '-') && (p == (s+2))) {
puts("missing number");
return -1;
}
putchar('\n');
return 0;
case '0':
printf("zero ");
break;
case '1':
printf("one ");
break;
case '2':
printf("two ");
break;
case '3':
printf("three ");
break;
case '4':
printf("four ");
break;
case '5':
printf("five ");
break;
case '6':
printf("six ");
break;
case '7':
printf("seven ");
break;
case '8':
printf("eight ");
break;
case '9':
printf("nine ");
break;
default:
puts(" invalid number");
return -1;
}
}
}
Compilation and executions :
/tmp % gcc -pedantic -Wall -Wextra n.c
vxl15036 /tmp % ./a.out
Insert a number:
0
zero
vxl15036 /tmp % ./a.out
Insert a number:
-1
negative one
vxl15036 /tmp % ./a.out
Insert a number:
12305
one two three zero five
vxl15036 /tmp % ./a.out
Insert a number:
007
zero zero seven
vxl15036 /tmp % ./a.out
Insert a number:
-
negative missing number
vxl15036 /tmp % ./a.out
Insert a number:
a
invalid number
As you see the number is rewritten as it was enter, 0 at left are not removed and -0 is negative zero
It can be fun to write one thousand two hundred thirty four for 1234 ;-)
I made a small change to your program so that it loops through once before to get the number of digits, and then loops through count times for the switch statement.
#include <stdio.h>
#include <stdbool.h>
int main(int argc, const char * argv[]) {
int input, number, right_digit;
bool isNegative = false;
printf("Insert a number:\n ");
scanf("%d", &input);
// if keyed-in number is negative, make it positive, but remember it was negative
if ( input < 0 ) {
input = -input;
isNegative = true;
}
if (isNegative == true){
printf("negative ");
}
int count = 0;
int n = input;
//count the digits
while(n != 0)
{
n /= 10;
++count;
}
number = 0;
// reversing the digits of input and store in number
while ( input ) {
// adds the last digit of input to value from right
number = 10 * number + input % 10;
input /= 10;
}
for(int i = 0; i < count; i++) {
right_digit = number % 10;
switch (right_digit) {
case 0:
printf("zero ");
break;
case 1:
printf("one ");
break;
case 2:
printf("two ");
break;
case 3:
printf("three ");
break;
case 4:
printf("four ");
break;
case 5:
printf("five ");
break;
case 6:
printf("six ");
break;
case 7:
printf("seven ");
break;
case 8:
printf("eight ");
break;
case 9:
printf("nine ");
break;
}
number = number / 10;
}
printf("\n");
return 0;
}
I think you use similar logic as this example integrated into your loop, but when you reverse the number the 0's get treated like leading 0's and are ignored. I didn't make any changes to the inside of the loop so that may need to be cleaned up.
test input:
12345000
output:
one two three four five zero zero zero

A simple “printing” calculator

When I'm typing in a digit I see
Type in a digit 1
Type in an operator ERROR: Unknown operator!
accumulator = 0.000000
Type in a digit
Why step - printf("Type in an operator ") is skipped and is replaced by - default:
printf ("ERROR: Unknown operator!\n");
break;
Thanks for the help in advance!
// Program to produce a simple printing calculator
#include <stdio.h>
#include <stdbool.h>
int main (void)
{
double accumulator = 0.0, number; // The accumulator shall be 0 at startup
char operator;
bool isCalculating = true; // Set flag indicating that calculations are ongoing
printf("You can use 4 operator for arithmetic + - / *\n");
printf("To set accumulator to some number use operator S or s\n");
printf("To exit from this program use operator E or e\n");
printf ("Begin Calculations\n");
while (isCalculating) // The loop ends when operator is = 'E'
{
printf("Type in a digit ");
scanf ("%lf", &number); // Get input from the user.
printf("Type in an operator ");
scanf ("%c", &operator);
// The conditions and their associated calculations
switch (operator)
{
case '+':
accumulator += number;
break;
case '-':
accumulator -= number;
break;
case '*':
accumulator *= number;
break;
case '/':
if (number == 0)
printf ("ERROR: Division by 0 is not allowed!");
else
accumulator /= number;
break;
case 'S':
case 's':
accumulator = number;
break;
case 'E':
case 'e':
isCalculating = false;
break;
default:
printf ("ERROR: Unknown operator!\n");
break;
}
printf ("accumulator = %f\n", accumulator);
}
printf ("End of Calculations");
return 0;
}
scanf for a char consumes the newline characters. So the scanned char is "linefeed" instead of the one you're expecting.
I replaced:
scanf ("%c", &operator);
by
scanf ("%*c%c", &operator);
(consuming linefeed before the operator without assigning it using %*c format)
and your code worked fine.

Suprisingly small limits of the calculator written in C

My task is to write a calculator, which accepts only valid operands, that is, * / + - ^. The calculator has to evaluate (check the validity) of the line being entered. For example, it accepts only lines of the following form: 20 + 9, 8 ^ 2, etc. If someone entered 9y, 20+2 or exit, the expression would be evaluated to 0. Then the user has to have the possibility of displaying lines, which were entered, regardless of their validity. (Switch E for invalid lines, switch V for valid lines, if valid line is entered and V is chosen it also displays the value of an expression).
Let's now consider the example in order to see how it works.
Line: 20 + 20
Switch: E
Output: There's nothing wrong with the line 20 + 20.
Switch: V
Output: The result is 40.
Line: 20r
Switch: E:
Output: The line is 20r
Switch: V:
Output: The line 20r is invalid.
The problem:
Every time I enter a line, which would have the result of calculation more then, I guess 7000 (it doesn't work for 8 * 900), it doesn't even allow me to choose the char for the switch. It displays the line Choose E for... and then automatically You haven't chosen the valid option of the switch..
MAIN.C:
#include "stdio.h"
#include "evalexpression.h"
int main() {
char string[100];
int result;
result = InterCalc(string);
CalcFilter(result, string);
return 0;
}
EVALEXPRESSION.C
#include "stdio.h"
#include "string.h"
#include "evalexpression.h"
#include "math.h"
#include "float.h"
static float f1, f2;
static char op;
int isValidExpression(const char *str) {
int res;
char ops[10];
res=sscanf(str, "%f %s %f", &f1, ops, &f2);
if (res==3) {
if (ops[0]=='+' || ops[0]=='-' || ops[0]=='^' || ops[0]=='*' || ops[0]=='/') {
op=ops[0];
return 1;
}
else
return 0;
}
else
return 0;
}
int getOperator() {
if (op=='+')
return 1;
else if (op=='-')
return 2;
else if (op=='/')
return 3;
else if (op=='*')
return 4;
else if (op=='^')
return 5;
else return 0;
}
float getFstOperand() {
return(f1);
}
float getSecOperand() {
return(f2);
}
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
if (strcmp(my_string, "exit\n")==0 ) {
printf("Program ended\n");
return 0;
}
else if ( isValidExpression(my_string) == 0 ) {
printf("Expression error\n");
return 0;
}
else
return 1;
}
float getExprValue() {
int operation;
operation = getOperator();
switch (operation) {
case 1:
return (getFstOperand() + getSecOperand());
break;
case 2:
return (getFstOperand() - getSecOperand());
break;
case 3:
return (getFstOperand() / getSecOperand());
break;
case 4:
return (getFstOperand() * getSecOperand());
break;
case 5:
return ( pow(getFstOperand(), getSecOperand()) );
break;
default:
return 0;
}
}
void CalcFilter(int a, char *str) {
float calculation_value;
printf("Press 'E' to display the invalid line or press 'V' to display the valid line\n");
int choice;
choice = getchar();
switch (choice) {
case 'E':
case 'e':
if (a==0)
printf("The line %s is invalid.\n", str);
else if (a==1)
printf("There's nothing wrong with the line %s\n", str);
break;
case 'V':
case 'v':
if (a==1) {
calculation_value = getExprValue();
//if (calculation_value > FLT_MAX || calculation_value < FLT_MIN)
// printf("The value of expression is beyond limits\n");
//else
printf("The result of %s is %f.\n", str, calculation_value); }
if (a==0)
printf("The line %s is invalid\n", str);
break;
default:
printf("You haven't chosen the valid option of the switch\n");
break;
}
}
Look at the first lines of your InterCalc() function
int InterCalc(char *my_string) {
fgets(my_string, sizeof(my_string), stdin);
sizeof is a compile-time operator. sizeof(my_string) is the size of a pointer to char which for a 32 bit system is typically 4 bytes.
sizeof does not give the length of whatever string my_string points at. It will not give 100 (the length of the array in main()).
You will need to pass the value 100 (or whatever the size is in main() if you change it) by some other means, such as an extra function parameter.

Program that displays each digit on an integer in english doesn't work with an integer beginning with "0"

I have an assignment were I have to write a program that takes an integer keyed in from the terminal and extracts and displays each digit of the integer in English. I'm not able to use arrays or recursion, we're just starting with programming.
For example:
"123" returns "one two three"
My program is working well (for the most part), but the problem is that when you enter something like "0123" in the terminal the program returns "eight three"... WTH??
This is my code:
// Program that takes an integer and displays each digit in English
#include <stdio.h>
int main (void)
{
int num, digit;
int reversed = 0, backupZero = 0;
printf("Please enter an integer:\n");
scanf("%i", &num);
if (num == 0) // In case the input is just "0"
{
printf("zero");
}
while (num > 0) // Loop to reverse the integer
{
digit = num % 10;
reversed = (reversed * 10) + digit;
if ((reversed == 0) && (digit == 0)) // If the integer finishes in zero
{
++backupZero; // Use this to add extra zeroes later
}
num /= 10;
}
while (reversed > 0)
{
digit = reversed % 10;
reversed /= 10;
switch (digit)
{
case 1:
printf("one ");
break;
case 2:
printf("two ");
break;
case 3:
printf("three ");
break;
case 4:
printf("four ");
break;
case 5:
printf("five ");
break;
case 6:
printf("six ");
break;
case 7:
printf("seven ");
break;
case 8:
printf("eight ");
break;
case 9:
printf("nine ");
break;
default:
printf("zero ");
break;
}
}
for (int counter = 0; counter < backupZero; ++counter) // Prints the extra zeroes at the end
{
printf("zero ");
--backupZero;
}
printf("\n");
return 0;
}
Probably is something on the mathematics, I admit I'm not good at it.
When you read in the number with
scanf("%i", &num);
You are letting scanf infer the base of the number. Numbers starting with 0 followed by other digits are interpreted as octal. So 0123 is not the same as 123. It is in fact, 83.
0100 = 64
020 = 16
03 = 3
---------
0123 = 83
To read the number as base 10, use
scanf("%d", &num);
If you want to handle numbers that start with '0', then I suggest that you read the user input as a string (array of characters) rather than as an integer.
In addition to that, instead of "doing a switch" on each character, you can use a simple array in order to map the correct word to each digit.
Here is one way for implementing it:
#include <stdio.h>
#define MAX_INPUT_LEN 100
const char* digits[] = {"zero","one","two" ,"three","four",
"five","six","seven","eight","nine"};
int main()
{
int i;
char format[10];
char str[MAX_INPUT_LEN+1];
sprintf(format,"%c%us",'%',MAX_INPUT_LEN); // now format = "%100s"
scanf(format,str); // will write into str at most 100 characters
for (i=0; str[i]!=0; i++)
{
if ('0' <= str[i] && str[i] <= '9')
printf("%s ",digits[str[i]-'0']);
else
printf("invalid character ");
}
return 0;
}
Oh, wow. It took me 3 or 4 hours to write following code. I'm into c only first week, so please be considerate.
Update: added working minus + some comments.
#include <stdio.h>
#include <math.h>
int main(void)
{
int num, count, user, out;
count = 0;
printf("Type in any int: ");
scanf("%d", &num);
// adding minus to the beginning if int is negative
if (num < 0)
{
num = -num;
printf("minus ");
}
user = num;
// creating a power to the future number
while (num != 0)
{
num = num / 10;
count++;
}
int i2;
i2 = count;
// main calculations: dividing by (10 to the power of counter) and subtracting from the initial number
for (int i = 0; i < i2; i++)
{
out = user / pow(10, count - 1);
user = user - out * pow(10, count - 1);
count--;
switch (out)
{
case 1:
printf("one ");
break;
case 2:
printf("two ");
break;
case 3:
printf("three ");
break;
case 4:
printf("four ");
break;
case 5:
printf("five ");
break;
case 6:
printf("six ");
break;
case 7:
printf("seven ");
break;
case 8:
printf("eight ");
break;
case 9:
printf("nine ");
break;
case 0:
printf("zero ");
break;
default:
break;
}
}
printf("\n");
return 0;
}
There are some mistakes:
if ((reversed == 0) && (digit == 0)) (incorrect)
if ((reversed == 0) || (digit == 0)) (correct)
And in the last loop you should remove
--backupZero;
And code will read numbers better

C - Issue converting a user generated number into words

So I've been working my way through Kochan's Programming in C and I've hit a snag on one of the questions which reads as follows:
"Write a program that takes an integer keyed in from the terminal and extracts and displays each digit of the integer in English. So if the user types in 932, the program should display the following: nine three two (Remember to display zero if the user types in just 0.)"
I had managed to get the program to print out the digits as words but unfortunately in reverse order. From there I thought it might be a good idea to reverse the number so to speak, but now when I run that value through my program only prints out "one one one ...." for how ever many digits long the number I enter in.
In other words, originally I managed to display 932 as "two three nine", but when I tried to reverse the number and run 239 through my program I only get "one one one".
If any one has any hints that could point me in the right direction it would be very much appreciated! My code is below:
#include <stdio.h>
int digitCount (int);
int reverseNumber (int);
int main(void)
{
//Chapter 6 Problem 6
int x, numberValue;
printf("Enter the number you'd like converted to words\n");
scanf("%i", &x);
numberValue = reverseNumber(x);
printf("The reverse is %i\n", numberValue);
do {
numberValue = numberValue % 10;
switch (numberValue) {
case 0:
printf("zero\t");
break;
case 1:
printf("one\t");
break;
case 2:
printf("two\t");
break;
case 3:
printf("three\t");
break;
case 4:
printf("four\t");
break;
case 5:
printf("five\t");
break;
case 6:
printf("six\t");
break;
case 7:
printf("seven\t");
break;
case 8:
printf("eight\t");
break;
case 9:
printf("nine\t");
break;
default:
break;
}
x = x / 10;
} while (x != 0);
return 0;
}
int digitCount (int u)
{
int cnt = 0;
do {
u = u / 10;
cnt++;
} while (u != 0);
return cnt;
}
int reverseNumber (int y)
{
int cnt, Rev;
cnt = digitCount(y); //returns number of digits
while (cnt != 0) {
Rev = Rev * 10 + y % 10;
y = y / 10;
cnt--;
}
return Rev;
}
In your reverseNumber function you have not initialized Rev. Make Rev=0
int reverseNumber (int y)
{
int cnt, Rev=0;
cnt = digitCount(y); //returns number of digits
printf("Digit count %d\n", cnt);
while (cnt != 0) {
Rev = Rev * 10 + y % 10;
y = y / 10;
cnt--;
}
return Rev;
}
In main in the do while loop use a temporary variable since you are overwriting numberValue with numberValue % 10. But the most ironic part in your program (where you complicated everything for yourself) is that there is no need to reverse the number at all. See the code here
In the way user entered - http://ideone.com/pORaP2
In reverse order - http://ideone.com/5GS8al
When you find modulo you get the number in the reverse order itself. Suppose you entered 234
First step 234%10 gives 4 prints four. And then makes 234 to 23
Second step 23%10 gives 3 prints three. And then makes 23 to 2
and then finally prints two.
Consider what the primary problem is you are dealing with, you need to process the left most digit first, then the next to the right, then the next. But the math of using modulus and division goes from right to left. So what you need is some way to either save the math processing and reverse, or have the output be delayed. Two options are available.
For an iterative approach you could utilize a FIFO queue type approach that holds the results of each digit and then prints out the queue. Could be as simple as an array with indexing:
int main(void) {
int x, i;
int result[32]; //arbitrary size
int index = 0;
printf("Enter the number you'd like converted to words\n");
scanf("%i", &x);
do {
results[index++] = x % 10;
x = x / 10;
} while( index < 32 && x != 0 );
//now print in reverse order
for(i = index-1; i >= 0; i--) {
switch (results[i]) {
case 0:
printf("zero\t");
break;
case 1:
printf("one\t");
break;
case 2:
printf("two\t");
break;
case 3:
printf("three\t");
break;
case 4:
printf("four\t");
break;
case 5:
printf("five\t");
break;
case 6:
printf("six\t");
break;
case 7:
printf("seven\t");
break;
case 8:
printf("eight\t");
break;
case 9:
printf("nine\t");
break;
default:
break;
}
}
}
There is second approach that works which is recursive. Here you delay the printing of the output until you reach the left most digit. The built in stack is used for by the recursive calls.
void printNumbers(int x);
int main(void) {
int x;
printf("Enter the number you'd like converted to words\n");
scanf("%i", &x);
printNumbers(x);
}
void printNumbers(int v) {
if( v > 9 ) {
printNumbers( v / 10 );
}
switch (v%10) {
case 0:
printf("zero\t");
break;
case 1:
printf("one\t");
break;
case 2:
printf("two\t");
break;
case 3:
printf("three\t");
break;
case 4:
printf("four\t");
break;
case 5:
printf("five\t");
break;
case 6:
printf("six\t");
break;
case 7:
printf("seven\t");
break;
case 8:
printf("eight\t");
break;
case 9:
printf("nine\t");
break;
default:
break;
}
}
Both approaches will solve the problem, but not if the input is a negative number.
My simple answer:
void printNum(int x)
{
static const char * const num[] = {
"zero ", "one ", "two " , "three ", "four ",
"five ", "six ", "seven ", "eight ", "nine "
};
if (x < 10) {
printf(num[x]);
return;
}
printNum(x / 10);
printNum(x % 10);
}

Resources