Skip to content

Instantly share code, notes, and snippets.

@maxdeliso
Last active December 12, 2015 01:39
Show Gist options
  • Save maxdeliso/4692931 to your computer and use it in GitHub Desktop.
Save maxdeliso/4692931 to your computer and use it in GitHub Desktop.
Safely apply rotation transformation to user specified strings.
CC=gcc
CFLAGS=-std=c99 -O1 -g -Wall -Wextra -pedantic
OUT=rotate
RM=rm
.PHONY: clean
rotate: rotate.c makefile
$(CC) $(CFLAGS) -o $(OUT) rotate.c
clean:
$(RM) rotate
/*
* file: rotate.c
* desc: Safely apply rotation transformation to user specified strings.
* lang: c99
* note: compile with: clang -std=c99 -Weverything -g -o rotate rotate.c
* me: Max DeLiso
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <assert.h>
#define LINE_BUFFER_SIZE 4096
#define CHARS_IN_ALPHABET 26
#define FIRST_UPPER_ALPHABET_CHAR 'A'
void strRotate( char* const str, const size_t strLen, const int k );
int main(int argc, char** argv) {
if(argc != 3) {
fprintf(stderr, "%s - n | %s str n\n", argv[0], argv[0]);
return 1;
/* if the first argument is a single -, read line by line from stdin */
} else if( strlen(argv[1]) == 1 && argv[1][0] == '-' ) {
const int userK = atoi(argv[2]);
char userBuf[LINE_BUFFER_SIZE];
int itemsRead;
do {
itemsRead = 0;
int fullInput;
/* while we can read characters without hitting EOF or
* encountering an error state or newline */
for(
int i = 0;
i < LINE_BUFFER_SIZE &&
!feof(stdin) &&
((fullInput = getchar()) != EOF) &&
((userBuf[i] = (char) fullInput) != '\n');
++i) {
itemsRead = i + 1;
}
/* if something was read ... */
if( itemsRead > 0 ) {
/* rotate it */
strRotate(userBuf, (size_t)itemsRead, userK);
/* null terminate it */
userBuf[itemsRead] = 0;
/* and print it back right away */
printf("%s\n", userBuf);
fflush(stdout);
}
} while ( !feof(stdin) && itemsRead > 0 );
/* otherwise just use the first argument as input */
} else {
char* userStr = argv[1];
int userK = atoi(argv[2]);
/* mutate & echo */
strRotate(userStr, strlen( userStr ), userK );
printf("%s\n", userStr);
}
return 0;
}
/* in place mutation of the strLen characters pointed at by str,
* rotating them k elements around modulo 26. all characters get
* automatically converted to uppercase. non-alpha chars are
* ignored
*
* pre: str is non-null
* pre: strLen is > 0
* */
void strRotate( char* const str, const size_t strLen, const int k ) {
assert(str != NULL);
assert(strLen > 0);
/* ensure that k is in the proper range */
int adjustedK = k % CHARS_IN_ALPHABET;
if( adjustedK < 0 ) {
adjustedK = (CHARS_IN_ALPHABET + adjustedK);
}
const int finalK = adjustedK;
/* loop over the given string, applying the transformation to chars */
for( unsigned int i = 0; i < strLen; ++i ) {
if( isalpha( str[i] ) ) {
signed int charOrdinal = toupper(str[i]) -
FIRST_UPPER_ALPHABET_CHAR;
signed int shiftedCharIndex = (charOrdinal + finalK) %
CHARS_IN_ALPHABET;
str[i] = (char)(FIRST_UPPER_ALPHABET_CHAR + shiftedCharIndex);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment