Unit conversion from user's file entered in command prompt - c

In my C programming class we are supposed to write a program that is able to perform unit conversion. This is to be done by taking a filename and the desired conversion from the user, opening the file, identifying the conversion factors within the file, closing the file, and displaying the final conversion.
Here is the sample file lengths that the instructor provided:
INCH 0.0254
FOOT 0.3048
YARD 0.9144
MILE 1609.344
MM 1e-3
CM 1e-2
METER 1
KM 1e3
AU 149597870700.0
Here is sample output that we need to replicate exactly:
% c11 -Wall units.c -o u
% ./u lengths 12 inch foot
12.00 inch is 1.00 foot.
% ./u lengths 30 inch foot
30.00 inch is 2.50 foot.
% ./u lengths 1 foot inch
1.00 foot is 12.00 inch.
% ./u lengths 1 inch foot
1.00 inch is 0.08 foot.
% ./u lengths 1 au mile
1.00 au is 92955807.27 mile.
% ./u lengths 1000 meter km
1000.00 meter is 1.00 km.
% ./u lengths 1 inch mile
1.00 inch is 0.00 mile.
% ./u
usage: ./u <unitfile> <amount> <from> <to>
% ./u lengthz 1 inch foot
./u: can’t open file lengthz
% ./u lengths 1 inch feet
./u: no such unit "feet"
What libraries must I include in order to make this program work? What is the best way to take input from the user in this situation?
Update:
After a bit of trial and error, I was able to get my program to take the command line arguments. Here is what I have so far:
#include <stdio.h>
#include <stdlib.h>
// Function to take file name from the user input
int main(int argc, char* argv[])
{
if (argc != 5)
{
printf("usage: %s filename\n", argv[0]);
}
else
{
FILE *file = fopen(argv[1], "r");
if (file == 0)
{
printf("can't open file %s\n", argv[1]);
}
else
{
int x;
while ((x = fgetc(file)) != EOF)
{
printf("%c", x);
}
fclose(file);
}
}
}
Unfortunately, this only prints the contents of the file assuming that the program gets 5 command line arguments.

Related

Shipping calculator not returning correct results

The assignment is to write a shipping calculator using the following information.
Packages above 50 pounds will not be shipped. You need to write a program in C that calculates the shipping charge.
The shipping rates are based on per 500 miles shipped. They are not pro-rated, i.e., 600 miles is the same rate as 900 miles or 1000 miles.
Here are the shipping charges -
Package Weight Rate per 500 miles shipped
Less than or equal to 10 pounds $3.00
More than 10 pounds but less than or equal to 50 pounds $5.00
If the shipping distance is more than 1000 miles, there is an additional charge of $10 per package shipped.
I originally started writing the program using double but wanted to used a trick I had seen on here to always force the program to round up for the shipping charges by adding 499 to distance then dividing by 500.
#include <stdio.h>
#include <stdlib.h>
int main()
{
int Shipping, packageWeight, packageDistance, packagePrice;
printf("Enter the weight of the package: \n");
scanf("%d", &packageWeight);
printf("The weight you have entered is %.2d\n", packageWeight);
if (packageWeight <= 10 )
Shipping = 3.00;
if (packageWeight <= 50 && packageWeight > 10 )
Shipping = 5.00;
if (packageWeight > 50.0) {
puts("Sorry, we only ship packages of 50 pounds or less.");
return 0;
}
printf("How far are you sending the package? \n");
scanf("%d", &packageDistance);
printf("The distance you entered is %.2d\n", packageDistance);
if (packageDistance <= 1000){
packagePrice = (packageDistance + 499 / 500) * Shipping;
printf("The shipping charge is %.2d \n", packagePrice);
system("pause");
}
if (packageDistance > 1000) {
packagePrice = (packageDistance + 499 / 500) * Shipping + 10.00;
printf("The shipping charge is %.2d \n", packagePrice);
system("PAUSE");
}
}
With a weight of 10 and distance of 501 the output should be a shipping charge of 6 but was 1503
Based on a a weight of 20 and a distance of 1001 the program should output a shipping charge of 25 but was 5000
You have mess with integers / doubles, output, expressions, etc.
Let me show you why you get 1503:
if (packageDistance <= 1000){
packagePrice = (packageDistance + 499 / 500) * Shipping;
printf("The shipping charge is %.2d \n", packagePrice);
system("pause");
}
Your packageDistance is 501 then if statement is true and you get inside.
Then you setup package price. First you get packageDistance which is 501. Then you add it with 499/500 which is 0 since 499 < 500 and you attempt to get integer part of division (as per C/C++ standard). The sum of 501 and 0 is 501.
Now, you multiply it with Shipping. The value you set is 3.0, but smart C convert it to integer 3. 501 * 3 is 1503 and you get the result.
Finally, you try to sent output as %.2d. This is nonsense and I am surprised C shows something at all, but I believe it just see d and ignores .2
This is what you have to do:
Understand your business logic (you do)
Be careful with integers and floating point numbers, read C documentation or send questions here if you do not understand something.
Make sure you use brackets when needed: a + b / c is not the same as (a + b) / c
Make sure you do not use integer division if you mean to use "regular" division.
Make sure you use %d for integers and %.2f for floating point numbers when appropriate.

Reading into an array from a txt file

So, I'm trying to get my program to read into an array of structs from a text file, and it compiles okay, but doesnt appear to actually be reading in the values?.. and I have no idea why. This is the relevant part of the code:
typedef struct Planet
{
char Planet_Name[30];
double Fuel;
double Velocity;
double Height;
double Gravity;
int Maximum_Thrust;
double Difficulty;
}Planet;
//read the Planets from a file
FILE* inputFile = fopen("Planets.txt", "r");
if(inputFile == NULL)
{
perror("Error. File unavailable");
exit(1);
}
for(j=0; j<10; j++)
{
fscanf("%29s %lf %lf %lf %lf %d %lf", SolarSystem[j].Planet_Name,
SolarSystem[j].Fuel, SolarSystem[j].Velocity,
SolarSystem[j].Height, SolarSystem[j].Gravity,
SolarSystem[j].Maximum_Thrust, SolarSystem[j].Difficulty);
}
printf("Please select a planet by entering the corresponding number:
Mercury[0], Venus[1], Earth[2], Moon[3], Mars[4], Jupiter[5], Saturn[6],
Uranus[7], Neptune[8]\n");
scanf("%d",&PlanetNum);
printf("You have chosen %s", SolarSystem[PlanetNum].Planet_Name);
This is the txt file (Title: Planets.txt)
Mercury 120 50 500 12.1 30 2
Venus 120 50 500 29.1 30 6
Earth 120 50 500 32.2 30 7
Moon 120 15 50 5.3 30 2
Mars 120 50 500 12.2 30 4
Jupiter 120 50 500 81.3 30 10
Saturn 120 50 500 34.3 30 8
Uranus 120 50 500 28.5 30 5
Neptune 120 50 500 36.6 30 9
Pluto 120 50 500 2.03 30 1
Except when it runs that final printf, it doesn't actually print anything, nor does it store any data in the structs (when its called later it's all zeroes).
Ideas?
The mistake is with your fscanf function . You have to provide FILE pointer (inputFile This context) as first argument and & operator(address of Similar to scanf function) in front of scanning integer and float.
Try this modified fscanf code :-
fscanf(inputFile,"%s%lf%lf%lf%lf%d%lf",SolarSystem[j].Planet_Name,&SolarSystem[j].Fuel, &SolarSystem[j].Velocity, &SolarSystem[j].Height, &SolarSystem[j].Gravity,&SolarSystem[j].Maximum_Thrust, &SolarSystem[j].Difficulty);

Unknown test case error in C program

This a question I have to submit for an assignment, hence it has to be evaluated online. My program is running correctly for 6 out of 7 test cases. Only 3 test cases are provided and they are as shown:
Sports or Economy Car
Help Mr.Kamath to check whether his vehicle is an economy car or not. The program should display “There is a gas hog” if the mileage is less than or equal to 15 Km and the program should display “It is an economy car” if the mileage is not less than 30 Km. Otherwise display "Fuel Economy". Write a C program to get the values of a Car variables from the user. Create a structure called Car. Order of the input values entered should be according to the structure variables
struct Car{
float startKm;
float endKm;
float litres;
};
Test Case
Input 1
30
50
5
Output 1
There is a gas hog
Input 2
40.5
80.5
1.5
Output 2
Fuel Economy
Input 3
30
0
5
Output 3
You have entered 0
My code:
#include<stdio.h>
struct Car
{
float startKm;
float endKm;
float litres;
};
int main()
{
struct Car c;
float m;
scanf("%f",&c.startKm);
scanf("%f",&c.endKm);
scanf("%f",&c.litres);
m=(c.endKm-c.startKm)/c.litres;
if(c.startKm<=0||c.endKm<=0||c.litres<=0)
{
printf("You have entered 0"); return 0;
}
else if(m<=15)
{
printf("There is a gas hog");
}
else if(m>=30)
{
printf("It is an economy car");
}
else
{
printf("Fuel Economy");
}
return 0;
}
These are the test cases(unknown):
These is my evaluation output:
PS: I am facing similar problems in many such programs with several test cases.
I also asked a similar question Cannot identify error with code, failing a test case
It would be helpful if someone suggests how to approach such unknown test cases.
If I'm not mistaken you should be able to start from 0 km. I went ahead and tried my own test case:
Starting km 0, Ending km 25, Liters used 1
if(c.startKm < 0 || c.endKm <= c.startKm || c.litres <= 0)

How to round float numbers in text in C?

So I have this text
today average human lifespan in Western countries is approaching and exceeding 80 years.
1 Japan 82.6 123 19
2 Hong Kong 82.2 234 411
3 Iceland 81.8 345 26
4 Switzerland 81.7 456 7
5 Australia 81.2 567 500
...
80 Lithuania 73.0 800 2
...
194 Swaziland 39.6 142 212
195 133714 18.0 133 998
196 100110011 10.0 667 87351
I need to round the float numbers in this text to whole numbers. I've searched a lot of forums but I cannot seem to find what I need.
This text is given in a .txt file. My task: "Round real number(that have decimals) to whole numbers. The corrected text should be in a new .txt" That's it.
scanf and sscanf are your best friend to extract anything of a string.
floor is use full to suppress decimal on a float. Then can be used to round it (to use it include math.h)...
The format string describes the expected format.The function return the number of parameters found.
Sample:
Initialization
int id = -1;
char country[160]; /* /!\ Warning country name length shall be fewer than 160 */
/* Scanf don't care of this array parameter length. If it is too short */
/* It will erase following memory... */
/* That is why scanf are often disparaging */
float percent = 0.0;
char a_number_as_string[10];
int other_number = -1;
char* Switzerland = "4 Switzerland 81.7654321 456 7";
effectif code
int ret = sscanf(Switzerland, "%d %s %f %s %d", &id, country,
&percent, a_number_as_string, &other_number);
if(ret == 5) {
printf("~~ id: %d\n\tcountry: %s\n\tpercent: %.2f\n\tand : "
"(%s, %d)\n", id, country, percent, a_number_as_string,
other_number);
/////// ROUND
printf("*** round");
printf("\twith printf %%.1f = %.1f\n", percent);
printf("\twith printf %%.2f = %.2f\n", percent);
printf("\twith printf %%.3f = %.3f\n", percent);
printf("\twith printf %%.4f = %.4f\n", percent);
printf("*** With floor (included in math.h)\n");
printf("\t1 decimal: %f\n", floor(percent*10)/10);
printf("\t2 decimal: %f\n", floor(percent*100)/100);
printf("\t3 decimal: %f\n", floor(percent*1000)/1000);
printf("\t4 decimal: %f\n", floor(percent*10000)/10000);
} else {
printf("--> ret = %d", ret);
}
output
~~ id: 4
country: Switzerland
percent: 81.70
and : (456, 7)
*** round
with printf %.1f = 81.8
with printf %.2f = 81.77
with printf %.3f = 81.765
with printf %.4f = 81.7654
*** With floor (included in math.h)
1 decimal: 81.700000
2 decimal: 81.760000
3 decimal: 81.765000
4 decimal: 81.765400
This function are describe in Unix, OSX, Unix terminal man pages:
man scanf
man sscanf
man floor
Or you can find it on several copies of this manages on the web for example
scanf
sscanf
floor
here is the program I have already tested it for a single line of input string:-
// LINK - http://stackoverflow.com/questions/40317323/how-to-extract-float-numbers-from-text-in-c#40317323
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main()
{
char s[100];
int i,j;
double sum=0.0,frac=0.0;
gets(s); // delimited by '\n' and not by ' '
for( i=0;s[i]!='\0';i++) // for finding index value of decimal point(.)
{
if(s[i]=='.')
break;
}
for(;s[i]!=' ';i--); // for changing key index value to the index value of the first space character(' ') before the decimal point(.)
i++;
for(i;s[i]!='.';i++)
{
sum=sum*10+(s[i]-48); // For extracting integer part
}
i++;
for(i,j=1;s[i]!=' ';i++,j++)
{
frac=frac+(s[i]-48)/pow(10,j); // For extracting fractional part
}
printf("\n\n%lf",sum+frac); // final answer integer part+decimal part
return 0;
}
Explanation:-
okay so what I did is:-
Since scanf() is automatically delimited by space I used gets() which is delimited by new line;
Then we know that there will be a decimal point(.) for floating number in the string, so we find the index value(say key) of the decimal point in the array.
Once we have found the decimal point we know there will only be numbers between the decimal point and the space character after the country name so now we find the index value of that space(key).
Now from that key value we again first move to the decimal point(.) character index while calculating the integer part.Calculated using ASCII value i.e. ASCII value of character Zero(0) is 48 and character Nine(9) is 57 hence subtracting 48 from every character and extracting the value.
Again from the Decimal point(.) to the next space character in the string is part of the floating number and after decimal the numbers follow the weight 10^(-1),10^(-2),10^(-3)...and so on hence the temporary variable and the power() function.Thus we, successfully calculated the fractional part also.
Finally, I just added the Integer and the fractional parts within the printf().
Try, using printf() with all the variables in each of the for loops for better understanding, kinda like dry-run.
You can parse all the values from the string using regex in c#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Data;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string[] input = {
"today average human lifespan in Western countries is approaching and exceeding 80 years.",
"1 Japan 82.6 123 19",
"2 Hong Kong 82.2 234 411",
"3 Iceland 81.8 345 26",
"4 Switzerland 81.7 456 7",
"5 Australia 81.2 567 500",
"80 Lithuania 73.0 800 2",
"194 Swaziland 39.6 142 212",
"195 133714 18.0 133 998",
"196 100110011 10.0 667 87351"
};
string pattern = #"(?'index'\d+)\s+(?'country'.*)\s+(?'float'[^ ]+)\s+(?'num1'\d+)\s+(?'num2'\d+)$";
for (int i = 1; i < input.Length; i++)
{
Match match = Regex.Match(input[i], pattern);
Console.WriteLine("index : '{0}', country : '{1}', float : '{2}', num1 : '{3}', num2 : '{4}'",
match.Groups["index"],
match.Groups["country"],
match.Groups["float"],
match.Groups["num1"],
match.Groups["num2"]
);
}
Console.ReadLine();
}
}
}

values changed by fscanf and fprintf for text file in C program [duplicate]

This question already has answers here:
What range of numbers can be represented in a 16-, 32- and 64-bit IEEE-754 systems?
(7 answers)
Closed 6 years ago.
I would like to output like "correct output data" from "input data" by below C program. But the result shows that the values are changed like "actual output data". Let me know how to solve it.
input data
-5190.978 -90026.901 158.677 15 90 81 58
-5165.821 -90011.875 152.742 15 90 89 54
-5158.762 -90010.093 148.083 31 80 82 42
correct output data
-5190.978 -90026.901 158.677 90 81 58
-5165.821 -90011.875 152.742 90 89 54
-5158.762 -90010.093 148.083 80 82 42
actual output data
-5190.978 -90026.898 158.677 90 81 58
-5165.821 -90011.875 152.742 90 89 54
-5158.762 -90010.094 148.083 80 82 42
/***************************************************************************:::
xyz(ref)rgb2xyzrgb
19/08/2016
ver1.1 2009/3/7
*******************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
int main(int argc,char *argv[])
{
FILE *fpr,*fpw;
int ref,r,g,b;
float x,y,z;
float n_x,n_y,n_z;
/*****************************************************
2.command line arguments processing
*******************************************************/
if(argc!=3)
{
fprintf(stderr,"Usage: %s (1)input_org.txt\n(2)write_xyz FILENAME\n",argv[0]);
exit(1);
}
printf("OPEN FILE NAME:%s\n",argv[1]);
/**********************************************************************************
**********************************************************************************
4. FILE OPEN + Binary File Input
**********************************************************************************
*************************************************************************************/
// open input file
if((fpr=fopen(argv[1],"rt"))==NULL)
{
printf("file cannot be opened。\n");
exit(1);
}
//write file
if((fpw=fopen(argv[2],"wt"))==NULL)
{
fprintf(stderr,"DSM by GSI data.raw\n");
exit(1);
}
while (fscanf(fpr,"%f %f %f %d %d %d %d", &x,&y,&z,&ref,&r,&g,&b) != EOF)
{
//printf("%.3f %.3f %.3f %d %d %d\n",x,y,z,r,g,b);
n_x = roundf(x * 1000) / 1000;
n_y = roundf(y * 1000) / 1000;
n_z = roundf(z * 1000) / 1000;
//printf("%.3f %.3f %.3f %d %d %d\n",n_x,n_y,n_z,r,g,b);
fprintf(fpw,"%.3f %.3f %.3f %d %d %d\n",n_x,n_y,n_z,r,g,b);
//printf("x:%f y:%f z:%f\n", x,y,z);
}
fclose(fpr);
fclose(fpw);
}
Instead of -90026.901 computer stores the nearest number that fits the precision. It's 90026.898. Remember that numbers are stored in binary on computers and 901/1000 doesn't have finite binary form. For this reason, some of the precision will be cut.
It would be the same if you tried to print 1/3. It won't print all the digits, but you actually expect it as you're used to decimal system. In binary system, some of the fractions that have finite decimal form won't have one.
The solution? Always try to enlarge macheps which is the arithmetic precision. The easiest would be to use double instead of float. It still doesn't give 100% but it's more probable that will work.
The topic is known as scientific calculation and is pain in a** for programmers.

Resources