Ctype Function: ispunct()


For the ctype ispunct() function, the goal is to understand that “punct” is short for punctuation and not puncture. To put this function to use you need to know what the library considers to be an ASCII punctuation character. It’s yet another step forward in my ongoing exploration of the ctype functions.

According to the ispunct() function, the following ASCII characters are not considered punctuation:

  • All control codes
  • The space
  • Numbers
  • Uppercase letters
  • Lowercase letters
  • The DEL character (code 127)

The following code uses the ispunct() function to sort out the lot of ASCII characters, from zero through 127 (the full ASCII code range):

2026_06_20-Lesson-a.c

#include <locale.h>
#include <wchar.h>
#include <ctype.h>

/* output the wide ASCII character
   specifically the control codes */
void outwide(int c)
{
    if( iscntrl(c) )
    {
        if( c==127 )
            putwchar(9249);    /* DEL */
        else
            /* 9216 = control code chars */
            putwchar(c+9216);
    }
    else
    {
        putwchar(c);
    }
}

int main()
{
    int ch;

    /* set the locale for wide characters */
    setlocale(LC_ALL,"");

    wprintf(L"Punctuation characters:\n");
    /* ASCII range */
    for( ch=0; ch<=127; ch++ )
        if( ispunct(ch) )
            outwide(ch);
    putwchar(L'\n');

    wprintf(L"Not punctuation characters:\n");
    /* ASCII range */
    for( ch=0; ch<=127; ch++ )
        if( !ispunct(ch) )
            outwide(ch);
    putwchar(L'\n');

    return 0;
}

I wrote the outwide() function to avoid some repetition in the main() function. Its job is to output the wide character versions of the control codes (ASCII zero through 31) as well as the DEL (code 127) as appropriate Unicode values.

The main() function contains two for loops. Each one uses the ispunct() function to test the value of ASCII code ch. The first loop outputs only what are considered to be punctuation characters. The second for loop outputs all the non-punctuation characters, which includes all the control codes as well as the DEL.

Here is sample output:

Punctuation characters:
!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~
Not punctuation characters:
␀␁␂␃␄␅␆␇␈␉␊␋␌␍␎␏␐␑␒␓␔␕␖␗␘␙␚␛␜␝␞␟ 0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz␡

In the following code, I’ve written my own ispunct() function. I also borrowed the iscntrl() function from last week’s Lesson:

2026_06_20-Lesson-b.c

#include <locale.h>
#include <wchar.h>
#include <stdbool.h>

/* is the character a control code? */
int iscntrl(int c)
{
    if( (c>=0 && c<=31) || c==127 )
        return true;
    else
        return false;
}

/* is the character "punctuation"? */
int ispunct(int c)
{
    /* eliminate control codes & space */
    if( c>=0 && c<=' ')
        return false;
    /* eliminate numbers/digits */
    if( c>='0' && c<='9' )
        return false;
    /* eliminate uppercase */
    if( c>='A' && c<='Z' )
        return false;
    /* eliminate lowercase */
    if( c>='a' && c<='z' )
        return false;
    /* eliminate DEL */
    if( c==127 )
        return false;

    return true;
}

/* output the wide ASCII character
   specifically the control codes */
void outwide(int c)
{
    if( iscntrl(c) )
    {
        if( c==127 )
            putwchar(9249);    /* DEL */
        else
            /* 9216 = control code chars */
            putwchar(c+9216);
    }
    else
    {
        putwchar(c);
    }
}

int main()
{
    int ch;

    /* set the locale for wide characters */
    setlocale(LC_ALL,"");

    wprintf(L"Punctuation characters:\n");
    /* ASCII range */
    for( ch=0; ch<=127; ch++ )
        if( ispunct(ch) )
            outwide(ch);
    putwchar(L'\n');

    wprintf(L"Not punctuation characters:\n");
    /* ASCII range */
    for( ch=0; ch<=127; ch++ )
        if( !ispunct(ch) )
            outwide(ch);
    putwchar(L'\n');

    return 0;
}

My ispunct() function contains a towering series of if conditions, each of which weeds out the non-punctuation characters as listed at the start of this post. I could have also written a switch-case structure to list the 32 characters that the ispunct() function qualifies as punctuation. I could have also added the isalnum() function (my own version) to help fish out the letters and numbers. Anyway, you get the idea.

For next week’s Lesson, I wrap up this series on the ctype functions with the final one: isxdigit().

Leave a Reply