The C Standard Library

Programming Paradigms


Logical Operators

  • C has logical operators !, && and ||, in decreasing order of precedence

  • If a is 0 then !a is 1 and !a is 0 otherwise - NOT

  • a&&b is 1 if both a and b are non-zero and is 0 otherwise - AND

  • a||b is 0 if both a and b are 0 and is 1 otherwise - OR

  • How can you use logical operators to change an int to 0 if it is false and 1 if it is true? - !!c

  • What is the value of !1||0&&1? - 0

  • The operators && and || are short-circuiting:

    • If the first thing gives the result already, then don’t evaluate the second thing, e.g. an and with 0 as the first operator doesn’t need anything more

Classifying Characters

  • C has various functions to classify different sorts of characters. These functions are declared in ctype.h

    #include<ctype.h>
    int isdigit(int c);
    
  • This function returns a non-zero value if the character c is a digit ('0'-'9') and zero otherwise.

  • c must be either in the range of an unsigned char or equal to EOF (otherwise behaviour is undefined)

  • Why does c have type int not char?

  • How could we implement it?

Examples

  • int isalnum(int c); alphanumeric

  • int isalpha(int c); alphabetic character

  • int isblank(int c); space or tab character

  • int iscntrl(int c); control character (0x00-0x1F and 0x7F)

  • int isgraph(int c); printable character other than space

  • int islower(int c); lowercase character

  • int isprint(int c); printable character including space

  • int ispunct(int c); printable character other than space or an alphanumeric character

  • int isspace(int c); whitespace character (' ', '\f', '\n', '\r', '\t' or 'v')

  • int isupper(int c); uppercase character

  • int isxdigit(int c); hexadecimal digit

More Input/Output stdio.h

  • We’ve previously seen printf() and scanf(), along with the variants fprintf(), sprintf(), fscanf() and sscanf().

  • sprintf() puts a formatted string into the array pointed to by str

    int sprintf(char *str, const char *format, ...);
    
  • snprintf() does the same, but puts at most size-1 characters into the array. Why might you want this?

    int snprintf(char *str, size_t size,
        const char *format, ...);
    
  • Aside: variants of these functions with bounds checking were introduced as an optional feature in C11 (see Annex K of the C standard): scanf_s(), printf_s() etc. They work in subtely different ways to the normal variants and NO compilers implement them entirely correctly. These functions are likely to be deprecated/removed in the future, so avoid using them.

More Input/Output stdio.h

  • feof() returns a non-zero value if the end of file has been reached and zero if not. This only happens if you have tried to read past the last character in the file, not if you have only read the last character.

    int feof(FILE *stream);
    
  • fgets() reads in at most size-1 characters from the file stream and stores them in the char array s, null-terminated.

    char *fgets(char *s, int size, FILE *stream);
    
  • fgets() keeps reading until it either reaches a newline '\n' (which will be included in the string s) or it reaches the end of the file.

  • Returns s on success and NULL on failure (if end-of-file has been reached and no bytes are read, this counts as failure)

More Input/Output stdio.h

  • fputs() writes every character from the null-terminated string s into the file stream stream

    int fputs(const char *s, FILE *stream);
    
  • puts() prints s to the screen followed by a newline '\n'

    int puts(const char *s);
    
  • fputc() writes the character c (cast to an unsigned char) to the file stream

    int fputc(int c, FILE *stream);
    
  • putchar() writes the character c to the screen

    int putchar(int c);
    
  • Aside: printing to the screen is often buffered. Once you are done writing, it is often good to print a newline, at which point the buffer will be flushed.

More Input/Output stdio.h

  • fgetc() gets a single character from the input stream (i.e. file) and returns it as an unsigned char cast to an int or EOF on error.

    int fgetc(FILE *stream);
    
  • getchar() works equivalently to fgetc(stdin)

    int getchar(void);
    
  • ungetc() lets you push back one character onto the stream. This will be the first character read on future reads from the stream. You are only guaranteed to be able to push back one character, but it does NOT have to be the character you read from the stream.

    int ungetc(int c, FILE *stream);
    

Random Numbers (stdlib.h)

  • rand() generates random numbers between 0 and RAND_MAX

  • srand() sets the seed of the random number generator. If srand() is given the same seed, it should produce the same sequence of random numbers from rand()

  • The random-number generator is not cryptographically secure!

  • Typical practice is to use the current time as the seed:

    #include <stdio.h>
    #include <stdlib.h>
    #include <time.h>
    
    ...
    srand(time(NULL));
    int random_number=rand();