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.

To keep things simple, we'll cover what we've learned so far and how it differs.

Libraries, Compilers, and Headers

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

file.cpp vs file.c

The first 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.

#include <stdio.h>

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. Moreover, we've lost the std namespace.

g++ vs gcc

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.

cout vs printf

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,

cin vs scanf

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.

Pass by address with scanf

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 <iostream>
using namespace std;

int main() {
  int x = 0;
  cout << "Please enter an integer: ";
  cin >> x;
  cout << "x is now " << x << endl;
  return 0;
}
#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.

Skipping leading spaces

We know that cin skips leading spaces. How about scanf?

Format string in scanf

Scanf is more of a departure from cin >> than it may appear from the above.

ex1.c compile & run

#include <stdio.h>
#include <math.h>

int main()
{
  double x, y;
  printf("command: ");
  while(scanf(" dist (%lf,%lf)",&x,&y) == 2) {
    printf("%lf\n",sqrt(x*x + y*y));
    printf("command: ");
  }
  printf("bye.\n");
  return 0;
}
$ gcc -o ex1 ex1.c -lm
$ ./ex1
command: dist (2,3)
3.605551
command: dist (-3,9.2)
9.676776
command:   dist  (  1, 1.2)
1.562050
command: dist(2.2,9.8)
10.043904
command: x
bye.

return value of scanf

It is important to remember that the return value of scanf amounts to the number of successful readings. In the above, the code checks if scanf returns 2. This means it checks if it reads the input into both x and y (i.e., two of them), successfully.

string vs char[]

We don't have string in C. So, we have to use a static array of char to represent a string.

#include <iostream>
using namespace std;

int main()
{
  string s;

  cout << "Enter a string: ";
  cin >> s; 
  cout << "You entered " << s << endl;

  return 0;
}

#include <stdio.h>


int main()
{
  char s[128];  // string s in C -- static array of chars 

  printf("Enter a string: ");
  scanf("%s", s);   // No need to use &s -- it is already of char* type
  printf("You entered %s\n", s);

  return 0;
}

Using files: fopen(), fclose(), fscanf(), fprintf()

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:


ifstream fin("someFile.txt");
int theInt;
fin >> theInt;

FILE* fin = fopen("someFile.txt","r");
int theInt;
fscanf(fin, "%d", &theInt);

Mandatory Practice Problem

Simple data bucketing. Write a program that works as follows: Sample run:
$ echo "1 3 2 4 10 8 7 5" > data.txt
$ cat data.txt
1 3 2 4 10 8 7 5
$ ./a.out
Filename? data.txt
$ cat even.txt
2 4 10 8
$ cat odd.txt
1 3 7 5
Solution: here.

Practice Problems

  1. 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
    
    Solution: here.