Is this code a portable?

Discussion in 'C Programming' started by Robert Bachmann, Feb 9, 2004.

  1. Two years I wrote a simple cesar encryption program, it worked but it
    relied on ASCII.
    So today I tried to make an portable cesar encryption.
    Please tell me if the code below is really protable.

    Thanks in advance.

    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <ctype.h>
    #include <locale.h>

    char
    letters_a_z[] = "zabcdefghijklmnopqrstuvwxy",
    letters_A_Z[] = "ZABCDEFGHIJKLMNOPQRSTUVWXY",
    letters_a_z_rot[] = "abcdefghijklmnopqrstuvwxyz",
    letters_A_Z_rot[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    int main (void)
    {
    int ch;

    setlocale (LC_CTYPE, "C");

    while ((ch = getc (stdin)) != EOF)
    {
    if (isupper (ch))
    ch = letters_A_Z_rot[strchr (letters_A_Z, ch) - letters_A_Z];
    else if (islower (ch))
    ch = letters_a_z_rot[strchr (letters_a_z, ch) - letters_a_z];

    putc (ch, stdout);
    }

    return 0;
    }


    --
    Robert Bachmann, Feb 9, 2004
    #1
    1. Advertising

  2. Robert Bachmann wrote:
    > Two years I wrote a simple cesar encryption program, it worked but it
    > relied on ASCII.
    > So today I tried to make an portable cesar encryption.
    > Please tell me if the code below is really protable.
    >
    > Thanks in advance.
    >
    > #include <stdlib.h>
    > #include <stdio.h>
    > #include <string.h>
    > #include <ctype.h>
    > #include <locale.h>
    >
    > char
    > letters_a_z[] = "zabcdefghijklmnopqrstuvwxy",
    > letters_A_Z[] = "ZABCDEFGHIJKLMNOPQRSTUVWXY",
    > letters_a_z_rot[] = "abcdefghijklmnopqrstuvwxyz",
    > letters_A_Z_rot[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    >
    > int main (void)
    > {
    > int ch;
    >
    > setlocale (LC_CTYPE, "C");
    >
    > while ((ch = getc (stdin)) != EOF)
    > {
    > if (isupper (ch))
    > ch = letters_A_Z_rot[strchr (letters_A_Z, ch) - letters_A_Z];
    > else if (islower (ch))
    > ch = letters_a_z_rot[strchr (letters_a_z, ch) - letters_a_z];
    >
    > putc (ch, stdout);
    > }
    >
    > return 0;
    > }


    For 8 bit character sets it is OK, you might need to check for SJIS and
    Big5 characters sets.

    This might be a tad faster but it relies on 8 bit character sets as well.

    #include <stdio.h>

    char key_array[256] = {
    ['A']='Z',
    ['B']='Y',
    ['C']='X',
    ['D']='W',
    ['E']='V',
    ['F']='U',
    ['G']='T',
    ['H']='S',
    ['I']='R',
    ['J']='Q',
    ['K']='P',
    ['L']='O',
    ['M']='N',
    ['N']='M',
    ['O']='L',
    ['P']='K',
    ['Q']='J',
    ['R']='I',
    ['S']='H',
    ['T']='G',
    ['U']='F',
    ['V']='E',
    ['W']='D',
    ['X']='C',
    ['Y']='B',
    ['Z']='A',
    ['a']='z',
    ['b']='y',
    ['c']='x',
    ['d']='w',
    ['e']='v',
    ['f']='u',
    ['g']='t',
    ['h']='s',
    ['i']='r',
    ['j']='q',
    ['k']='p',
    ['l']='o',
    ['m']='n',
    ['n']='m',
    ['o']='l',
    ['p']='k',
    ['q']='j',
    ['r']='i',
    ['s']='h',
    ['t']='g',
    ['u']='f',
    ['v']='e',
    ['w']='d',
    ['x']='c',
    ['y']='b',
    ['z']='a',
    };

    int main (void)
    {
    int ch;

    while ( (ch = getc (stdin)) != EOF)
    {

    int ch2;

    ch = ( ch2 = key_array[ ch & 0xff ] ) ? ch2 : ch;

    putc (ch, stdout);


    }

    return 0;
    }
    Gianni Mariani, Feb 9, 2004
    #2
    1. Advertising

  3. Robert Bachmann

    Eric Sosman Guest

    Robert Bachmann wrote:
    >
    > Two years I wrote a simple cesar encryption program, it worked but it
    > relied on ASCII.
    > So today I tried to make an portable cesar encryption.
    > Please tell me if the code below is really protable.
    >
    > Thanks in advance.
    >
    > #include <stdlib.h>
    > #include <stdio.h>
    > #include <string.h>
    > #include <ctype.h>
    > #include <locale.h>
    >
    > char
    > letters_a_z[] = "zabcdefghijklmnopqrstuvwxy",
    > letters_A_Z[] = "ZABCDEFGHIJKLMNOPQRSTUVWXY",
    > letters_a_z_rot[] = "abcdefghijklmnopqrstuvwxyz",
    > letters_A_Z_rot[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    >
    > int main (void)
    > {
    > int ch;
    >
    > setlocale (LC_CTYPE, "C");
    >
    > while ((ch = getc (stdin)) != EOF)
    > {
    > if (isupper (ch))
    > ch = letters_A_Z_rot[strchr (letters_A_Z, ch) - letters_A_Z];
    > else if (islower (ch))
    > ch = letters_a_z_rot[strchr (letters_a_z, ch) - letters_a_z];
    >
    > putc (ch, stdout);
    > }
    >
    > return 0;
    > }


    This should work, because the setlocale() causes the
    isupper() and islower() functions to consider only the
    fifty-two letters A-Z and a-z as alphabetic. (However,
    the setlocale() call should be unnecessary: according to
    the Standard, every program begins in the "C" locale.)

    You might want to consider some improvements, though;
    it's almost always better to achieve a goal with less code
    instead of more. One suggestion is to handle both upper-
    and lower-case in a single operation:

    char alpha[] = "abc...xyzABC...XYZ";
    char coded[] = "bcd...yzaBCD...YZA";
    ...
    if (isalpha(ch))
    ch = coded[ strchr(alpha, ch) - alpha ];

    Another possibility is to do away with the isalpha()
    test by using the alpha[] array itself to define the
    characters that are subject to change. With the arrays
    as above you could write

    char *p;
    ...
    p = strchr(alpha, ch);
    if (p != NULL)
    ch = coded[p - alpha];

    This may not look like a big improvement and it may in
    fact be just a hair slower than the prior version, but it
    has an advantage: it generalizes to let you encode non-
    alphabetic characters as well. For example, you could
    scramble digits as well as letters, or spaces and other
    puncutation, just by changing the two arrays.

    Finally, on machines with "normal" character sets of
    256 or so distinct codes, there's a technique that is even
    more general and (after some initial setup) probably faster.
    The idea is to build a table giving the coded equivalent of
    every possible character; this will be the identity mapping
    for many characters, but will be something else for the
    enciphered characters. You'd set the table up like this:

    #include <limits.h> /* for UCHAR_MAX */

    char caesar[1+UCHAR_MAX];
    int i;
    for (i = 0; i <= UCHAR_MAX; ++i)
    caesar = i; /* the identity mapping */
    for (i = 0; alpha != '\0'; ++i)
    caesar[ alpha ] = coded;

    Once the table is built, the actual processing reduces to

    while ((ch = getc(stdin)) != EOF)
    putc (caesar[ch], stdout);

    .... which is almost as simple as one can get. Of course,
    this technique is viable only for "normal" character sets;
    on machines with (for example) 32-bit characters, the table
    would become unwieldy and `i' might not work as a plain `int'.

    --
    Eric Sosman, Feb 9, 2004
    #3
  4. Gianni Mariani wrote:
    > Robert Bachmann wrote:

    [code snipped]

    > For 8 bit character sets it is OK, you might need to check for SJIS and
    > Big5 characters sets.

    I think it should be OK also for n bit character sets.
    (Where n is >= 8)
    Of course it wouldn't encode other characters then
    "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ". (without " of
    course)

    > This might be a tad faster but it relies on 8 bit character sets as well.
    >
    > #include <stdio.h>
    >
    > char key_array[256] = {
    > ['A']='Z',
    > ['B']='Y',
    > ['C']='X',

    [...]
    > ['Y']='B',
    > ['Z']='A',
    > ['a']='z',
    > ['b']='y',

    [...]
    > ['y']='b',
    > ['z']='a',

    The key should be
    ['A']='B',
    ['B']='C',
    ['C']='D',
    ....
    ['Y']='Z',
    ['Z']='A',
    etc.

    [snipped]



    --
    Robert Bachmann, Feb 9, 2004
    #4
  5. In article <c08sn2$>,
    Gianni Mariani <> wrote (slightly edited)

    char k[1]={[0]=0};

    Is this C?

    Francois Grieu
    Francois Grieu, Feb 10, 2004
    #5
  6. Irrwahn Grausewitz, Feb 10, 2004
    #6
  7. Eric Sosman wrote:
    > Robert Bachmann wrote:

    [...]
    > You might want to consider some improvements, though;
    > it's almost always better to achieve a goal with less code
    > instead of more. One suggestion is to handle both upper-
    > and lower-case in a single operation:
    >
    > char alpha[] = "abc...xyzABC...XYZ";
    > char coded[] = "bcd...yzaBCD...YZA";
    > ...
    > if (isalpha(ch))
    > ch = coded[ strchr(alpha, ch) - alpha ];
    >
    > Another possibility is to do away with the isalpha()
    > test by using the alpha[] array itself to define the
    > characters that are subject to change. With the arrays
    > as above you could write
    >
    > char *p;
    > ...
    > p = strchr(alpha, ch);
    > if (p != NULL)
    > ch = coded[p - alpha];
    >

    Thanks for that advice, that will make things a little bit simpler.

    P.S:
    I just realized that the subject line should have been "Is this code a
    portable one?" or "Is this code portable?".

    --
    Robert Bachmann, Feb 10, 2004
    #7
  8. In article <>,
    Irrwahn Grausewitz <> wrote:

    > Francois Grieu <> wrote:
    > > Gianni Mariani <> wrote (slightly edited)
    > >
    > >char k[1]={[0]=0};
    > >
    > >Is this C?

    >
    > Designated initializers are a new feature of C99, providing
    > a mechanism for initializing "sparse" aggregates.
    > See: C99 6.7.8 Initialization


    Wow ! Thanks for pointing this out. Can be usefull for
    conpile-time-initialized sparse arrays.


    Francois Grieu
    Francois Grieu, Feb 11, 2004
    #8
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Eli Bendersky
    Replies:
    1
    Views:
    1,161
    Mike Treseler
    Mar 1, 2006
  2. Shin
    Replies:
    5
    Views:
    4,310
  3. The Saqe

    Looking for portable C++ code

    The Saqe, Sep 23, 2003, in forum: C++
    Replies:
    3
    Views:
    352
    Noah Roberts
    Sep 24, 2003
  4. Rolf Hemmerling
    Replies:
    3
    Views:
    758
    Roger Leigh
    Oct 31, 2003
  5. Replies:
    7
    Views:
    914
Loading...

Share This Page