How can I use C to assign user input to a variable? - c

I am wondering if there is a function I could use in the standard libary. Do I need another library (BTW, I am developing for unix).

See the scanf() function in stdio.h. It takes a format specifier like printf() and pointers to the variables to store the user input in

Use scanf()
Format: int scanf ( const char * format, ... );
Read formatted data from stdin.
Reads data from stdin and stores them according to the parameter format into the locations pointed by the additional arguments. The additional arguments should point to already allocated objects of the type specified by their corresponding format tag within the format string.
Example:
#include <stdio.h>
int main(void)
{
int n;
printf("Enter the value to be stored in n: ");
scanf("%d",&n);
printf("n= %d",n);
}
However have a look at this.

You seems quite new to C so let me add a little something to Prasoon answer, which is quite correct and complete, but maybe hard to understand for a beginner.
When using scanf( const char * format, ... ); in his exemple, Prasoon use :
scanf("%d",&n);
When using this, the "%d" indicate you're going to read an integer (See wikipedia for complete format list ).
The second argument (note that the ... indicates you can send any number of arguments) indicate the address of the variable in which you are gonna stock user entry.

'Tis interesting - two answers so far both suggest scanf(); I wouldn't.
When everything goes right, scanf() is OK. When things go wrong, recovery tends to be hard.
I would normally use fgets() to read the user information for one line into a buffer (character array) first. I would then use sscanf() to collect information from the buffer into the target variables. The big advantage is that if the user types '12Z' when you wanted them to type two numbers, you can tell them what you saw and why it is not what you wanted much better. With scanf(), you can't do that.

Related

format specifiers in scanf( ) in C?

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);

Asking for a name and returning the length of the name in C

I've been struggling with this code for quite some time now.
This is my first time posting here. I am new to C, and I feel that I almost got it.
I have to ask for your name, middle initial, and last name. Then I greet you and tell you the length of your name. Sounds simple enough. I have the following code, I have to use the header file as it is here and that makes things worse. Any help would be greatly appreciated, I feel that I already applied all my knowledge to it and still can't get it to work.
This is my header file:
#ifndef NAME_H_
#define NAME_H_
struct name{
char first[20];
char middle;
char last[20];
};
#endif
and this is my .c file:
#include "name.h"
#include <stdio.h>
#define nl printf("\n");
int strlen(char*s);
char first;
char middle;
char last;
main()
{
printf("enter your first name : ");
scanf("%c", &first);
printf("\n enter your middle initial name : ");
scanf("%c", &middle);
printf("\n enter your last name: ");
scanf("%c", &last);
printf("\n\n Hello %c",first, " %c" ,middle, " %c", last);
printf("\n The String returned the following length: ",strlen);
}
I have t use printf and scanf, then store the name components a name "structure" imported from name.h and lastly use int strlen(char *s); to calculate it.
I get this output with the weird indentation and everything:
enter your first name : Joe
enter your middle initial name :
enter your last name:
Hello J
The String returned the following length: [-my user id]$
Thanks!
Several things about this are not quite right.
First, you shouldn't be declaring strlen yourself. It's a standard C library function, which means you should include the appropriate header. In this case,
#include <string.h>
Second, you're storing the input in variables of type char. Those are literally what they say: they store a single character. So unless you're only allowing people to have single-character names, you need a bit more than that. This sort of string input problem is actually rather tricky in C, since you have to do explicit memory management and don't know how much data the user is going to send you in advance. One of the simpler things is to just use a large buffer and truncate, but for a more complex program you'd want to do error handling and possibly dynamically resize the buffer. But for starters:
char first[1024];
char middle[1024];
char last[1024];
will at least get you started. Your struct name has some of this, but you're not currently using it (and the sizes are pretty small).
Next, scanf is a tricky way to get input strings. scanf of a %s pattern will happily read more than 1024 characters and write over the end of the buffer and destroy your program. This is why C programmers usually read input data using fgets instead, since then you can more easily say how big of a buffer you're willing to read:
fgets(first, sizeof(first), stdin);
Be aware that if the user enters more than 1023 characters, it will read the first 1023 characters and then leave the rest there, where you'll end up reading it as part of the middle name. String handling in C is complex! C is not good at this sort of thing; that's why people tend to use Perl or similar languages for this sort of interactive string handling where you don't know sizes in advance. In C, you have to pursue a strategy like repeatedly calling fgets until you get a newline at the end of the result and then deciding whether to dynamically resize your data structure or throw an error. Alternately, you can use scanf with %1023s but you need to qualify the format to specify the maximum length. The syntax is a bit weird and tricky; fgets is simpler when you're reading character strings.
As mentioned in the other answer, strlen is a function that you need to call on a char * variable (or char array) to get the length of the string it holds. You probably want to call it on first, middle, and last and add them together.
Finally, in your last printf, you have to pass one format and then all of the arguments for that format. You want something more like:
printf("\n\n Hello %s %s %s", first, middle, last);
(once you fix the type of those variables).
This is a lot of random detail. I hope it helps some. The important brief takeaway is that a string in C is a sequence of char ending in a char with a value of 0, and all C data structures have to be sized in advance (either statically or dynamically with malloc). C furthermore has no bounds checking, so it's completely up to you to ensure that you only read as much data as you created space for.
use
strlen(first)
to get the length of variable first ..similarly for other varibles... To get the cumulative length use
printf("\n Length: ",strlen(first)+strlen(middle)+strlen(last));

C: 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(...);
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.

scanf error handling C

Say If i want an input to be
[Name] [Name]
How would I detect
[Name] [Name] [Name]
and return error?
Here is what I have so far,
char in[20];
char out[20];
scanf(" %s %s", out, in);
scanf returns the number of validly converted arguments. So in your first case, the return value would be 2, in the latter case 3.
To check the right amount of parameters, this might help:
char in[20];
char out[20];
char error[20];
int check;
check = scanf(" %s %s %s", out, in, error);
if(check != 2)
{
// TODO: error handling
}
EDIT: now it should be working, see comments below.
Of course, as stated by other posters: scanf is not considered a quite safe function since buffer overflows can occur, and you should avoid using it. It is better to read the inputs to a buffer with fgets() and the try to parse the arguments you want.
This is homework, so you might be required to work under certain (arbitrary) restrictions. However, the phrase "scanf error handling" is something of an oxymoron in the C programming language.
The best way to do this is to read in a line/other suitable chunk and parse it with C string functions. You can do it in one line of scanf but there are many drawbacks:
You can guard against buffer overflows, but if a buffer isn't large enough you can't recover.
You can specify specific character ranges for your strings, but it starts to look a little regexy, and the behavior of the "%[" format of scanf isn't mandated in the standard.
You can check for a third name, but the code looks unintuitive - it doesn't look like you only want two names, it looks like you want three. scanf also gives you very little control over how you handle whitespace.
EDIT: I initially thought from your question that the names were contained in brackets (a la "[Bruce] [Wayne]") but it now appears that was merely your convention for denoting a placeholder.
Anyway, despite my intense dislike of scanf, it has its uses. The biggest killer (for me) is the inability to distinguish between line endings and simple space separation. To fix that, you can call fgets to read the data into a buffer, then call sscanf on the buffer. This gives you both a) safer reading (scanf messes with the ability of other more straightforward functions to read from a buffer) and b) the benefits of scanf formats.
If you have to use scanf, your format basically be this:
" %s %s %s"
With the third being undesirable. As #Constantinius's answer shows, you'd need to read data into three buffers, and check whether or not the third passed. However, if you're reading multiple consecutive lines of this data, then the first entry of the next line would satisfy the third slot, falsely giving you an error. I highly recommend using fgets and sscanf or ditching the sscanf for more precise manual parsing in this case.
Here's a link to the fgets man page if you missed the one I snuck in earlier. If you decide to ditch sscanf, here are some other functions to look into: strchr (or strspn, or strcspn) to find how long the name is, strcpy or memcpy (but please not strncpy, it's not what you think it is) to copy data into the buffers.

difference betweent printf and gets

I am beginner for programming.I referred books of C programming,but i am confused.
1.) What's the difference betweent printf and gets?
I believe gets is simpler and doesn't have any formats?
printf
The printf function writes a formatted string to the standard output. A formatted string is the result of replacing placeholders with their values. This sounds a little complicated but it will become very clear with an example:
printf("Hello, my name is %s and I am %d years old.", "Andreas", 22);
Here %s and %d are the placeholders, that are substituted with the first and second argument. You should read on the man page (linked above) the list of placeholders and their options, but the ones you'll run into most often are %d (a number) and %s (a string).
Making sure that the placeholder arguments match their type is extremely important. For example, the following code will result in undefined behavior (meaning that anything can happen: the program may crash, it may work, it may corrupt data, etc):
printf("Hello, I'm %s years old.", 22);
Unfortunately in C there is no way to avoid these relatively common mistakes.
gets
The gets function is used for a completely different purpose: it reads a string from the standard input.
For example:
char name[512];
printf("What's your name? ");
gets(name);
This simple program will ask the user for a name and save what he or she types into name.
However, gets() should NEVER be used. It will open your application and the system it runs on to security vulnerabilities.
Quoting from the man page:
Never use gets(). Because it is
impossible to tell without knowing the
data in advance how many characters
gets() will read, and because gets()
will continue to store characters past
the end of the buffer, it is extremely
dangerous to use. It has been used to
break computer security. Use fgets()
instead.
Explained in a more simple way the problem is that if the variable you give gets (name in this case) is not big enough to hold what the user types a buffer overflow will occur, which is, gets will write past the end of the variable. This is undefined behavior and on some systems it will allow execution of arbitrary code by the attacker.
Since the variable must have a finite, static size and you can't set a limit of the amount of characters the user can type as the input, gets() is never secure and should never be used. It exists only for historical reasons.
As the manual suggested, you should use fgets instead. It has the same purpose as gets but has a size argument that specifies the size of the variable:
char *fgets(char *s, int size, FILE *stream);
So, the program above would become:
char name[512];
printf("What's your name? ");
fgets(name, sizeof(name) /* 512 */, stdin /* The standard input */);
They fundamentally perform different tasks.
printf: prints out text to a console.
gets: reads in input from the keyboard.
printf: allowing you to format a string from components (ie. taking results from variables), and when output to stdout, it does not append new line character. You have to do this by inserting '\n' in the format string.
puts: only output a string to stdout, but does append new line afterward.
scanf: scan the input fields, one character at a time, and convert them according to the given format.
gets: simply read a string from stdin, with no format consideration, the return character is replaced by string terminator '\0'.
http://en.wikipedia.org/wiki/Printf
http://en.wikipedia.org/wiki/Gets

Resources