C Loops: Difference between revisions
(9 intermediate revisions by the same user not shown) | |||
Line 20: | Line 20: | ||
== Reading stdin line by line == | == Reading stdin line by line == | ||
''fgets'' is a C function that reads a line of input from a file. It takes three arguments (inputs): | |||
<source lang="c"> | |||
fgets(line, maxchars, file) | |||
</source> | |||
# ''line'': the name of a variable in which to store the result, this should be a character array (pointer) with enough space to store the line, | |||
# ''maxchars'': the maximum number of characters possible in a line (the function will never try to read more than this many characters, even if a line is longer), | |||
# ''file'': the name of the file to read from, here we use ''stdin'' to read from whatever is piped to this program. | |||
''fgets'' returns a value indicating whether or not it was able to read any input. In this way, it's possible to use as the ''condition'' of a while loop to do something with all available input. | |||
<source lang="c"> | |||
// read all of stdin line by line | |||
while (fgets(line, MAXLINE, stdin)) { | |||
// do something with line | |||
} | |||
// loop stops when there's no more input | |||
</source> | |||
The following C program reads the content of stdin ''line by line'' and simply re-outputs it unchanged. In this way, this code could be the basis for a text filter. | |||
Note how ''MAXLINE'' is defined as a compiler directive to tell C how much space to create for the line variable, both (1) when declaring the variable, and (2) when calling the fgets function. The "%s" format code means to output the contents of line as a ''string'' or sequence of characters (which it is). | |||
Note how ''MAXLINE'' is defined as a compiler directive to tell C how much space to create for the line variable, | |||
both (1) when declaring the variable, and (2) when calling the fgets function. | |||
<source lang="c"> | <source lang="c"> | ||
Line 57: | Line 60: | ||
The following program prints the message "line is ??? characters long" with ??? filled with the result of calling the strlen function. What do you notice about the value strlen returns, is it correct (and if not, could you guess why that is?) | The following program prints the message "line is ??? characters long" with ??? filled with the result of calling the strlen function. What do you notice about the value strlen returns, is it correct (and if not, could you guess why that is?) | ||
Note how the code includes the ''string.h'' header file to make use of the ''strlen'' function defined within it. | Note how the code includes the ''string.h'' header file to make use of the ''strlen'' function defined within it. The "%d" format code means to output the contents of linelen as a ''decimal number''. | ||
<source lang="c"> | <source lang="c"> | ||
Line 119: | Line 122: | ||
</source> | </source> | ||
The same program, with a '''for''' loop instead of a | The same program, with a '''for''' loop instead of the inner '''while'''. For is a convenient shortcut for a more general purpose ''while'' and makes it's harder to forget to initialize or to increment the loop variable, but it takes a little getting used to what it means. | ||
<source lang="c"> | <source lang="c"> | ||
Line 151: | Line 154: | ||
// do something! | // do something! | ||
} | } | ||
[[Category:Cookbook]] |
Latest revision as of 22:40, 2 November 2010
How to use the programs on this page
Save the sample code as a file ending in .c, for instance "readlines.c", then from the command line, cd to the directory containing the file, and type:
gcc readlines.c -o readlines
or to include debugging info (for use with gdb/ddd)
gcc -g readlines.c -o readlines
Then to run the program and feed it some text (such as itself), you could use:
./readlines < readlines.c
or perhaps, something like (just make sure the file is plain text):
./readlines < ~/Documents/alice.txt
Reading stdin line by line
fgets is a C function that reads a line of input from a file. It takes three arguments (inputs):
fgets(line, maxchars, file)
- line: the name of a variable in which to store the result, this should be a character array (pointer) with enough space to store the line,
- maxchars: the maximum number of characters possible in a line (the function will never try to read more than this many characters, even if a line is longer),
- file: the name of the file to read from, here we use stdin to read from whatever is piped to this program.
fgets returns a value indicating whether or not it was able to read any input. In this way, it's possible to use as the condition of a while loop to do something with all available input.
// read all of stdin line by line
while (fgets(line, MAXLINE, stdin)) {
// do something with line
}
// loop stops when there's no more input
The following C program reads the content of stdin line by line and simply re-outputs it unchanged. In this way, this code could be the basis for a text filter.
Note how MAXLINE is defined as a compiler directive to tell C how much space to create for the line variable, both (1) when declaring the variable, and (2) when calling the fgets function. The "%s" format code means to output the contents of line as a string or sequence of characters (which it is).
#include "stdio.h"
#define MAXLINE 1000
int main () {
char line[MAXLINE];
while (fgets(line, MAXLINE, stdin)) {
printf("%s", line);
}
// returning 0 from main is the convention to indicate that the program finished normally
return 0;
}
The following program prints the message "line is ??? characters long" with ??? filled with the result of calling the strlen function. What do you notice about the value strlen returns, is it correct (and if not, could you guess why that is?) Note how the code includes the string.h header file to make use of the strlen function defined within it. The "%d" format code means to output the contents of linelen as a decimal number.
#include "stdio.h"
#include "string.h"
#define MAXLINE 1000
int main () {
int i=0;
int linelen;
char line[MAXLINE];
while (fgets(line, MAXLINE, stdin)) {
linelen = strlen(line);
printf("line is %d characters long\n", linelen);
}
return 0;
}
Exercise: Line Numbering
Exercise: Write a program that adds line numbers to each line given to it via stdin.
The first argument to printf is the "format" string, which works like a kind of template. It includes support for "padding" values:
printf("%04d\n", 27); printf("%06d\n", 27);
would output:
0027 000027
Exercise: Use string padding to pad the line numbers of your line numbering program.
Processing each line character by character
To do some simple filtering of each line, it's possible to use a nested loop to do something with each character in a line.
#include "stdio.h"
#include "string.h"
#define MAXLINE 1000
int main () {
char line[MAXLINE];
int linelen;
int i;
while (fgets(line, MAXLINE, stdin)) {
linelen = strlen(line);
i=0;
while (i<linelen) {
printf("%c ", line[i]);
i++;
}
printf("\n");
}
return 0;
}
The same program, with a for loop instead of the inner while. For is a convenient shortcut for a more general purpose while and makes it's harder to forget to initialize or to increment the loop variable, but it takes a little getting used to what it means.
#include "stdio.h"
#include "string.h"
#define MAXLINE 1000
int main () {
char line[MAXLINE];
int linelen;
int i;
while (fgets(line, MAXLINE, stdin)) {
linelen = strlen(line);
for (i=0; i<linelen; i++) {
printf("%c ", line[i]);
}
printf("\n");
}
return 0;
}
Exercise: Punctuation only filter
Exercise: The ctypes.h header includes a function called ispunct, which returns True if a given character is punctuation. Modify the code above to have a program that prints only the punctuation of a file (it a character is not punctuation, print a space.
if (ispunct(c)) { // do something! }