Book 3: Variables and User Input

Previous | Next

Motv variable boxNow that you have learned how to write “Masters of the void” onto the screen, and you have probably already tried writing something else between the quotes or duplicating the printf-line, we would like to get more daring. To do this, C has variables. A variable is simply a name for a box into which you can put a value of a specific data type. We already know int, so let’s create a variable with this data type, for holding whole numbers. Change your main.c file so main() looks like the following (leave the #include in there!):

int	main()
{
	int		myNumber;
	
	myNumber = 7;
	printf( "I am %d years old.", myNumber );

	return 0;
}

Before we get to the explanation, here’s a little movie that illustrates what happens when this program runs:

The first line

int		myNumber;

defines a variable named myNumber which may hold data of type int. “Defining” something basically means you tell your compiler what a certain word is supposed to mean. In this case, you tell the compiler that you want some memory in which you can keep any number, and that whenever you refer to myNumber, you want the compiler to substitute whatever you stored in myNumber before. The second line

myNumber = 7;

now assigns the number 7 to this variable. This is done using the = operator, which writes whatever is to its right into the container to its left. Note that, even though main() and myNumber both have the data type int, main() is not a variable and myNumber is not a function. A function is a list of commands, while a variable is a place to store data.

But what does the next line do?

 printf( "I am %d years old.", myNumber );

You see, printf() doesn’t simply print the text to the screen just like that, rather, it looks at the text you give it and looks for placeholders. Placeholders always start with a per cent sign (“%”) and then have one character after them that indicates what should be inserted here. In our case, that character is “d”, which means “decimal number”, which means it wants an int. You can also use “%s” to mean “string of characters”, i.e. a bit of text. It will replace every such placeholder with a value and then print that to your screen.

 

Be careful with your placeholders. If you specify the wrong placeholders, or forget one of the values to fill the placeholders, or specify “%s %d” but then pass the number first and the string second, or make other mistakes, the compiler will not stop you with an error. Your program will compile just fine, but when you run it it might print garbage or even crash at that line. The only indication that something has gone wrong will be a little yellow warning icon in the status area and an entry in the Issues Navigator that explains the issue.
[The status area with only a warning, not an error]

So, where does it get the values from? Well, you specify them as additional parameters after your text with placeholders, each separated by commas. So if you wanted to provide a number and a name, you could write:

printf( "I am %s and I'm %d years old", "Pete", 29 );

Obviously, this would be a little pointless, as you could just write “I am Pete and I’m 29 years old” right away, but when you’re using variables this can come in really handy to output whole sentences assembled from data the user entered: If you run the original program (choose Run from the Product menu), it writes “I am 7 years old.” into the Console Area. So, you see that myNumber is automatically replaced by its value. Neat, huh? Change the printf line to match the second example and run it. It will say “I am Pete and I’m 29 years old”.

Now let’s try another neat thing:

int	main()
{
	int	a,
		b,
		c;
	
	a = b = c = 23;
	printf( "a = %d, b = %d, c = %d", a, b, c );
	return 0;
}

Note how, in this example, there are three equals signs chained together. Run it, and you will get “a = 23, b = 23, c = 23” on your screen. This comes from the fact that these statements are executed from right to left. That is, first 23 is put into c, then c (which contains 23 now) is put into b and then b (which now also contains 23) into a.

Another thing that may catch your eye here is how I defined a, b and c. You can define multiple variables by writing the data type once and then specifying a list of variable names separated by commas. Again, where you insert spaces, newlines and tabs is mandatory, their count isn’t. Most programmers put each variable on its own line, but since C couldn’t care less about how much whitespace you put between identifiers, you could also write:

int	a, b, c;

Just remember to finish off the definition of a variable with a semicolon (“;”). Also, most versions of C require variable definitions to go at the top of a “{ … }” block, you can’t just put them anywhere you want.

But now, wouldn’t you want to do something more dynamic than just outputting the same text? OK. Let’s get started with input from the user. With all you already know, it’ll be pretty easy. Change your version of main() again:

int	main()
{
	int		userInput;
	
	printf( "Please enter your age: " );
	
	scanf( "%d", &userInput );
	fpurge( stdin );
	
	printf( "You are %d years old.\n", userInput );
	
	return 0;
}

Note that if you run this, you may have to open the Console Area if it doesn’t open automatically for you, and place the cursor in it to be able to edit it. Also, you may get confusing non-bold messages from the system telling you about the gory details of what it is doing interspersed with your writing. You can use the pop-up menu in the upper left of the Console Area to switch between “All Output” (the current setting), “Debugger Output” (the confusing stuff only) or “Target Output” (only the stuff your program outputs via printf and the like).

If, suddenly, the Console Area shows the word “(lldb)” (or “(gdb)”) and Xcode highlights one of your source code lines in green, you have made a programming error, and your program has crashed (it is showing you a command-line prompt where you could type in commands the debugger should do). Xcode helpfully highlights the line whose instructions it was trying to follow when it crashed. If you can’t make sense of the error message at the right end of the line, for now just compare it to the line in this tutorial, and make sure it matches exactly. We’ll go into what some of these mean later, when you’re more familiar with some of the gory details of C.

If your program crashes, the Run button turns into an Stop button. Click that once you’ve fixed your mistake, and it will force-quit the crashed program and you can try running it again.

Again, here’s a movie illustrating how the code you just typed in will do its magic. Since I can’t really show you yet what printf(), scanf() and fpurge() really do internally, I left those out of this animation:

First we define an integer variable named userInput. This is the place the data the user entered will go. Then we output some text that tells the user he/she is to enter a number. And now comes the actual part that gets the user input. scanf() is the opposite of printf(), and simply waits until the user has typed something in and pressed the return key on the keyboard. Since scanf() reads, and doesn’t write, the placeholders tell scanf() what kind of data to read, and the parameters you pass it are the destination where you want the read data to go. Also note the “&” before the userInput variable. We’ll learn why this is necessary later when we do our own parameters. For now, just see it as a quirk that scanf() requires before all its destination parameters.

The call to fpurge() makes sure any excess characters entered after the number are discarded, and also tells the system you are finished reading text and will be writing again. stdin is the name of the input stream used by scanf(). Think of it as the name C gives to your keyboard. There’s also stdout used by printf() and stderr used to log errors. But you won’t need those anytime soon.

Finally, to prove that the value arrived properly, we write the variable’s value to the screen again. Here you might note some gibberish at the end of the scanf text and the actual text we want to printf: \n. Whenever you encounter a backslash inside some text enclosed in quotes, this means that you want to express some special character inside your text. What character is to be inserted is specified by the next character after the \.

In this case it is an n, which means “newline”, that is, we tell the compiler to start a new line, just as if we hit the return key on the keyboard. You can also use \t to type a tab, \" to type a quote, and to type a backslash, you use \\ so it knows you really want a backslash and this isn’t the start of another special character.

Previous | Next

This entry was posted in C Tutorial. Bookmark the permalink.

29 Responses to Book 3: Variables and User Input

  1. TJessiman says:

    Hi having a bit of trouble, keep getting an error message saying “linker command failed with exit code 1 (use -v to see invocation)”. Wondering if you could help. Included the code in case I’ve typed it out wrong:

    #include

    int main ()
    {
    int myNumber;

    myNumber = 7;
    printf( “I am %d years old.”, myNumber );

    return 0;
    }

    • OPreuss says:

      The first line must be:

      #include

    • Sebastian says:

      Hi TJessiman,

      If i’m seeing it right, you are missing this (without the single quotes): ” after your ‘#include’ in the first line of code.

      It should be:
      #include

      Greetings

      • Sebastian says:

        Or you aren’t missing it :s, it is escaped by the HTML tags…
        ‘smallerthansign’stdio.h’largerthensign’

        So I didn’t spot the problem…
        Please delete my posts…

        • Tyler N says:

          The top line should read –

          #include

          You forgot to include your file which is why it came back with an error.

          (The hint was in the ‘#include’ 😉

          • Tyler N says:

            It won’t allow me to add the studio.h within my previous comment but that is the file you need to include within the top line of code.

            For example, #include

            (without the spaces.

          • Uli Kusterer says:

            It’s not stUdio, it’s stdio. Short for Standard-Input-Output (Std I O).

  2. Charles Marshall says:

    This is a great tutorial and a great format for learning. The Comments section not only helps to answer my questions but I’m learning a lot by trying to answer other’s before I read your reply! I’ve always thought learning what causes something to fail helps to reinforce the understanding of how it works. Great Job! Keep up the good work!

  3. Uli Kusterer says:

    Sam,

    the format string is one long string as the first parameter, not three short ones as the first three parameters, so this should be:

    printf( “a = %d, b = %d, c = %d”, a, b, c );

    If you add extra quotes, that means the commas are seen as parameter separators, not as punctuation used inside the text.

  4. sam says:

    Hey there,

    Great tutorial but one slight issue, when I have these lines of code in xcode, I get the following warning:
    a = b = c = 23;
    printf(“a = %d”, “b = %d”, “c = %d”,a,b,c);

    warning: format ‘%d’ expects type ‘int’, but argument 2 has type ‘char *’

    When I run these lines I get this output: a = 3919

  5. Uli Kusterer says:

    kevin, Can you post your code here? My guess is something is wrong with your scanf() line.

  6. kevin says:

    i wrote my program the exact way it is shown here and in the console when i run the program the line saying enter your age appears and i enter a number then press return but nothing happens. only when i type q to quit then press return does the line you are blank years old appear. help?

    • Ian says:

      Hi,
      I got the same issue, turns out if you shift to enter the numbers when prompted it doesn’t work, same if i use an external numpad. So i got it to run “properly” by just entering and , as in keys without modifiers. It’s something that has been confusing me so far, do not expect asci and what not symbols or characters to be mapped to your keyboard as displayed on the keys…

    • Uli Kusterer says:

      It should work, but it’s a bit picky about what it accepts. Have you tried leaving out anything but the raw number? So no decimals, no thousands separators, and small numbers?

  7. Christian says:

    Thank you Uli,

    I figured it out. I was also pressing enter on the number pad rather than return on the main keyboard to move the program along.

    Thanks for the quick reply.

  8. Uli Kusterer says:

    Christian, you probably didn’t open the “Console” window: Choose “Console” from the “Run” menu and you will have a window with your text. Your program was happily running, you just didn’t see it. Hence the error message about having to stop the running program before you can start it again.

  9. Christian says:

    Hello, I am not able to get the second part to run.

    scanf( “%d” , &userInput );
    fpurge( stdin );

    printf( “You are %d years old.\n”, userInput );
    return 0;

    Once I input my age and hit return nothing happens.
    Also when I hit build and go a screen pops open and says stop executable… i click ok to continue building and then it runs but I am not sure why it pops open with that warning. It did not do it for the previous programs.

    Xcode v3.13

    Thanks

    Christian

  10. Uli Kusterer says:

    Andrew, where the application goes depends on various factors (settings specified in the project and in Xcode’s preferences). In a bog-standard Xcode setup, you should see the executable in a “build” folder next to your project file. Usually it is in a “Debug” or “Release” folder in there. Alternately, you can double-click the icon for the generated application in the little brown “Products” folder in the Groups & Files list of your project window to launch it with Terminal.

  11. Andrew Hobson says:

    Once I compile the project, if I want to quit Xcode and run the program from the “real” MacOS X Terminal, what mst I do?
    Where is the final program stored?
    How can I execute it?

  12. Uli Kusterer says:

    Jaxerell, fpurge() is not always needed. The issue is that on some versions of Mac OS and Linux you would need to use this command, while newer versions of Mac OS for example don’t need it anymore. But according to the ANSI standard, you have to use fpurge() in this context, so I thought I’d be better safe than sorry.

  13. Jaxerell says:

    I had the same problem/error as Lindsay, with stdin, so I just took the line out, the whole fpurge line.

    It worked with a plain number, and when I entered a number AND text, it ignored the text and just used the number. This is what you said that fpurge does, yet it did it without the line.

  14. Uli Kusterer says:

    zach, that Terminal display is where you enter stuff in Xcode to get it into your running program.

    To actually write a graphical user interface, you need to do some additional work (usually involving the use of the Objective C programming language and Cocoa framework). It’s just that this would exceed the scope of this tutorial, so I stuck with the Terminal-esque text input/output calls to keep things simple.

    But that Terminal-like window Xcode opens should be enough for most uses until you’re familiar with C and want to move on to Objective C.

  15. zach says:

    Let’s say I code something where the user can input three numbers, and the c code can calculate them together. Does XCode run this code and open up a little space where the user can input the numbers? I ask this because each time I run my simple c code, it opens a Terminal-esque display. Do I have to run a different compiler if I am writing software c code where the user will need to input data and interact with my software?

    Sorry, brand new to c, willing to learn. Just downloaded Xcode, but not sure past the point of the Console running my code in a Terminal like display format.

  16. Uli Kusterer says:

    You are using “%s” to tell scanf() to expect a string of text, but then you give it a variable that is declared as an int (which is an integer number). That can’t work.

    We will learn how to correctly use scanf() with “%s” in Book 10. Hang on until then, you’re doing fine, and it’s great to try out different things, but this one is a bit more complicated than it looks 🙂

  17. MO says:

    I want to write a program to for his/her name, and this what I did:

    #include

    int main()
    {
    int userName;

    printf(“Please enter your name:”);

    scanf(“%s”, &userName);
    fpurge(stdin);

    printf(“\nYour name is %s \n”, userName);

    return 0;
    }

    but when I run it, this what happen:

    Please enter your name:mohammed

    [Session started at 2009-05-14 15:52:09 -0600.]
    Loading program into debugger…
    GNU gdb 6.3.50-20050815 (Apple version gdb-962) (Sat Jul 26 08:14:40 UTC 2008)
    Copyright 2004 Free Software Foundation, Inc.
    GDB is free software, covered by the GNU General Public License, and you are
    welcome to change it and/or distribute copies of it under certain conditions.
    Type “show copying” to see the conditions.
    There is absolutely no warranty for GDB. Type “show warranty” for details.
    This GDB was configured as “i386-apple-darwin”.Program loaded.
    sharedlibrary apply-load-rules all
    Attaching to program: `/Users/grey_falkon2003/Documents/first project revised/build/Debug/first project revised’, process 894.
    kill

    The Debugger Debugger is attaching to process

    *** I don’t know whats wrong!!

  18. Gaby J says:

    Hey, I’m starting a project (developing an iPhone app), and I need to learn C first. You guys are one of the only sites that teaches this in “Mac terms”, and it’s great. Thanks!!!

  19. Uli Kusterer says:

    Lindsay, have you checked that all the #include statements are in your code? If you leave one of them out, that will cause the error you mention.

  20. Lindsay Cripps says:

    Great tutorial.

    I’m getting an error coming up along side – fpurge( stdin );

    error: ‘stdin’ undeclared (first use in this function)

    Latest 3.1 version of Xcode

Leave a Reply

Your email address will not be published. Required fields are marked *


*