Using stdin in C

Kua

Kua

Associate
Joined
21 Jul 2008
Posts
512
Location
Lancaster
Hiya

I've just started a second year C course. We were asked to write a Caesar Cipher. Here's my effort (any suggestions welcome). I meet all the marking criteria apart from we have to make sure we read the input from stdin. May be I've done that already. I'm not sure. As far as I understand it stdin is simply an input stream. When I prompt the user for their message am I not already using the input stream?

Code:
	eek!
 
Last edited:
Soldato
Joined
16 May 2005
Posts
6,509
Location
Cold waters
Few things I notice:
  • Your scanf and getchar usage probably covers what they meant by reading from stdin.
  • You should check the number of arguments (argc) before trying to use them (argv).
  • That while(getchar() ... ) in main will just munch characters without doing anything with them. Not sure why it's there.
  • Using the decimal representations of ASCII characters is unnecessary and hard to read. You can compare against character literals directly, i.e. ch>='A' instead of ch>=65
  • I don't think putchar(stdin) there makes sense.

I was bored so I did a version. Probably differs from the exact spec yours was made to fill, and probably has bugs, but take a look. It deals with whole files rather than lines of text, so you could test the full encode/decode round trip with this in a unix shell:

Code:
$ cat memo.txt | ./cipher encode 11 | ./cipher decode 11

Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

void code(int shift);
void usage(char* exe);
char shift_in_range(char range_start, char range_end, char ch, int shift);

int main(int argc, char** argv)
{
    int shift, encode, decode;
    
    if (argc != 3)
    {
        usage(argv[0]);
        return EXIT_FAILURE;
    }
    
    shift = atoi(argv[2]);
    if (shift == 0)
    {
        usage(argv[0]);
        return EXIT_FAILURE;
    }
    
    encode = strcmp(argv[1], "encode") == 0;
    decode = strcmp(argv[1], "decode") == 0;
    
    if (encode)
    {
        code(shift);
    }
    else if (decode)
    {
        code(-shift);
    }
    else
    {
        usage(argv[0]);
        return EXIT_FAILURE;        
    }
    
    return EXIT_SUCCESS;    
}

void usage(char* exe)
{
    fprintf(stderr, "usage: %s encode|decode <shift-length>\n", exe);
}

void code(int shift)
{
    char ch;
    
    while ( (ch = getchar()) != EOF)
    {
        if (islower(ch))
        {
            putchar(shift_in_range('a', 'z', ch, shift));
        }
        else if (isupper(ch))
        {
            putchar(shift_in_range('A', 'Z', ch, shift));
        }
        else
        {
            putchar(ch);            
        }        
    }
    
    return;    
}

char shift_in_range(char range_start, char range_end, char ch, int shift)
{
    int ch_shifted, range_length, overrun, underrun;
    
    range_length = range_end + 1 - range_start;    
    ch_shifted = ch + shift;    
    
    if (ch_shifted > range_end)
    {
        overrun = ch_shifted - range_end;
        return range_start + (overrun % range_length);
    }
    else if (ch_shifted < range_start)
    {
        underrun = range_start - ch_shifted;
        return range_end - (underrun % range_length);
    }
    else
    {
        return ch_shifted;
    }
}
 
Last edited:
Associate
Joined
16 Dec 2009
Posts
330
Location
Birmingham
don't forget to use fflush(stdin); elsse your likely to get some bugs.

stdin is the standard input buffer. Think of it like an array where whenever you type something whatever you typed then goes to the input buffer. i.e.
if you typed 'hello' the input buffer would be:
123456
hello\n
when you use getchar() its actually taking a single value from the input buffer so it would read 'h', next time you call it it would read 'e' and so on.

Notice that '\n' is a single value in the input buffer. This happens whenever a new line is entered, there are other escape sequences all of which are used by the input buffer. be careful with input buffers because of this. If you don't use the fflush(stdin); before each time you request a user input it may cause the program to read an unintended character (based on what is in the input buffer). If you use scanf() it doesnt matter as this takes a set sequence of data only.

To answer the question you access the input stream (keyboard entry in this case) by using one of the following:

scanf(); (stdio.h)
getchar(); (stdlib.h)
getch(); and getche() (conio.h)

hope this helps
 
Soldato
Joined
12 Dec 2003
Posts
8,141
Location
East Sussex
Posting code and assessment descriptions is a bad idea man. I'd definitely get done for plagiarism if I got caught doing that. You do realise that there's members of faculty in Computer Science departments throughout the country looking for people like you?
 
Soldato
Joined
16 May 2005
Posts
6,509
Location
Cold waters
That sort of coarse grained policing is a shame really because the ease of bouncing ideas around and getting help online is one of the best things about being a programmer.
 
Soldato
Joined
12 Dec 2003
Posts
8,141
Location
East Sussex
That sort of coarse grained policing is a shame really because the ease of bouncing ideas around and getting help online is one of the best things about being a programmer.

I totally understand where you're coming from and I somewhat agree but there's a difference between formulating a sensible question that helps and just pasting code, a rough assessment description and asking for "suggestions" .
 
Back
Top Bottom