Last active
December 12, 2015 01:39
-
-
Save maxdeliso/4692931 to your computer and use it in GitHub Desktop.
Safely apply rotation transformation to user specified strings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| * 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