We've covered quite a few topics in these first few weeks. It's time to pause and discuss some of the differences between what we've learned with C++ and how the C language differs. Many of these differences are quite small, so you just need to be aware of them and remember which to use depending on the language that you are utilizing. Other differences are bigger, but since this is an introductory course, we won't actually get to the more advanced topics that really illustrate why we have the two languages instead of just one.
To keep things simple, we'll cover what we've learned so far and how it differs.
Compiling a C program will use the gcc compiler instead of g++ (because C++ is a superset of C, g++ will actually work, but won't constrain you to C-only conventions...and you need to be aware of those constraints). Just like g++, you'll notice it creates an executable called a.out, which you run to run the program.
The next difference is simple file name conventions. A file of C code should be named code.c in contrast to our C++ code.cpp extension. It's a simple difference and is not actually required, but this is the convention to follow to make sure you don't confuse what language is in your file. Let's take a look at a simple C and C++ program now.
| file.cpp | file.c |
|
|
| g++ file.cpp | gcc file.c |
You should notice that the included library is different. In order to have basic input/output functions for C, you now include stdio.h instead of iostream. You cannot include iostream because that library is written with C++ and won't compile with your gcc compiler. The other difference is that we've lost the std namespace.
Printing is different in C because the shorthand operators like >> are not available and neither are the handy variables cin and cout. Those are handy things we get from C++ and its available libraries. Let's continue our example and print a greeting:
|
|
The new function is printf and it can take a single string argument. This is then printed the terminal. Notice that endl is no longer available, so you use must explicitly use the newline char '\n' when you want a new line.
What about variables? The good news is that C and C++ have roughly the same primitive types so not much changes there. The one difference is that bool is not a variable type in C. There are no true/false constant values and there is no bool type. Instead, the int value 0 corresponds to false and all other values true.
Let's put these differences together and print out some numbers:
|
|
The C printf function can take any number of arguments, and the first argument must be a string which is the template for what you print. If you want to print variable values, then you must use format specifiers like %d and %lf in my example. Specifiers tell the program how to display the values amongst the rest of the string. All the format specifiers can be seen here - as you can see,
chars.
ints.
doubles.
What about while, do-while, for loops, and if statements? It's all the same. Here's a loop comparison. There is no difference except for how we print:
|
|
Input is one of the bigger differences between the languages. The next thing we'd like to do is read values in from the user, cin-style.
If you think about the C++ statement cin >> x, what that actually means is "take the value off the text stream, and store it in the location used by x". C++ uses some fairly complex stuff (with pass-by-reference) to make this happen, but it's a feature that C doesn't have. So in C, we have to explicitly use pass-by-address. We do this using the scanf function:
#include <stdio.h>
int main() {
int x = 0;
printf("Please enter an integer: ");
scanf("%d", &x); // *** pass by address
printf("x is now %d\n", x);
return 0;
}
Go ahead and compile and run that program, to see that indeed, an input integer reads in to x. The scanf line is saying, read in an integer ("%d", as with printf), and store it in x.
Like with printf, a single scanf command can read in multiple values, as long as the number of specifiers and number of pointers is the same.
scanf can do some other cool things, too. Suppose you want the user to type in a command like Convert ___ dollars. and you want to burn the "Convert" and the "dollars." (see sample run 1 below). You can do that this way:
| code | sample run 1 | sample run2 |
|
$ ./a.out
Convert 3.5 dollars.
Converting 3.500000 dollars.
|
$ ./a.out
C 3.5 dollars.
Converting 0.000000 dollars.
|
As you can see in sample run 2, scanf is somewhat constraining in that the input has to be formatted exactly like you specify in your string argument. This means you don't have flexibility for the user to type anything different, such as lowercase where uppercase was expected. "Convert" in the scanf above cannot be "Change" or "convert". Whitespace has some flexibility, though, and any space character you have in your scanf string is interpreted as "one or more spaces". This means the user can have extra spaces by accident and your input will still work.
fopen, which accepts two C strings as arguments, the first of
which is a filename, and the second is a mode (detailed
here). After doing this, you can use fscanf or
fprintf just like you would scanf and
printf. So, to open a file and read an integer:
FILE* fin = fopen("someFile.txt","r");
int theInt;
fscanf(fin, "%d", &theInt);
$ ./sleeping Time: 0330 Go away, I'm asleep! $ ./sleeping Time: 1650 I'm Awake! $ ./sleeping Time: 2301 Go away, I'm asleep!
$ ./product Enter two integers: 2 5 Product of all integers between 2 and 5 is 120 $ ./product Enter two integers: 10 13 Product of all integers between 10 and 13 is 17160 $ ./product Enter two integers: 1 12 The product of all integers between 1 and 12 is 479001600