C for Java Programmers: Basics

George Ferguson

Summer 2018
Minor bugfix Fall 2022

This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
Creative Commons License

In this lesson, you will write basic programs from an “Intro to CS” course using C. These should not be hard since C and Java are very similar. Read the C for Java Programmers document if you don’t already understand this.

Each step of the lesson asks you to answer a question or write some code. Do the steps yourself before checking your work by revealing the answer.

Write a program that stores a temperature in degrees Fahrenheit using a variable and converts it to Kelvins using the following formula:

If the formula isn’t displayed, you can look it up at Wikipedia.
Your output should be of the form “212 degrees F is 373.15 K”.
Here’s one solution: #include <stdio.h> int main(int argc, char* argv[]) { float degreesF = 212.0; float kelvins = 5.0/9.0 * (degreesF - 32) + 273.15; printf("%f degrees Fahrenheit is %f Kelvins", degreesF, kelvins); } Values, types, expressions, and work about the same in C as in Java.

A few quick comments:

  • We used float variables to store the temperature. You could have used double instead. You should already know that it would be wrong to use int since temperatures can clearly be fractional. Try it!
  • We used the %f specifier in the printf format string (“floating point”). You could also use g or e. Try it!
  • If you want more or less places after the decimal point, you need to tell printf how many with a “precision” modifier, as in %.2f. Try it!
  • We specified the fraction “five ninths” using floating point numbers (with a decimal point). You should already know that if you write it as 5/9, they may be treated as integers, and five divided by nine using integer division is... 0. Try it!
  • Finally, the answer on your platform may or may not be exactly 373.15. You should already understand that floating point arithmetic is not precise.

Add code to test whether the temperature is less than or equal to 32 °F, in which case it should print “That’s freezing!”, or is greater than or equal to 212 °F, in which case it should print ”That’s boiling!”, otherwise it should print “That’s nice.”
if (degreesF <= 32) { printf("That's freezing!\n"); } else if (degreesF >= 212) { printf("That's boiling!\n"); } else { printf("That's nice.\n"); } Conditionals in C are almost identical to conditionals in Java, including if-else and switch.
Write code to print the numbers from 1 to 10, and to print the numbers from 10 down to 1 counting by twos.
int i=1; while (i <= 10) { printf("%d\n", i); i += 1; } // or for (int i=1; i <= 10; i++) { printf("%d\n", i); } for (int j=10; j >= 1; j -= 2) { printf("%d\n", j); } Iteration statements are almost identical in C and Java, include while, for, and do-while. C also has the same increment/decrement operators (++ and --) and compound assignment statments (+=, etc.). In fact, Java has them because C has them!
C is not an object-oriented language, so it doesn’t have methods defined in classes. Instead, it has the more general idea of a “function”. This is covered in the C for Java Programmers document. Object-oriented programming in C is covered in the next lesson in this tutorial.

For now, write the following two functions:

Include code to demonstrate your functions being used.

void printStars(int n) { for (int i=1; i <= n; i++) { printf("*"); } } float ftok(float degf) { return 5.0/9.0 * (degf - 32) + 273.15; } These definitions must come before they are used, meaning before the code for main. Then to use them in main, for example: printStars(5); printf("\n"); printf("0 degrees F is %f Kelvins\n", ftok(0.0));

Download full program: basics1.c

Let’s talk input and output (I/O).

In Java, you use the Scanner class to read input from the console (there are other possibilities also). It’s not quite so straightforward in C, but the basic patterns are not hard to learn.

In C, the basic building block for input is the C standard library function scanf (defined in <stdio.h>). It’s sort of like printf in reverse. You give it a format string with % specifiers, and it reads the input according to that specification. For example, %d means “read an integer,” %f means “read an floating-point number,” and so on. There can be more than one % specifier, in which case scanf tries to read more than one thing.

An important point is that scanf usually needs to “return” more than one thing. There’s the value or values specified in the format string, and there’s an overall return value indicating whether the values were present in the input. The latter is returned as the return value of the function. To receive the individual values, you must also pass scanf references (pointers) to where you want them stored. For primitive types, this will be a pointer to a variable of that type, for example an int*. For reference types, including strings which are char*s, you just just give scanf the pointer.

FYI: The C for Java Programmers document uses scanf as an example in its discussion of pointers. Check it out.

Then write a function that reads, separately, an integer, a floating-point value, and a string and prints out what it read.

int main(int argc, char* argv[]) { int n; printf("Enter an integer: "); scanf("%d", &n); printf("You entered %d\n", n); float f; printf("Enter a floating-point number: "); scanf("%f", &f); printf("You entered %f\n", f); char str[256]; printf("Enter a string (no more than 255 characters): "); scanf("%255s", str); printf("You entered \"%s\"\n", str); } You may be surprised by what happens when you give scanf the %s specifier. Read the manual entry for it. That’s what it’s supposed to do. Read on for an alternative.

You could also read all three values in one call to scanf. Try it!

The manual entry for scanf says the following about the %s specifier:
“Matches a sequence of non-white-space characters; the next pointer must be a pointer to char, and the array must be large enough to accept all the sequence and the terminating NUL character. The input string stops at white space or at the maximum field width, whichever occurs first.”
This is sort of similar to what Scanner.next returns.

If you just want to read the next line of input (up to a newline), like Scanner.nextLine, the function you want is fgets. The incantation fgets(str, 255, stdin); reads into the character array str at most 255 characters from the standard input (stdin). The array str must be big enough to hold that many characters and a terminating NUL character, and it’s YOUR problem to make sure that it is.

Note: There is an apparently simpler function named gets which reads from the console into the given character array with no length limit. The manual entry for gets and fgets says the following:

“The gets() function cannot be used securely. Because of its lack of bounds checking, and the inability for the calling program to reliably determine the length of the next incoming line, the use of this function enables malicious users to arbitrarily change a running program’s functionality through a buffer overflow attack. It is strongly suggested that the fgets() function be used in all cases.”
So don’t use gets. Use fgets and give an appropriate size limit for the buffer you’re reading into. Also note that fgets includes the newline that the user typed.

Finally, for this step, write a program that reads lines from the console and prints them out as they are read. The program should stop reading when it reads an empty (blank) line.

printf("Enter lines of text; blank line to finish:\n"); do { fgets(str, 255, stdin); printf("%s", str); } while(str[0] != '\n'); Note that the newline is included in the characters read into str, which is why we don’t have to print one ourselves. That’s also why the loop condition works: if the first (0th) character read is a newline character, then the input was an empty line. You could also use the strlen function from <string.h> and test for a string of length... 1 (since it includes the newline).

Download full program: basics2.c

More I/O: In Java, you use File objects and various flavors of InputStreams, OutputStreams, Readers, Printers, and Scanners to read and write files. In C it’s quite a bit simpler, but the standard library provides functions to get the job done. You will need to #include <stdio.h> to use these functions. With this background, write a function that takes two filenames as parameters and copies the contents of the file with the first name into a file with the second name (creating it if it doesn’t exist, overwriting it if it does exist, both of which are the default behavior of fopen).
int copyfile(char* srcfilename, char* dstfilename) { FILE* src = fopen(srcfilename, "r"); if (src == NULL) { return 0; } FILE* dst = fopen(dstfilename, "w"); if (dst == NULL) { return 0; } while (!feof(src)) { char str[256]; if (fgets(str, 255, src) != NULL) { fprintf(dst, "%s", str); } } fclose(src); fclose(dst); return 1; }

Download full program: basics3.c and sample text file xanadu.txt

Back to Tutorial Home