C vs C++

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.

Libraries, Compilers, and Headers

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.cppfile.c

#include <iostream>
using namespace std;

int main() {
  return 0;
}

#include <stdio.h>


int main() {
  return 0;
}
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.

Variables and Printing

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:


#include <iostream>
using namespace std;

int main() {
  cout << "Hello world!" << endl;
  return 0;
}

#include <stdio.h>

                            
int main() {
  printf("Hello world!\n");                           
  return 0;
}

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:


#include <iostream>
using namespace std;

int main() {
  int n = 20;
  double d = 4.5;
  cout << "I bought " << n << " apples for $" << d;
  return 0;
}

#include <stdio.h>

                            
int main() {
  int n = 20;
  double d = 4.5;
  printf("I bought %d apples for $%lf", n, d);
  return 0;
}

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,

Loops and Conditionals

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:


#include <iostream>
using namespace std;

int main() {
  for( int i = 0; i < 5; i++ )
    cout << "Hello for the " << i << "th time!" << endl;
  return 0;
}

#include <stdio.h>

                            
int main() {
  for( int i = 0; i < 5; i = i+1 )
    printf("Hello for the %dth time!\n", i);
  return 0;
}

Input

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

#include <stdio.h>

int main() {
  double money = 0;
  // 1. Consumes "Convert"
  // 2. Reads the double into money
  // 3. Consumes "dollars."
  scanf("Convert %lf dollars.", &money);

  printf("Converting %lf dollars.\n", money);

  return 0;
}
$ ./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.

Reading from files

Very superficial differences. First, you make a pointer to a FILE using 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);

Practice Problems

  1. Write a C program sleeping that reads a 4-digit time (HHMM, 24-hour time), and prints out "I'm Awake!" if the time is between 0600 and 2300 (inclusive), and "Go away, I'm asleep!" otherwise. Example of running your program:
    $ ./sleeping
    Time: 0330
    Go away, I'm asleep!
    $ ./sleeping
    Time: 1650
    I'm Awake!
    $ ./sleeping
    Time: 2301
    Go away, I'm asleep!
       
  2. Write a C program called 'product' that reads two integers n1 and n2 (with n1 < n2) from the user. For example, if n1=2 and n2=5, then the result would be 2⋅3⋅4⋅5, which comes out to 120. Example runs:
    $ ./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