My assignment states
"The program is not allowed to show any menu: It must receive the option of the mathematical function to execute and its arguments as parameters in the main function."
and examples of execution of the program are (suppose the program is called c2):
./c2 fradd 2/3 5/7
# Expected output: 29/21
My understanding is that we have to write a function fFradd() outside of int main (int argc, char * argv[]). Then implement that function.
So my question is: How do I take the fractions given as arguments and split them into n1, d1, n2, d2?
I know (using the example given) that 2/3 would be saved into one space of the argv[] array (I'm not sure that's the proper terminology but hopefully you understand my point). I'm just not sure how to get the program to read that argument (argv[2]) and recognize 2/3 as n1/d1.
The closest I could find was using something like sscanf(argv[2],"%i/%i",n1,d1);, but I know sscanf is for strings...and obviously that can't be done with scanf()
You're 100% right, you should use sscanf().
Not sure what you mean by "sscanf() is for strings". It's for scanning a string, and converting parts of the string into other values of other types. Here, read the manual page one more time to refresh your idea of what the function is capable of doing.
Converting to integer is very common, and is done almost as you said. You must pass the address of the destination variable for each conversion though, so make it:
int n, d,
if(sscanf(argv[i], "%d/%d", &n, &d) == 2)
{
printf("got the fraction %d/%d\n", n, d);
}
the above should probably be put into a loop, as the argv[i] implies.
Related
While reading from a file in C, I was told that I can add an * after the % to disregard that input. For example:
fscanf(inputfile, "%lf %lf %*lf", &num1, &num2);
In this example the pointer reads three double values, but only two of them need to be stored (the ones without the * sign after the % sign).
Could someone explain how it works, because as far as I know the * sign is used to initialize or step into a pointer?
The use of * is just a string constant chosen arbitrarily. It has no relation to pointer dereferencing. How it "works" is that the parser in scanf simply parses the type as it would normally then throws away the value rather than looking for a parameter to put it in.
I have written a program that takes 2 arguments from the user and adds them together so for example if the user puts ./test 12 4 it will print out the sum is: 16.
the part that is confusing me is why do I have to use the atoi and I can't just use argv[1] + argv[2]
I know that atoi is used convert a string to an integer and I found this line of code online which helped me with my program but can someone explain to me why do I need it :
sum = atoi(argv[1])+atoi(argv[2]);
code:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int sum = 0;
sum = atoi(argv[1])+atoi(argv[2]);
printf("The sum is : %d \n", sum);
return 0;
}
The reason is the same thing as the difference between you and your name. The user typed "./test 12 4" so before your program ran, the command shell that the user is using prepared two sequences of numbers representing the text characters that form the names of the user's numbers and gave them to your program - the shell got those directly from the terminal where the user typed them.
In order to add the numbers that these sequences identify by name you need to use a function that converts those two names to int - a representation of the numbers that they identify for which addition is defined. This function is called 'atoi' and the two names were the sequences {49,50,0} and {52,0} (being representations of the symbol sequences {'1','2','\0'} and {'4', '\0'}). The 0 (also written '\0') is a code for a special symbol that can't be printed or typed directly (this is a lie but I don't want to get into that) and it's added to the end of the names so that atoi, as it reads the name character code by character code, knows when it reached the end. Note that these particular values depend on what platform you're using but I'm assuming it's a platform that uses ascii or utf-8 rather than something like ebcdic.
As part of printing the resulting number, printf uses the "%d" directive to accept the int way of representing the answer (which you got from adding two ints) and converts it back to to the name of the answer as character codes {49,56} ({'1','6'}) ready to send back to the terminal. I left out any possible terminating 0 ('\0') in the output codes just there because printf doesn't indicate an end here unlike the end indications you receive in the inputs from the shell - the terminal can't look for an end in the same way that atoi does and printf doesn't give you the name for further usage within the C program; it just sends the name right out of the program for display to the terminal (which is the place that the command shell hooked up to the program's output stream).
Although atoi isn't the only thing you could do with the incoming names for numbers, the C language has been designed to give the ending marker for each argv element because it will typically be needed for any alternative choices you might make for handling the incoming information.
Try this to see the codes being used explicitly (still assuming your system uses ascii or utf-8):
#include <stdio.h>
#include <stdlib.h>
char const name_of_program[] = "./test";
char const name_of_first_number[] = {49,50,0}; // {'1','2','\0'} would be the same as would "12" - with the quotes
char const name_of_second_number[] = {52,0}; // {'4','\0'} would be the same as would "4" - with the quotes
int main()
{
char const *argv[] = {
name_of_program,
name_of_first_number,
name_of_second_number,
NULL,
};
int sum = 0;
sum = atoi(argv[1])+atoi(argv[2]);
printf("The sum is : %d \n", sum);
return 0;
}
"the part that is confusing me is why do i have to use the "atoi" and i can't just use argv[1] + argv[2]"
The argv argument holds a list of strings that the program can take as input. The C language does not automatically convert strings to numbers, so you have to do that yourself. The atoi function takes a string as a parameter and returns an integer, which can then be used for the arithmetic operations you want.
In other languages such as C++, summing strings usually concatenates them, but in C you will get a compiler error.
Your argv[i] is type C string by default:
int main(int argc, char *argv[])
and sum is type int.
Even if you input a number it will be read as a char* by your compiler. atoi() makes it read as an int so you can do arithmetic calculations with it.
[Answer updated thanks to comments bellow]
Why do we pass the format specifiers to scanf( ) in C as its parameters?
I mean, can't we just do
scanf( &var ); // Here, var is any pre-declared variable.
the type of var can be fetched from its declaration. Why is this not allowed ?
I see the below code as a waste of memory.
scanf( "%d" , &var );
The type cannot be "fetched from it's declaration". There is nothing magical about scanf(), it's just a function. A function in C cannot access meta information about variables.
This is why, in general, function arguments are declared including their type. For variable-argument functions such as scanf(), the first argument is not optional and it is used to describe the number and type of the other arguments in some fashion chosen by the function itself.
You clearly need to read some book on C programming to get better understanding of the core concepts. Unlike some other languages, C doesn't have I/O mechanism baked into the language. scanf() is just a library function and as such, this function has no way to automagically know the type of the variable it is supposed to fill.
Because %d will simply specify what the type of var is, there is no memory wastage. scanf(&var) would not work because the function is not designed to accept arguments that way.
You know that variables in C can be of different types:
int: Integer
char: Character
float: Floating point number.
...
Unlike other languages, variable types cannot be implicitly inferred at compilation time in C. That is why you always declare the type of your variables ( Example: int a or char c).
Because scanf is just a function in C, and because functions in C should take parameters of a specific type, people who coded C decided to use the following format:
scanf("%d", &var) ; // for integers
scanf("%c", &var); //for chars
scanf("%f", &var); //for double and floats.
using %d or %c does not waste memory or whatsoever. you can think about it as a flag that specifies the type of the input variable.
Could the developers of C do it without %d, %c...etc? Yes they could, but then, they have to handle all possible exceptions that might arise from sending the wrong type.
Suppose the developers of C used just the following format
scanf(&var);
That is surly very concise, but then you will have to use the same syntax to send chars/int/double...etc, and then the function scanf has to figure out a way to decide about the type of the variable that was sent. Remember what I told you before? variable types CANNOT be implicitly inferred at compilation time, and thus, this task will be almost impossible.
They could however use a different scanf function for every type. For example:
scanfInt(&var); //for integers.
scanfFloat(&var); //for floats.
...
...
That would work perfectly, but it makes less sense to replicate the same code of scanf and use different functions just because the type is different.
So what is the solution? ==> Use the same function name ( scanf ), and then add a parameter (%d, %f, %c..) that will be used internally as a flag by C to know the parameter type.
I hope now you have a better understanding of the use of %d, %f....
There are two major points you are missing here.
First, we humans sitting at the keyboard will write something like:
char var = '0';
And we know that the "type" of this variable is char and we probably intend to store a character there. Once the compiler gets a hold of this it removes these "human" elements all that is left is at some memory location there is 1 byte reserved, further references to places in the code where we wrote "var" will interact with this memory location. That is all the compiler knows, there is no understanding of the intended variable "type".
Second, the format specificers do so much more than just indicate a simple type. Look at any page explaining scanf() and you'll see a long list, take special note of things like scan sets, negated scan sets, and expected input lengths.
Let's say I want the user to enter just a single digit, 0-9, well I don't have to just assume they will do as I ask, I can help ensure they will by using the format specifiers in scanf():
int var = 0;
print("enter 1 digit (0-9):\n");
scanf("%1d", &var);
Now, no matter how many digits they enter, I'll only have stored the first one.
What if you have a string that you want to read from the user, and you want to read everything up until you hit a new line character (read over spaces). We'll there are a number of options for this, but scanf can do it too. The "standard" to read a string is:
scanf("%s",some_string);
But that will stop at any whitespace character, so you wouldn't want scanf() to make an assumption in this case, you'd want to be able to use a specific negated scanset:
scanf("%[^\n]",some_string);
Can I use scanf(...) as argument to a function ?
Like this:
printInteger(scanf(....));
Can I use scanf to attribute the value that I read to some variable ?
Like this:
n = scanf(...);
p.s.: Here I'm explaining why I'm asking this.
This question can be a little weird I know, but I'm working in a project, which is developing a compiler that takes some language as input and then compile to C.
For example, this is my language, let's call 'stackoverflow' ;)
proc printInteger(integer k)
integer i;
begin
for i = 1 to k do
print i;
end
proc main()
integer n, i;
boolean ok;
begin
printInteger(getInteger);
n = getInteger;
ok = true;
while i < n do
begin
print i;
i = i + 1;
end
if ok then print 1; else print 0;
end
I won't get deeper in the language, but notice that getInteger means that I would like to do a scanf(...), what I mean is, when appears getInteger I would like to compile as scanf(...), so that's why I would like to know some ways to use scanf(...).
Can I use scanf(...) as argument to a function ? Like this:
printInteger(scanf(....));
Can I use scanf to attribute the value that I read to some variable ? Like this:
n = scanf(...);
You can use scanf as an argument to a function, but the real answer to both questions is no: scanf doesn't return any data scanned, it returns the number of items successfully scanned - or EOF if the end-of-input is reached before any successful scanning. You only get access to the items scanned using the pointers that you pass as scanf arguments to receive the values. So while you can pass scanf as an argument to a function, it won't do what you seem to want.
If you want to implement the getInteger operation in your language, in C, it's hard to make suggestions since only you know how this language/operation should work. Just using scanf, the implementation would look something like this:
int nextInt;
int numScanned = scanf("%d", &nextInt);
if (numScanned < 1)
handleError();
return nextInt;
But if you're doing general parsing for your language, then using scanf is a bad idea: you'll soon run into problems with the limitations of scanf, and you're not going to be able to anticipate all of the input types unless your language is really simple, simpler than the example that you've included.
To do this properly, find a good lex library for C. This will prevent a lot of headaches. Otherwise, if you must do the lexing yourself, start looking over fgets, get a line at a time from your input, and do the tokenizing yourself.
You ask:
Can I use scanf(...) as an argument to a function like this?
printInteger(scanf(....));
The answer to the first question is "Yes, but ...".
Can I use scanf to attribute the value that I read to some variable like this?
n = scanf(...);
The answer to the second is "No, because ...".
The "but" is mostly 'but it does not do what you expect so you would very seldom, if ever, do so'.
In the first example, scanf() returns either the (integer) number of successful conversions, or EOF if it reached EOF. In no case does it return the value that it just read (not least because, in general, it reads multiple values and most of them are not integers). So, if you want to print the number of values that was converted, you could use the printInteger() function to do so, but it is not what you'd normally want to do.
Similarly, in the second case, you can certainly assign the result of scanf() to an integer n as shown (and it is often sensible to do so if you're going to need to report an error). However, that is not the value that was read (assuming you had a %d conversion specification); it is the number of successful conversions.
I know my way around ruby pretty well and am teaching myself C starting with a few toy programs. This one is just to calculate the average of a string of numbers I enter as an argument.
#include <stdio.h>
#include <string.h>
main(int argc, char *argv[])
{
char *token;
int sum = 0;
int count = 0;
token = strtok(argv[1],",");
while (token != NULL)
{
count++;
sum += (int)*token;
token = strtok(NULL, ",");
}
printf("Avg: %d", sum/count);
printf("\n");
return 0;
}
The output is:
mike#sleepycat:~/projects/cee$ ./avg 1,1
Avg: 49
Which clearly needs some adjustment.
Any improvements and an explanation would be appreciated.
Look for sscanf or atoi as functions to convert from a string (array of characters) to an integer.
Unlike higher-level languages, C doesn't automatically convert between string and integral/real data types.
49 is the ASCII value of '1' char.
It should be helpful to you....:D
The problem is the character "1" is 49. You have to convert the character value to an integer and then average.
In C if you cast a char to an int you just get the ASCII value of it. So, you're averaging the ascii value of the character 1 twice, and getting what you'd expect.
You probably want to use atoi().
EDIT: Note that this is generally true of all typecasts in C. C doesn't reinterpret values for you, it trusts you to know what exists at a given location.
strtok(
Please, please do not use this. Even its own documentation says never to use it. I don't know how you, as a Ruby programmer, found out about its existence, but please forget about it.
(int)*token
This is not even close to doing what you want. There are two fundamental problems:
1) A char* does not "contain" text. It points at text. token is of type char*; therefore *token is of type char. That is, a single byte, not a string. Note that I said "byte", not "character", because the name char is actually wrong - an understandable oversight on the part of the language designers, because Unicode did not exist back then. Please understand that char is fundamentally a numeric type. There is no real text type in C! Interpreting a sequence of char values as text is just a convention.
2) Casting in C does not perform any kind of magical conversions.
What your code does is to grab the byte that token points at (after the strtok() call), and cast that numeric value to int. The byte that is rendered with the symbol 1 actually has a value of 49. Again, interpreting a sequence of bytes as text is just a convention, and thus interpreting a byte as a character is just a convention - specifically, here we are using the convention known as ASCII. When you hit the 1 key on your keyboard, and later hit enter to run the program, the chain of events set in motion by the command window actually passed a byte with the value 49 to your program. (In the same way, the comma has a value of 44.)
Both of the above problems are solved by using the proper tools to parse the input. Look up sscanf(). However, you don't even want to pass the input to your program this way, because you can't put any spaces in the input - each "word" on the command line will be passed as a separate entry in the argv[] array.
What you should do, in fact, is take advantage of that, by just expecting each entry in argv[] to represent one number. You can again use sscanf() to parse each entry, and it will be much easier.
Finally:
printf("Avg: %d", sum/count)
The quotient sum/count will not give you a decimal result. Dividing an integer by another integer yields an integer in C, discarding the remainder.
In this line: sum += (int)*token;
Casting a char to an int takes the ASCII value of the char. for 1, this value is 49.
Use the atoi function instead:
sum += atoi(token);
Note atoi is found in the stdlib.h file, so you'll need to #include it as well.
You can't convert a string to an integer via
sum += (int)*token;
Instead you have to call a function like atoi():
sum += atoi (token);
when you cast a char (which is what *token is) to int you get its ascii value in C - which is 49... so the average of the chars ascii values is in fact 49. you need to use atoi to get the value of the number represented