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]
Related
I'm going through the CS50 exercises and I don't understand this piece of code. All it does it take a positive integer as input and then printf. So in main() we're saving the input in int i.
In the next step int i is used as a parameter/argument(?) for the function get_positive_int ("string prompt").
Why is it a string? How is this possible? I'd have thought typecasting would have to be used for this to happen...
Please feel free to correct me, I'm lost.
// Abstraction and scope
#include <cs50.h>
#include <stdio.h>
int get_positive_int(string prompt);
int main(void)
{
int i = get_positive_int("Positive integer: ");
printf("%i", i);
}
// Prompt user for positive integer
int get_positive_int(string prompt)
{
int n;
do
{
n = get_int("%s", prompt);
}
while (n < 1);
return n;
}
According to the documentation, get_int formats the prompt like printf. So the %s here is the format string to printf, and the second parameter (prompt) is the string which is printed by the %s.
In other words, the format string here is used only for output. There is no need to specify a format string for the input (like for scanf) because the function already knows that it's inputting an int.
In the next step int i is used as a parameter/argument(?) for the function get_positive_int ("string prompt").
Not quite.
i receives the value returned from get_positive_int. The string "Positive integer" is the argument to get_positive_int. get_positive_int passes that string (prompt) on to get_int, which does the actual work of writing the prompt string to standard output and reading the input you type in.
get_int obviously calls vprintf. All the *printf functions require a format string to tell them how many additional arguments to expect, what their type is, and how their values should be formatted for output. In this particular case, we're telling vprintf to expect a single argument of type string (char *).
You can write more complex prompts for get_int, such as
i = get_int( "Enter the %d'th name: ", count );
If count is 5, then the prompt will be written as
Enter the 5'th name:
get_int then calls C's input functions (fgets, fscanf, whatever) to read and parse what you type in and make sure it's a valid integer.
<gratuitous rant>
The CS50 library abstracts away most of the gorier details of C I/O and string handling, which is nice, but in the process leaves you absolutely unprepared for the reality of text processing in C - it's a lot harder than CS50 makes it look.
Once you're done with CS50, throw away everything it taught you about strings and I/O and find a decent C reference manual. Be prepared to start over from the beginning.
</gratuitous rant>
I am an absolute beginner in (c) programming and I have to find a solution for the following problem:
I have to parse command line arguments to floats in a struct. This works quite well using argc, argv and atof. But is there an way to check, whether the user used valid "float-characters" (0-9 and .) in his input?
atof only returns its error 0.0 when there isn't any number at the beginning of the string to parse. If the user writes for example ./programname 4,5, atof would still write 4 into my float...
I would have to check every single submitted character and in addition, set a counter to check, whether the user used more than one .. How can I achieve this efficiently?
EDIT:
Thank you vor your answers! My program is intended to convert only strings that consist of integers from 0 to 9 and a .. I forgot to mention that! I now try to write a function, that compares the input string to a string containing the valid chars using one for and one while loop. As I only want to check the second and the third argmunent of argv (argv[1] and argv[2]), I use a second for loop outside the rest to achieve that...
You can use sscanf and a dummy character to see if the complete string was converted or not, as in this answer:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[])
{
char dummy;
float f;
if(sscanf(argv[1], "%f%c", &f,&dummy) != 1)
printf("Input error.\n");
else
printf("%f\n", f);
}
Live demo here
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
What is the use of the %n format specifier in C? Could anyone explain with an example?
Most of these answers explain what %n does (which is to print nothing and to write the number of characters printed thus far to an int variable), but so far no one has really given an example of what use it has. Here is one:
int n;
printf("%s: %nFoo\n", "hello", &n);
printf("%*sBar\n", n, "");
will print:
hello: Foo
Bar
with Foo and Bar aligned. (It's trivial to do that without using %n for this particular example, and in general one always could break up that first printf call:
int n = printf("%s: ", "hello");
printf("Foo\n");
printf("%*sBar\n", n, "");
Whether the slightly added convenience is worth using something esoteric like %n (and possibly introducing errors) is open to debate.)
Nothing printed. The argument must be a pointer to a signed int, where the number of characters written so far is stored.
#include <stdio.h>
int main()
{
int val;
printf("blah %n blah\n", &val);
printf("val = %d\n", val);
return 0;
}
The previous code prints:
blah blah
val = 5
I haven't really seen many practical real world uses of the %n specifier, but I remember that it was used in oldschool printf vulnerabilities with a format string attack quite a while back.
Something that went like this
void authorizeUser( char * username, char * password){
...code here setting authorized to false...
printf(username);
if ( authorized ) {
giveControl(username);
}
}
where a malicious user could take advantage of the username parameter getting passed into printf as the format string and use a combination of %d, %c or w/e to go through the call stack and then modify the variable authorized to a true value.
Yeah it's an esoteric use, but always useful to know when writing a daemon to avoid security holes? :D
From here we see that it stores the number of characters printed so far.
n The argument shall be a pointer to an integer into which is written the number of bytes written to the output so far by this call to one of the fprintf() functions. No argument is converted.
An example usage would be:
int n_chars = 0;
printf("Hello, World%n", &n_chars);
n_chars would then have a value of 12.
So far all the answers are about that %n does, but not why anyone would want it in the first place. I find it's somewhat useful with sprintf/snprintf, when you might need to later break up or modify the resulting string, since the value stored is an array index into the resulting string. This application is a lot more useful, however, with sscanf, especially since functions in the scanf family don't return the number of chars processed but the number of fields.
Another really hackish use is getting a pseudo-log10 for free at the same time while printing a number as part of another operation.
The argument associated with the %n will be treated as an int* and is filled with the number of total characters printed at that point in the printf.
The other day I found myself in a situation where %n would nicely solve my problem. Unlike my earlier answer, in this case, I cannot devise a good alternative.
I have a GUI control that displays some specified text. This control can display part of that text in bold (or in italics, or underlined, etc.), and I can specify which part by specifying starting and ending character indices.
In my case, I am generating the text to the control with snprintf, and I'd like one of the substitutions to be made bold. Finding the starting and ending indices to this substitution is non-trivial because:
The string contains multiple substitutions, and one of the substitutions is arbitrary, user-specified text. This means that doing a textual search for the substitution I care about is potentially ambiguous.
The format string might be localized, and it might use the $ POSIX extension for positional format specifiers. Therefore searching the original format string for the format specifiers themselves is non-trivial.
The localization aspect also means that I cannot easily break up the format string into multiple calls to snprintf.
Therefore the most straightforward way to find the indices around a particular substitution would be to do:
char buf[256];
int start;
int end;
snprintf(buf, sizeof buf,
"blah blah %s %f yada yada %n%s%n yakety yak",
someUserSpecifiedString,
someFloat,
&start, boldString, &end);
control->set_text(buf);
control->set_bold(start, end);
It doesn't print anything. It is used to figure out how many characters got printed before %n appeared in the format string, and output that to the provided int:
#include <stdio.h>
int main(int argc, char* argv[])
{
int resultOfNSpecifier = 0;
_set_printf_count_output(1); /* Required in visual studio */
printf("Some format string%n\n", &resultOfNSpecifier);
printf("Count of chars before the %%n: %d\n", resultOfNSpecifier);
return 0;
}
(Documentation for _set_printf_count_output)
It will store value of number of characters printed so far in that printf() function.
Example:
int a;
printf("Hello World %n \n", &a);
printf("Characters printed so far = %d",a);
The output of this program will be
Hello World
Characters printed so far = 12
Those who want to use %n Format Specifier may want to look at this:
Do Not Use the "%n" Format String Specifier
In C, use of the "%n" format specification in printf() and sprintf()
type functions can change memory values. Inappropriate
design/implementation of these formats can lead to a vulnerability
generated by changes in memory content. Many format vulnerabilities,
particularly those with specifiers other than "%n", lead to
traditional failures such as segmentation fault. The "%n" specifier
has generated more damaging vulnerabilities. The "%n" vulnerabilities
may have secondary impacts, since they can also be a significant
consumer of computing and networking resources because large
guantities of data may have to be transferred to generate the desired
pointer value for the exploit. Avoid using the "%n" format
specifier. Use other means to accomplish your purpose.
Source: link
In my opinion, %n in 1st argument of print function simply record the number of character it prints on the screen before it reach the the %n format code including white spaces and new line character.`
#include <stdio.h>
int main()
{
int i;
printf("%d %f\n%n", 100, 123.23, &i);
printf("%d'th characters printed on the screen before '%%n'", i);
}
output:
100 123.230000
15'th characters printed on the screen before '%n'(with new character).
We can assign the of i in an another way...
As we know the argument of print function:-
int printf(char *control-string, ...);
So, it returns the number the number of characters output. We can assign that return value to i.
#include <stdio.h>
int main()
{
int i;
i = printf("%d %f\n", 100, 123.23);
printf("%d'th characters printed on the screen.", i);
}
%n is C99, works not with VC++.
I was fooling around with one of the sample programs in the K&R, and found that this
#include <stdio.h>
main()
{
double nc;
for (nc = 0; getchar() != EOF; ++nc)
;
printf("%lf\n", nc );
putchar(nc);
}
produces output that is 3.000000 (which I totally expected) then a new line with a heart on it (which I totally did not expect). Why would it output a new line with a heart on it?
I assume it has something to do with me mixing data types.
You're calling putchar() with a double as an argument. It's going to get implicitly typecast to int, and then that character will be output. You get the heart because for some reason your character set has a heart as character number 3. If you run it and type a bunch more characters before the EOF, you'll get a different character. On my machine, your program doesn't make a heart, but if I type more characters, I can get whatever I want on that next line. ASCII character 3 is ETX, end of text, so I don't know why you would get the heart in your case - are you using some weird locale or character set? What does this program output on your machine:
#include <stdio.h>
int main(int argc, char *argv[])
{
putchar(3);
putchar('\n');
return 0;
}
Edit:
You're getting the heart because that's what's in your character set at position 3. From wikipedia:
In Code page 437, the original character set of the IBM PC, the value of 3 (hexadecimal 03) represents the heart symbol. This value is shared with the non-printing ETX control character, which overrides it in many contexts.