Got an segment error and not sure what causes it - c

#include <stdio.h>
int main () {
int vIn_a, vIn_b, vIn_c;
char vOperator;
printf("Please enter a number\n");
scanf("%d", vIn_a);
printf("Please enter a number\n");
scanf("%d", vIn_b);
printf("Please enter a Operator\n");
scanf("%c", vOperator);
switch(vOperator){
case '+':
vIn_c = (vIn_a + vIn_b);
break;
case '-':
vIn_c = (vIn_a - vIn_b);
break;
case '/':
vIn_c = (vIn_a / vIn_b);
break;
case '*':
vIn_c = (vIn_a * vIn_b);
break;
}
printf("Result: %d %c %d = %d", vIn_a, vOperator, vIn_b, vIn_c);
return 0;
}
Just trying to figure this out, i ran gdb. But not sure what my debugger is telling me at this point. Maybe im overlooking it?
Debugger: Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7c60d36 in ?? () from /usr/lib/libc.so.6
So what is causing this segmentation fault guys? Im learning C and im lost.
Thanks in advance.

When you use scanf(), you don't pass the variable into which you want to store the value, you pass a pointer to the variable.
So, for instance, instead of scanf("%d", vIn_a);, you need scanf("%d", &vIn_a); - note the '&'!
The effect of the scanf() calls, as you wrote them, was to pass an arbitrary number (whatever random content was in the uninitialised vIn_a and vIn_b) into scanf(). It treated those random(ish) integer values as pointers. So when it wrote the user-contributed value into the "pointer" it has been passed, it had the effect of:
*(int *)vIn_a = user_entered_value;
If you know your way around pointers, you'll know this is a recipe for disaster!
There are two more gotchas:
Your '/' operator doesn't check whether its divisor (vIn_b) is zero, so it would be easy to crash with a divide-by-zero error if the user selected zero for vIn_b and '/' for the operator.
You don't have a default: clause in your switch statement, so if the user types something other than the operator characters you're checking for, vIn_c will contain random rubbish as it's uninitialised by the time it's printed.

You can use scanf function with &. For example; scanf("%d", &vIn_a);
For documentation : https://cplusplus.com/reference/cstdio/scanf/

Related

Switch function directly goes to default. What's the issue?

I am new to C and am writing a simple code of converting temperatures. The code is still incomplete but still should give me some output
#include<stdio.h>
void main()
{
float temp;
char choice;
printf("\n 1. Celcius to Farenhite\n 2. Farenhite to Celcius\n What do you want to convert from? : ");
scanf("%c", &choice);
switch (choice)
{
case 1:
printf("Enter temperature in Celcius: ", temp );
scanf("%f", &temp);
break;
case 2:
printf("Enter temperature in Farenhite: ", temp);
scanf("%f", &temp);
break;
default:
printf("Invalid Choice");
break;
}
}
When I run this it asks "what do you want to convert from?" and shows the options. But when I enter 1 or 2, it directly prints and shows "Invalid Choice".
Pls tell me what's wrong :(
1 is 'int' and not a char.
1 and '1' are different.
This is the edited code
#include<stdio.h>
void main()
{
float temp;
char choice;
printf("\n 1. Celcius to Farenhite\n 2. Farenhite to Celcius\n What do you want to convert from? : ");
scanf("%c", &choice);
switch (choice)
{
case '1':
printf("Enter temperature in Celcius: ", temp );
scanf("%f", &temp);
break;
case '2':
printf("Enter temperature in Farenhite: ", temp);
scanf("%f", &temp);
break;
default:
printf("Invalid Choice");
break;
}
}
The number one is not the same as the digit "1". You are entering the character "1" and your switch statement is checking for the number one.
The number one is how many hearts I have. It can be written with the digit '1' but any number of other ways.
The digit '1' is a character. It is sometimes use to represent the number one but can also be used for other things. A variable of type char can hold the digit 1 since digits are characters.
Your switch statement is checking for the number one. You want to check for the character 1.
'1' is a character, whereas 1 is an integer. Your switch statement can't find a case to match with, hence it goes to default.
Is that the complete code? You're not converting anything here, you're only asking the user for the temperature and storing it in a variable.
OT: Indent properly, your code is messy and difficult to read. And do not use scanf for taking input. You may want to check out this link http://sekrit.de/webdocs/c/beginners-guide-away-from-scanf.html.
This is a common misunderstanding for novices and occasional typo for experienced programmers(*).
1 means "the integer value one" (it is the integer literal for the value of 1).
Assuming your on an ASCII compatible platform(**) that is the character with ASCII code 1 (the non-printing character called Start of Header - SOH).
The ASCII Code for the character 1 is actually 49. But you should write:
case '1':
Because those apostrophes identify the 1 as the character representing 1 not the numeric value of 1.
The compiler will interpret '1' as actually meaning character of 1 meaning the (codepoint) value of 49.
In C char has a deeply dual role as a numeric type and as the smallest unit of text and accidental mixing of those roles causes endless confusion.
Arguably char has 3 roles. The smallest arithmetic type, the smallest unit of text (a character) and the unit of addressable memory (byte).
There are historical reasons why those roles are conflated in C.
(*) But I can't find a good answer for it even though there should be thousands of times this has been asked.
(**) C does not specify a character set but if you working on a platform that isn't ASCII compatible you will know about it. Unless you've found something in your Grandparent's basement and they're sadly not around to explain it. This footnote exists for the likely comments to the effect that C doesn't specify a character set.
Your program reads a byte from stdin and compares that to the values 1 and 2. It is unlikely the user can type these byte values as they correspond to control characters CtrlA and CtrlB1. The byte values representing the digits 1 and 2 typed by the user are noted in C as '1' and '2'. These are called character constants and are int values for the encoding of the corresponding characters.
Furthermore, you should:
indent your code more consistently.
define main with a return type int
test the return value of scanf()
fix the spelling of Fahrenheit, named after German physicist Daniel Gabriel Fahrenheit and Celsius, named after Swedish astronomer Anders Celsius.
1: From a unix terminal, one can actually enter these byte values by hitting CtrlV CtrlA and CtrlV CtrlB, respectively, followed by Enter.
Here is a modified version:
#include <stdio.h>
int main() {
float temp;
char choice;
printf(" 1. Celsius to Fahrenheit\n"
" 2. Fahrenheit to Celsius\n"
" What do you want to convert from? ");
if (scanf(" %c", &choice) != 1)
return 1;
switch (choice) {
case '1':
printf("Enter temperature in Celsius: ", temp);
if (scanf("%f", &temp) != 1)
return 1;
printf("%g degrees Celsius is %g degrees Fahrenheit\n",
temp, 32 + temp * 9 / 5);
break;
case '2':
printf("Enter temperature in Fahrenheit: ", temp);
if (scanf("%f", &temp) != 1)
return 1;
printf("%g degrees Fahrenheit is %g degrees Celsius\n",
temp, (temp - 32) * 5 / 9);
break;
default:
printf("Invalid choice\n");
break;
}
return 0;
}

My program topped working when I enter a number

I used to compile in VSCode with mingw-64 in Windows 10.
Please rectify my errors.
[1]: https://i.stack.imgur.com/j5CKZ.jpg [
#include <stdio.h>
int main() {
float rupees,result;
int choice;
printf("Enter 1 for USD\n");
printf("Enter 2 for EUR\n");
printf("Enter 3 for AUS\n");
printf("Enter 4 for UAE Dirham\n");
printf("Enter amount in Rupees\n");
scanf("%d",&rupees);
printf("Enter your choice\n");
scanf("%d",choice);
switch (choice)
{
case 1:
result=rupees*73.04 ;
break;
printf("%f Amount equal to %f USD\n",rupees,result);
case 2:
result=rupees*88.82 ;
printf("%f Amount equal to %f EUR\n",rupees,result);
break;
case 3:
result=rupees*56.36 ;
printf("%f Amount equal to %f AUS\n",rupees,result);
break;
case 4:
result=rupees*19.89 ;
printf("%f Amount equal to %f Dirham\n",rupees,result);
break;
default:
printf("Enter correct choice");
break;
}
return 0;
}
Firstly, Let me try to review your thought process before getting onto the code.
You declared and read variables to store the value in rupees, the user choice and the conversion result.
You wrote a switch case to activate a particular block of code based on user choice and in a default case, you wrote a "printf" statement to convey to the user that the choice was invalid.
However, the program is tainted and below are the reasons why:
The Logic is invalid, as per your program, 1 rupee must be equivalent to 73.04 USD, 88.82 EUR,56.36 AUS and 19.89 Dirham accordingly which is a falsity. The vice versa is true! 1 USD=73.04 Rupees and so on. Quick Fix would be to replace "*" operator with "/" operator at every switch case.
You cannot actually read a fractional value for rupees using the above code as the placeholder for a float data-type in C is "%f" and not "%d".
In the line where you wanted to read the user choice, you did not use the Address-Of Operator(&) i.e you did not give the address location into which the value is to be read, you gave the identifier itself.
In the first switch case, you placed the break statement before the "printf" statement. Which would mean that you would break the control flow even before you would print something on your console.
In a default case, you asked the user to enter a valid choice but the problem is that the control terminates thereafter leaving no scope to re-enter the choice. A quick fix to this is to put the switch case within a loop or alternatively, just display an error message stating "Invalid Choice". (Note that such issues are called semantic errors where the structure of the program is valid as per the language rules but the overall logic and flow of the application is inconsistent).
Miscellaneously, there are some message-format errors that could be made better.
Ex: You don't have to ask to enter his/her choice given that you prior mentioned "Enter 1 for USD.....2 for EUR.....". Also, you could probably replace Amount with Rupees while printing the end-result to make the output more elegant and clear.
Last but not the least, the flow of your code is not so appropriate. Initially you display the entire catalogue to the user to choose from and then you ask the user to enter the value in rupees(you could ask the user to enter the rupee value irrespective of his conversion scale). By slightly rearranging the code, the usability of your script increases.
Want to look at Rectified Code? Here you go!
Rectified Code:
#include <stdio.h>
int main()
{
float rupees,result;
int choice;
printf("Enter amount in Rupees\n");
scanf("%f",&rupees);
printf("Enter 1 for USD\n");
printf("Enter 2 for EUR\n");
printf("Enter 3 for AUS\n");
printf("Enter 4 for UAE Dirham\n");
scanf("%d",&choice);
switch (choice)
{
case 1:
result=rupees/73.04 ;
printf("%f Rupees is equivalent to %f USD\n",rupees,result);
break;
case 2:
result=rupees/88.82 ;
printf("%f Rupees is equivalent to %f EUR\n",rupees,result);
break;
case 3:
result=rupees/56.36 ;
printf("%f Rupees is equivalent to %f AUS\n",rupees,result);
break;
case 4:
result=rupees/19.89 ;
printf("%f Rupees is equivalent to %f Dirham\n",rupees,result);
break;
default:
printf("That was an Invalid Choice!");
break;
}
return 0;
}

Getting zero answer while using DO-WHILE loop

I tried to calculate the tot(total fee) in the do-while loop, but all I get is tot=0.00?! Why is this happening? And after that I get a message: it said the variable fee is not being initialised?
#include<stdio.h>
int main(void)
{
int cofno;
float tot=0.0;
float fee;
char option;
do{
printf("Enter cofno: ");
scanf("%d",&cofno);
if(cofno>0)
{
printf("Key in (h/c): ");
scanf("%c",&option);
getchar();
switch(option)
{case 'h':fee=cofno*1.80;
break;
case 'c': fee=cofno*2.50;
break;
}
tot=tot+fee;
//the program will repeat until the user key in negative value or zero
}
}while(cofno>0);
printf("\ntot=RM%.2f \n\n",tot);
return 0;
}
scanf(" %c",&option); This will solve the problem for you. The reason the ' ' is provided in the scanf so that it can consume the white space characters.
What happened earlier was that your character input got the \n from previous input.
To check the thing that it inputted \n try outputting the option like this
printf("[%c]",option); you will see output
[
]
Also the break statement you provide is breaking for the case staement. Not the while loop. You have infinite loop now. You can solve this with a added condition.
...
tot=tot+fee;
if(option == 'c' || option =='h')
break;
...
Even more simply, you could have changed the while condition overall and make it like this
while(cofno<=0);
this conforms to your idea the program will repeat until the user key in negative value or zero more suitably.

integer input in switch case and user enter strings

I am writing code for my switch case. I am taking input from the user and printing the respective day based on the input. But my question is, if user is giving string input it is printing case 0 statement as output. Can anyone please correct this program?
#include<stdio.h>
int main(void){
int days;
scanf("%d",&days);
switch(days){
case 0: printf("Mon");break;
case 1: printf("Tue");break;
case 2: printf("Wed");break;
case 3: printf("Thu");break;
case 4: printf("Fri");break;
case 5: printf("Sat");break;
case 6: printf("Sun");break;
default: printf("Plz enter a valid day(0-6) :( ");
}
return 0;
}
My output printing is :
>>a.out
Naveen
mon
scanf won't modify your int if the format specifier isn't found in the input.
In this case, you're switching on an uninitialized int. Doing anything with uninitialized POD types is generally A Bad Thing™, so you should take care that your value is initialized properly.
In this case, since you want it to trigger the default branch, initializing as int days = -1; (or as anything not in [0,6]) should do the trick.
PS: Note that scanf also returns an int telling you how many arguments it successfully found. This means you can check if scanf returned either 0 or EOF and handle this case separately - for example a more descriptive error message.
loop until days was properly scanned
while(scanf("%d",&days) != 1) getc(stdin);

Why is the following program stuck in a loop?

I wrote a solution to an exercise that asks to write a program that acts as a simple "printing" calculator, and also detects division by zero and checks for unknown operators.
The program works as intended when expected operators are entered. For example:
"100 S" prints "= 100.000000"
"2 /" prints "= 50.000000"
"10 *" prints "= 500.000000"
It also detects division by zero and unknown operators.
However, when I enter operators in wrong order, like this:
"/ 2" or "* 10", the program is stuck in a loop.
How do I fix this bug so that when the operators are entered in wrong order, it just prints "Unknown operator"?
// Write a program that acts as a simple "printing" calculator
#include <stdio.h>
int main (void)
{
float acc, b;
char operator;
printf ("Begin Calculations\n");
while ( operator != 'E') {
scanf ("%f %c", &b, &operator);
switch (operator)
{
case 'S': // set accumulator
case 's':
acc = b;
printf ("= %f\n", acc);
break;
case 'E': // end program
case 'e':
printf ("= %f\nEnd of Calculations.\n", acc);
break;
case '+':
printf ("= %f\n", acc += b);
break;
case '-':
printf ("= %f\n", acc -= b);
break;
case '*':
printf ("= %f\n", acc *= b);
break;
case '/':
if ( b == 0 )
printf ("Can't divide by zero.\n");
else
printf ("= %f\n", acc /= b);
break;
default:
printf ("Unknown operator.\n");
break;
}
}
return 0;
}
Update: I've found a solution
while ( operator != 'E' && operator != 'e' ) {
if ( scanf ("%f %c", &b, &operator ) < 2 ) {
printf ("Error. You need to enter a number.\n");
break;
}
else {
switch (operator)...
The result of scanf is the number of fields assigned. If scanf returns 0, it will return 0 for the same format string every time you call it. Because scanf pushes back the last character it read that does not match the input sequence (%f), it will repeatedly try to convert the same string over and over.
That's why you loop infinitely. You might want to check the result of scanf. If it's less than 2, error out.
I think you would need to make your input routine more robust than scanf (apparently) is. For example, if you read your input in whole lines, you can parse them (say, using sscanf) to get the components w/o mucking up the input stream.
scanf is reading until it can parse a floating point number. Try using gets to read in a string and then parse that string from there.
http://www.cplusplus.com/reference/clibrary/cstdio/gets/
I guess that to exit you need to enter a float + 'E' (0.0 E) and not just 'E'. Would that be what you're asking about?
Ah! I see you mentioned placing things backward. Yes. scanf() is never going to detect that.
If you're under Linux, check out lex and yacc (or flex and bison to be precise.) To do things like these, it's a lot better and you can make things a lot better (support parenthesis, minus and plus operator, instead of just add and subtract, etc.)
It's not "stuck in a loop", it's waiting for the operator that this line:
scanf ("%f %c", &b, &operator);
promises. That line reads until it receives a floating-point number, and then it reads an operator. If you give it an operator first, it will simply ignore it.
(By the way, you should initialize operator to something specific before getting to the line while ( operator != 'E') {, because for all you know, operator might happen to start out as 'E'. Also, as Mysticial says, operator isn't a great name for a C identifier, because of its uses in C++.)
The problem is that scanf() is trying to read what you told it to, that is, a floating point number and a character. When you type the other way around scanf returns because its not the format you told it too, but unfortunately it WONT flush the buffer, so the while would go again and scanf tries to read again, and so on.
Drop scanf, although if this is only for a homework you may try doing:
if (!scanf ("%f %c", &b, &operator)) {
scanf ("%*[^\n]"); /* TRY to flush stdin */
printf("Incorrect input!");
incorrect_input++;
continue;
} else {
incorrect_input = 0;
}
if (incorrect_input > 5) {
break; /* Very simple measure to avoid getting stuck in the loop */
}
However, when I enter operators in wrong order, like this: "/ 2" or "* 10", the program is stuck in a loop.
How do I fix this bug so that when the operators are entered in wrong order, it just prints "Unknown operator"?
You might want to read the entire expression and then parse it for correctness. There are various expression notation methods (infix, postfix (also known as reverse polish notation) and prefix (otherwise known as polish notation)) which makes the task of validating and evaluating them easier.
Also if you have or can get hold of the "The C Programming Language" book written by Dennis Ritchie and Brian Kernighan, turn to chapter 4 and read the section that walks you through the design and implementation of a calculator program.

Resources