C Loops: Difference between revisions

From XPUB & Lens-Based wiki
 
(6 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 (parameters):
''fgets'' is a C function that reads a line of input from a file. It takes three arguments (inputs):


fgets(line, maxchars, file)
<source lang="c">
fgets(line, maxchars, file)
</source>


# line: the name of a variable in which to store the result,
# ''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),
# ''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.
# ''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 keep reading each line until no more input is available (at which time ''fgets'' returns 0 and the while loop stops).
''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
<source lang="c">
    while (fgets(line, MAXLINE, stdin)) {
// read all of stdin line by line
        // do something with line
while (fgets(line, MAXLINE, stdin)) {
    }
    // do something with line
    // loop stops when there's no more input
}
// 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.


The following C program reads the content of stdin ''line by line'' and simply re-outputs it through unchanged. In this way, this could be seen as the basis for writing some sort of text filter program.
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 '''while'''.
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">

Latest revision as of 23: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)
  1. 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,
  2. 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),
  3. 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!
 }