C pointers in reversi games - c

I want to that this function after than player 1 puts position program chack where on the left is player's 1 pawn and all of opponent's paws between player's 1 two pawns turning on 'X', like in reversi games.
This is whole unfinished code:
#include<stdio.h>
#define SIZE 7
char board[SIZE][SIZE];
char letter;
int number;
void make_board(char tab[SIZE][SIZE]){
int w,k;
for(w=0; w < SIZE; w++){
for(k=0; k < SIZE; k++){
tab[w][k] = '.';
}
}
tab[0][0] = 'X';
tab[1][0] = '1';
tab[2][0] = '2';
tab[3][0] = '3';
tab[4][0] = '4';
tab[5][0] = '5';
tab[6][0] = '6';
tab[0][1] = 'A';
tab[0][2] = 'B';
tab[0][3] = 'C';
tab[0][4] = 'D';
tab[0][5] = 'E';
tab[0][6] = 'F';
tab[4][4] = 'X';
tab[4][3] = 'O';
tab[3][4] = 'O';
tab[3][3] = 'X';
}
char draw_board(char tab[SIZE][SIZE]){
int w, k;
for(w=0; w < SIZE; w++){
for(k=0; k < SIZE; k++){
printf("%2c", tab[w][k]);
}
printf("\n");
}
}
int translate(char letter){
int letter_to_number;
switch(letter){
case 'A':
case 'a':
letter_to_number = 1;
break;
case 'B':
case 'b':
letter_to_number = 2;
break;
case 'C':
case 'c':
letter_to_number = 3;
break;
case 'D':
case 'd':
letter_to_number = 4;
break;
case 'E':
case 'e':
letter_to_number = 5;
break;
}
return letter_to_number;
}
int finished(char tab[SIZE][SIZE]){ // looking '.' in array
int i,j;
for(i=1;i<=SIZE;i++){
for(j=1;j<=SIZE;j++){
if(tab[i][j]=='.'){
return 1;
}else{
return 0; // if don't find any '.' game is finish
}
}
}
}
void hit(char tab[SIZE][SIZE], int player ){
int i,j;
int *poz1, *poz2;
printf("Call out a letter and a number of a row and column on the grid:\n");
scanf(" %c %d", &letter, &number);
i=translate(letter);
poz1=&tab[number][i];
if(tab[number][i]=='.'){
if(player==1){
*poz1='X';
for(poz1-1;*poz1=='X';poz1--){
poz2=&poz1;}
poz1=&tab[number][i];
for(poz2;poz2<=poz1;poz2++){
*poz2='X';}
}else{
*poz1='O';
for(poz1-1;*poz1=='O';poz1--){
poz2=&poz1;}
poz1=&tab[number][i];
for(poz2;poz2<=poz1;poz2++){
poz2='O';}
}
}else{
printf("On this place already is pawn\n");
}
draw_board(board);
getchar();
}
int main(){
int i,j,k, pg1=0, pg2=0, player=1;
make_board(board);
draw_board(board);
do{
if(player==1){
printf("Player 1\n");
hit(board, gracz);
k=finished(board);
gracz=2;
}else{
printf("Player 2\n");
hit(board, gracz);
k=finished(board);
player=1;
}
}while(k==1);
for(i=1;i<=SIZE;i++){
for(j=1;j<=SIZE;j++){
if(board[i][j]=='X'){
pg1++;
}else{
pg2++;
}
}
}
if(pg1>pg2){
printf("Player 1 wins");
}else{
printf("Player 2 wins");
}
return 0;
}

Bit buggy code:
poz1=&tab[number][i];
if(tab[number][i]=='.'){
if(player==1){
*poz1='X';
for(poz1-1;*poz1=='X';poz1--){
poz2=&poz1;}
poz1=&tab[number][i];
for(poz2;poz2<=poz1;poz2++){
*poz2='X';}
How can you asgn &pos1 to pos2. For this you need pointer to a pointer, i.e, pos 2 should be declared as **pos2.
Also, what do you want to achieve by looping over poz1 (set 'X' earlier)?
Anyhow, some cleanup to your code:
if(tab[number][i]=='.'){
if(player==1){ //considering player 1 is 'X'
// Loop to the left till you find opponent's piece or come to edge.
for(j=i-1;tab[number][j]=='O' && j!=0 ;j--)
;
// Validation check
if(i-j <=1 || tab[number][j] != 'X');
//Invalid move
return 1;
else
// convert all the opponents pieces between two of yours piece
for(k=i;k>j;k--)
tab[number][k] = 'X';
The above part of code is informative only..this will check if the move is valid for left side..and if valid convert the opponents pieces.. you need to understand this and put similar logic for "Right", "Diagonal" etc to complete the reversi game.

Related

Why my converter doesn't count the last digit?

This program is about converting Roman number to decimal number. The program can convert the alphabet to number but it can not process the last roman digit. I think my flow is alright but the output is not right. Can any body give me a helping hand?
#include <stdint.h>
#include <stdio.h>
#include <string.h>
int roman_to_int(const char s[], int length) {
// Please complete the function body
int ans = 0, value[length];
for (int i = 0; i < length; i++) {
switch (s[i]) {
case 'I': value[i] = 1; break;
case 'V': value[i] = 5; break;
case 'X': value[i] = 10; break;
case 'L': value[i] = 50; break;
case 'C': value[i] = 100; break;
case 'D': value[i] = 500; break;
case 'M': value[i] = 1000; break;
}
}
for (int i = 0; i < length - 1; i++) {
if (value[i] >= value[i+1])
ans += value[i];
else {
ans = ans + value[i+1] - value[i];
i++;
}
}
return ans;
}
int main() {
char roman_num[] = "III";
char roman_num_2[] = "CXXIII";
char roman_num_3[] = "MMMCDLIX";
printf("roman_to_int(%s) = %d\n", roman_num,
roman_to_int(roman_num, strlen(roman_num)));
printf("roman_to_int(%s) = %d\n", roman_num_2,
roman_to_int(roman_num_2, strlen(roman_num_2)));
printf("roman_to_int(%s) = %d\n", roman_num_3,
roman_to_int(roman_num_3, strlen(roman_num_3)));
}
You should add the value of the last roman digit after the end of the second loop.
As an alternative, you could make value on entry longer than n and set the last entry to 0 so you won't need the make a special case of the last roman digit.
Note that you should also handle the case of unrecognised roman digits: either by ignoring them or by returning an error code, such as a negative value -1.
It is also simpler for roman_to_int to take a null terminated C string and compute the length there.
Here is a modified version:
#include <stdio.h>
#include <string.h>
int roman_to_int(const char s[]) {
// Please complete the function body
int length = strlen(s);
int ans = 0, value[length + 1];
for (int i = 0; i < length; i++) {
switch (s[i]) {
case 'I': value[i] = 1; break;
case 'V': value[i] = 5; break;
case 'X': value[i] = 10; break;
case 'L': value[i] = 50; break;
case 'C': value[i] = 100; break;
case 'D': value[i] = 500; break;
case 'M': value[i] = 1000; break;
default: return -1;
}
}
value[length] = 0;
for (int i = 0; i < length; i++) {
if (value[i] >= value[i + 1])
ans += value[i];
else
ans -= value[i];
}
return ans;
}
int main() {
char roman_num[] = "III";
char roman_num_2[] = "CXXIII";
char roman_num_3[] = "MMMCDLIX";
char roman_num_4[] = "MMMCDLIZ"; // error
printf("roman_to_int(%s) = %d\n", roman_num, roman_to_int(roman_num));
printf("roman_to_int(%s) = %d\n", roman_num_2, roman_to_int(roman_num_2));
printf("roman_to_int(%s) = %d\n", roman_num_3, roman_to_int(roman_num_3));
printf("roman_to_int(%s) = %d\n", roman_num_4, roman_to_int(roman_num_4));
return 0;
}

C Program Incorrect Output

I am currently writing a program that is supposed to receive input from a text file and output statistics about the text such as the number of letters, size of words and how often they occur, and how many times each word occurs. However, every time I run the program, the wordLengthAnalysis does not produce the correct output. The other two run perfectly. Here is some sample text (The number represents how many lines are supposed to be read):
1
Hello my name is Bob
I live in Canada
Usually it is only off by one number. What should I do to correct my issue? I am very new to programming so I'm sure it is something basic.
#include <stdio.h>
#include <string.h>
#define MAX_WORD_LENGTH 20
#define MAX_LINES 10
#define MAX_LINE_LENGTH 80
void letterAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal);
int wordLengthAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal, int wordLength);
void wordAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal);
int main (void){
int lineTotal, wordSize;
scanf("%d\n", &lineTotal);
char text[lineTotal][MAX_LINE_LENGTH];
for(int i = 0; i < lineTotal; i++){
gets(text[i]);
}
printf("\n***Letter count analysis***\n");
letterAnalysis(text, lineTotal);
printf("\n***Word length analysis***\n");
for (int i = 1; i < 21; i++){
wordSize = wordLengthAnalysis(text, lineTotal, i);
if (wordSize == 1){
printf("\n%-2d\tword of length %d", wordSize, i);
}
else if (wordSize == 0){}
else{
printf("\n%-2d\twords of length %d", wordSize, i);
}
}
printf("\n\n***Word analysis***\n");
wordAnalysis(text, lineTotal);
return 0;
}
void letterAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
int alphabet[26] = {0};
for (int i = 0; i < lineTotal; i++){
for(int j = 0; j < MAX_LINE_LENGTH; j++){
switch(text[i][j]){
case 'A': case 'a':
alphabet[0]++;
break;
case 'B': case 'b':
alphabet[1]++;
break;
case 'C': case 'c':
alphabet[2]++;
break;
case 'D': case 'd':
alphabet[3]++;
break;
case 'E': case 'e':
alphabet[4]++;
break;
case 'F': case 'f':
alphabet[5]++;
break;
case 'G': case 'g':
alphabet[6]++;
break;
case 'H': case 'h':
alphabet[7]++;
break;
case 'I': case 'i':
alphabet[8]++;
break;
case 'J': case 'j':
alphabet[9]++;
break;
case 'K': case 'k':
alphabet[10]++;
break;
case 'L': case 'l':
alphabet[11]++;
break;
case 'M': case 'm':
alphabet[12]++;
break;
case 'N': case 'n':
alphabet[13]++;
break;
case 'O': case 'o':
alphabet[14]++;
break;
case 'P': case 'p':
alphabet[15]++;
break;
case 'Q': case 'q':
alphabet[16]++;
break;
case 'R': case 'r':
alphabet[17]++;
break;
case 'S': case 's':
alphabet[18]++;
break;
case 'T': case 't':
alphabet[19]++;
break;
case 'U': case 'u':
alphabet[20]++;
break;
case 'V': case 'v':
alphabet[21]++;
break;
case 'W': case 'w':
alphabet[22]++;
break;
case 'X': case 'x':
alphabet[23]++;
break;
case 'Y': case 'y':
alphabet[24]++;
break;
case 'Z': case 'z':
alphabet[25]++;
default: break;
}
}
}
for(int i = 0; i <= 25; i++){
printf("%c: \t%d\n", ('a' + i), alphabet[i]);;
}
}
int wordLengthAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal, int wordLength){
int sentenceLength;
int counter, wordSize = 0;
for(int i = 0; i < lineTotal; i++){
sentenceLength = strlen(&text[i][0]);
for(int j = 0; j < sentenceLength; j++){
if(text[i][j] == ' '){
if(counter == wordLength){
wordSize++;
counter = 0;
}
else{
counter = 0;
}
}
else{
counter++;
}
}
}
return wordSize;
}
void wordAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
char maxWords[800];
char word[MAX_LINE_LENGTH], word2[MAX_WORD_LENGTH], *ptrText, *ptrTextCounter;
int counter, textCounter = 0;
int sentenceLength, wordTracker;
int lineFlag;
for(int i = 0; i < lineTotal; i++){
ptrText = &text[i][0];
sentenceLength = strlen(ptrText);
counter = 0;
for (int j = 0; j < sentenceLength + 1; j++){
wordTracker = 1;
if (text[i][j] == ' ' ){
if (counter != 0){
sprintf(word, "%.*s", counter, ptrText);
ptrTextCounter = &text[i][j+1];
lineFlag = j;
if(strstr(maxWords, word) == NULL){
for (int k = i; k < lineTotal; k++){
textCounter = 0;
if (lineFlag == j){
ptrTextCounter = &text[i][j+1];
}
else{
lineFlag = 0;
ptrTextCounter = &text[i][j+1];
}
for ( ; lineFlag < sentenceLength; lineFlag++){
if(text[k][lineFlag] == ' '){
if (textCounter != 0){
if(textCounter == counter){
sprintf(word2, "%.*s", textCounter, ptrTextCounter);
if(strcmp(word, word2) == 0){
wordTracker++;
}
}
ptrTextCounter = &text[k][lineFlag + 1];
textCounter = 0;
}
else{
ptrTextCounter = &text[k][lineFlag+1];
}
}
else{
textCounter++;
}
}
}
if(wordTracker == 1){
printf("\n\"%.*s\"\t\tappeared %d time", counter, ptrText, wordTracker);
}
else{
printf("\n\"%.*s\"\t\tappeared %d times", counter, ptrText, wordTracker);
}
}
strcat(maxWords, word);
ptrText = &text[i][j+1];
counter = 0;
}
else{
ptrText = &text[i][j+1];
}
}
else{
counter++;
}
}
}
}
The problem is that you need to set counter to 0 at the start of every line.
for(int i = 0; i < lineTotal; i++){
sentenceLength = strlen(&text[i][0]);
counter = 0;
for(int j = 0; j < sentenceLength; j++){
You also need to check if the counter is equal at the end of each line.
for(int j = 0; j < sentenceLength; j++){
if(text[i][j] == ' '){
if(counter == wordLength){
wordSize++;
counter = 0;
}
else{
counter = 0;
}
}
else{
counter++;
}
}
if(counter == wordLength){
wordSize++;
counter = 0;
}
Hope this helps!

Segmentation Fault Error (C)

I am currently writing a program that is supposed to receive input from a text file and output statistics about the text such as the number of letters, size of words and how often they occur, and how many times each word occurs. However, every time I run the program, I get a segmentation fault error. The program runs until I hit the line Letter Count Analysis. The I receive the segmentation fault error. Here is some sample text:
1
Hello my name is Bob
I live in Canada
The number represents how many lines are supposed to be read. What should I do to correct my issue? I am very new to programming so I'm sure it is something basic.
#include <stdio.h>
#include <string.h>
#define MAX_LINE_LENGTH 80
#define MAX_WORD_LENGTH 20
#define MAX_LINES 10
void letterAnalysis(char [][MAX_LINE_LENGTH], int lineTotal);
int wordLengthAnalysis(char [][MAX_LINE_LENGTH], int lineTotal, int wordLength);
void wordAnalysis(char [][MAX_LINE_LENGTH], int lineTotal);
int main (void){
int lineTotal, wordSize;
char text[lineTotal][MAX_LINE_LENGTH];
char n[1];
fgets(n, 10, stdin);
lineTotal = n[0] - '0';
for(int i = 0; i < lineTotal; i++){
fgets(text[i], MAX_WORD_LENGTH, stdin);
}
printf("\n***Letter count analysis***\n");
letterAnalysis(text, lineTotal);
printf("\n***Word length analysis***\n");
for (int i = 1; i <= MAX_WORD_LENGTH; i++){
wordSize = wordLengthAnalysis(text, lineTotal, i);
if (wordSize == 1){
printf("\n%-2d\tword of length %d", wordSize, i);
}
else{
printf("\n%-2d\twords of length %d", wordSize, i);
}
}
printf("\n\n***Word analysis***\n");
wordAnalysis(text, lineTotal);
return 0;
}
void letterAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
int alphabet[26] = {0};
for (int i = 0; i < lineTotal; i++){
for(int j = 0; j < MAX_LINE_LENGTH; j++){
switch(text[i][j]){
case 'A': case 'a':
alphabet[0]++;
break;
case 'B': case 'b':
alphabet[1]++;
break;
case 'C': case 'c':
break;
alphabet[2]++;
case 'D': case 'd':
alphabet[3]++;
break;
case 'E': case 'e':
alphabet[4]++;
break;
case 'F': case 'f':
alphabet[5]++;
break;
case 'G': case 'g':
alphabet[6]++;
break;
case 'H': case 'h':
alphabet[7]++;
break;
case 'I': case 'i':
alphabet[8]++;
break;
case 'J': case 'j':
alphabet[9]++;
break;
case 'K': case 'k':
alphabet[10]++;
break;
case 'L': case 'l':
alphabet[11]++;
break;
case 'M': case 'm':
alphabet[12]++;
break;
case 'N': case 'n':
alphabet[13]++;
break;
case 'O': case 'o':
alphabet[14]++;
break;
case 'P': case 'p':
alphabet[15]++;
break;
case 'Q': case 'q':
alphabet[16]++;
break;
case 'R': case 'r':
alphabet[17]++;
break;
case 'S': case 's':
alphabet[18]++;
break;
case 'T': case 't':
alphabet[19]++;
break;
case 'U': case 'u':
alphabet[20]++;
break;
case 'V': case 'v':
alphabet[21]++;
break;
case 'W': case 'w':
alphabet[22]++;
break;
case 'X': case 'x':
alphabet[23]++;
break;
case 'Y': case 'y':
alphabet[24]++;
break;
case 'Z': case 'z':
alphabet[25]++;
break;
}
}
}
for(int i = 0; i <= 25; i++){
printf("%c: \t%d\n",'a' + i, alphabet[i]);;
}
}
int wordLengthAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal, int wordLength){
int sentenceLength;
int counter, wordSize = 0;
for(int i = 0; i < lineTotal; i++){
sentenceLength = strlen(&text[i][0]);
for(int j = 0; j < sentenceLength + 2; j++){
if(text[i][j] == ' '){
if(counter == wordLength){
++wordSize;
counter = 0;
}
else{
counter = 0;
}
}
else{
counter++;
}
}
}
return wordSize;
}
void wordAnalysis(char text[][MAX_LINE_LENGTH], int lineTotal){
char maxWords[800];
char word[MAX_LINE_LENGTH], word2[MAX_WORD_LENGTH], *ptrText, *ptrTextCounter;
int counter, textCounter = 0;
int sentenceLength, wordTracker;
int lineFlag;
for(int i = 0; i < lineTotal; i++){
ptrText = &text[i][0];
sentenceLength = strlen(ptrText);
counter = 0;
for (int j = 0; j < sentenceLength + 1; j++){
wordTracker = 1;
if (text[i][j] == ' ' ){
if (counter != 0){
sprintf(word, "%.*s", counter, ptrText);
ptrTextCounter = &text[i][j+1];
lineFlag = j;
if(strstr(maxWords, word) == NULL){
for (int k = i; k < lineTotal; k++){
textCounter = 0;
if (lineFlag == j){
ptrTextCounter = &text[i][j+1];
}
else{
lineFlag = 0;
ptrTextCounter = &text[i][j+1];
}
for ( ; lineFlag < sentenceLength; lineFlag++){
if(text[k][lineFlag] == ' '){
if (textCounter != 0){
if(textCounter == counter){
sprintf(word2, "%.*s", textCounter, ptrTextCounter);
if(strcmp(word, word2) == 0){
wordTracker++;
}
}
ptrTextCounter = &text[k][lineFlag];
textCounter = 0;
}
else{
ptrTextCounter = &text[k][lineFlag+1];
}
}
else{
textCounter++;
}
}
}
if(wordTracker == 1){
printf("\n\"%.*s\"\t\tappeared %d time", counter, ptrText, wordTracker);
}
else{
printf("\n\"%.*s\"\t\tappeared %d time", counter, ptrText, wordTracker);
}
}
strcat(maxWords, word);
ptrText = &text[i][j+1];
counter = 0;
}
else{
ptrText = &text[i][j+1];
}
}
else{
counter++;
}
}
}
}
I get a couple of warnings:
main.c:17:14: warning: variable length array used [-Wvla]
char text[lineTotal][MAX_LINE_LENGTH];
^
main.c:17:15: warning: variable 'lineTotal' is uninitialized when used here [-Wuninitialized]
char text[lineTotal][MAX_LINE_LENGTH];
^~~~~~~~~
You haven't initialized lineTotal but are using it. This causes undefined behavior.
main.c:64:21: warning: code will never be executed [-Wunreachable-code]
alphabet[2]++;
^~~~~~~~
Your break; is likely misplaced.
main.c:152:20: warning: variable 'counter' may be uninitialized when used here [-Wconditional-uninitialized]
if(counter == wordLength){
^~~~~~~
Again, you're using a potentially uninitialized variable.
Also:
char n[1];
fgets(n, 10, stdin);
Your array has one element but you tell fgets it can access up to n[10].
Hint (if it wasn't obvious already): never program C without warnings.

Case/Switch in C not working

I am making a game for school this is a basic slot machine it will randomly generate numbers and converts the numbers to chars in a separate array. This seems to not be working as the statement is completely ignored. It doesn't give the right output and some time they will just go to blanks.
Output:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
/*
George Mason
Slots
Date Started: 4/25/16
Date Finished:
Dr K.
*/
void loadScreen();
void spacer();
void tabSpacer();
void clearScr();
int printMachine(char*, int);
int randomNum(int*, int);
int convertNum(int*, char*, int);
int rand_int();
void game();
int main(){
srand(time(NULL));
int stop;
loadScreen();
clearScr();
game();
scanf("%d", &stop);
}
void game(){
int tokens = 5, randomNums[9], x, y = 9;
char randomChars[9], userInput;
randomNum(randomNums, 9);
convertNum(randomNums, randomChars, 9);
printMachine(randomChars, 9);
}
int printMachine(char* randomChars, int y){
printf("-------------\n");
printf("| %c | %c | %c | \n", randomChars[0], randomChars[1], randomChars[2]);
printf("| %c | %c | %c | \n", randomChars[3], randomChars[4], randomChars[5]);
printf("| %c | %c | %c | \n", randomChars[6], randomChars[7], randomChars[8]);
printf("-------------");
}
int randomNum(int* randomNums, int y){
int x,a = 0, b = 9;
for(x = 0; x < y; x++){
randomNums[x] = ((rand() % (b-a+1)) + a);
}
}
int convertNum(int* randomNums, char* randomChars, int y){
int x;
for(x = 0; x < 9; x++){
switch(randomNums[x]){
case 1:
randomChars[x] = '#';
break;
case 2:
randomChars[x] = '#';
break;
case 3:
randomChars[x] = '$';
break;
case 4:
randomChars[x] = '+';
break;
case 5:
randomChars[x] = '&';
break;
case 6:
randomChars[x] = '*';
break;
case 7:
randomChars[x] = '?';
break;
case 8:
randomChars[x] = '!';
break;
case 9:
randomChars[x] = '~';
break;
default:
randomChars[x] = 'e';
break;
}
}
}
void loadScreen(){
int x;
for(x = 0; x < 3; x++){
spacer();
}
tabSpacer();
printf("Please wait 5 seconds while we load the saved data.\n");
tabSpacer();
printf(" If there is no saved data one will be created.");
sleep(5);
}
void spacer(){
int x;
for(x = 0; x < 3; x++){
printf("\n");
}
}
void tabSpacer(){
printf("\t ");
}
void clearScr(){
system("cls");
}
You have forgot to keep break; after every case so it will run all cases i.e from case 1 to case 9.
At the end it will save randomChars[x] = '~'; (case 9).
case 1:
randomChars[x] = '#';
break;
case 2:
randomChars[x] = '#';
break;
.
.
.
.
case 7:
randomChars[x] = '?';
break;
case 8:
randomChars[x] = '!';
break;
case 9:
randomChars[x] = '~';
break;
EDIT:
why your function return type is int when you are not returning any value. change int to void.
function game() is not declared before main()
I am getting Output like this:

Frequency analysis? Caesar cipher C

I have written this code so far, and now i am required to use the frequency analysis to crack the code which I am not not clear of.
From what I understand, I must first count the frequency of letters in a string, then I would say compare it with the most frequent letters in German language, and later sort it with bubble sort. Is this correct?
I would really appreciate it if anyone could give me Ideas or hints on where to start. Thank you in advance.
EDITED: Hi Guys, i just edited my code and the frequency analysis seems to be working fine right now. It would help me if you guys can give comments or critics on my code. Thanks!
BTW its German language, i changed it.
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <ctype.h>
#define MAX 100
struct Data
{
char letter;
int num;
};
typedef struct Data DATA;
void encode(char message[], int shift)
{
int i;
FILE *pout;
pout = fopen("Output_encode.txt", "w");
if (pout == NULL)
{
printf("File could not be opened for writing!\n");
exit(1);
}
for(i=0;i<strlen(message);i++)
{
if (!isalpha(message[i]))
continue;
// checking for upper case
if(isupper(message[i]))
message[i]=((message[i]-'A') + shift) % 26 + 'A';
else
//checking for lower case
if(islower(message[i]))
message[i]=((message[i]-'a') + shift) % 26 + 'a';
}
printf("\n\tEncoded text: %s\n", message);
fprintf(pout, "%s\n", message);
if (fclose(pout) != 0)
printf("Error in closing file!\n");
}
void decode(char message[], int shift)
{
int i;
FILE *pout;
pout = fopen("Output_decode.txt", "w");
if (pout == NULL)
{
printf("File could not be opened for writing!\n");
exit(1);
}
for(i=0;i<strlen(message);i++)
{
if (!isalpha(message[i]))
continue;
// checking for upper case
if(isupper(message[i]))
message[i]=((message[i]-'A') + (26-shift)) % 26 + 'A';
else
//checking for lower case
if(islower(message[i]))
message[i]=((message[i]-'a') + (26-shift)) % 26 + 'a';
}
printf("\n\tDecoded text: %s\n", message);
fprintf(pout, "%s\n", message);
if (fclose(pout) != 0)
printf("Error in closing file!\n");
}
void textfile_decode()
{
FILE *pin, *pout;
char filename_in[MAX], filename_out[MAX];
char text[MAX];
char text3[MAX]={0};
char table[26] = {'e','n','i','r','s','t','a','d','h','u','l','c','g','o','m','b','f','w','k','z','p','v','j','y','x','q'}; //Frequency letters in German dictionary
DATA temptext, text2[26];
int temp, position;
int i, m, max, trial, l=0, n=0, k=0;
printf("Enter name of input file: ");
scanf("%s", filename_in);
pin = fopen(filename_in, "r");
if (pin == NULL)
{
printf("File could not be opened for reading!");
}
printf("Enter name of output file: ");
scanf("%s", filename_out);
pout = fopen(filename_out, "w");
if (pout == NULL)
{
printf("File could not be opened for writing!");
}
printf("\nOriginal Code:\n");
while(!feof(pin))
{
fgets(text, MAX, pin); //Read from textfile
fputs(text, stdout); //Show original code on console
}
printf("\n");
if (pin == NULL)
{
printf("File could not be opened for reading!");
}
fclose(pin);
pin = fopen(filename_in, "r");
for (i = 0; i <= 25; i++)
{
text2[i].letter = 'a' + i; //Array elements A-Z
text2[i].num = 0; //Number of letters (Frequency)
}
while(!feof(pin))
{
i = 0;
fgets(text, MAX, pin); //Read from textfile per line
while(text[i] != '\0')
{
if(1 == isupper(text[i])) // Replace capital letters with small
{
text[i] += 32;
}
switch(text[i]) //Counting letters (letter frequency)
{
case 'a':
text2[0].num += 1;
break;
case 'b':
text2[1].num += 1;
break;
case 'c':
text2[2].num += 1;
break;
case 'd':
text2[3].num += 1;
break;
case 'e':
text2[4].num += 1;
break;
case 'f':
text2[5].num += 1;
break;
case 'g':
text2[6].num += 1;
break;
case 'h':
text2[7].num += 1;
break;
case 'i':
text2[8].num += 1;
break;
case 'j':
text2[9].num += 1;
break;
case 'k':
text2[10].num += 1;
break;
case 'l':
text2[11].num += 1;
break;
case 'm':
text2[12].num += 1;
break;
case 'n':
text2[13] .num+= 1;
break;
case 'o':
text2[14].num += 1;
break;
case 'p':
text2[15].num += 1;
break;
case 'q':
text2[16].num += 1;
break;
case 'r':
text2[17].num += 1;
break;
case 's':
text2[18].num += 1;
break;
case 't':
text2[19].num += 1;
break;
case 'u':
text2[20].num += 1;
break;
case 'v':
text2[21].num += 1;
break;
case 'w':
text2[22].num += 1;
break;
case 'x':
text2[23].num += 1;
break;
case 'y':
text2[24].num += 1;
break;
case 'z':
text2[25].num += 1;
break;
default: break;
}
i++;
}
}
for(i = 0; i <= 26; i++) // Sorting array text2 according to letter frequency
{
temp = text2[i].num;
for(m = i+1; m <= 27; m++)
{
if(text2[m].num > temp)
{
max = m;
temp = text2[m].num;
}
}
temptext = text2[max];
text2[max] = text2[i];
text2[i] = temptext;
}
fclose(pin);
fclose(pout);
pin = fopen(filename_in, "r");
pout = fopen(filename_out, "w");
do
{
k += 1;
} while (text2[k].num == text2[k+1].num); //Check--> How many letters have the same frequency
trial = 2;
while(!feof(pin))
{
fgets(text, MAX, pin);
do
{
position = table[l] - text2[n].letter; // determine letter position
i = 0;
do
{
if(0 !=isalpha(text[i]))
{
if(0 != isupper(text[i])) // Checking for uppercase
{
text3[i] = text[i];
text3[i] = text3[i] + position;
if(text3[i] > 90) // If exceeds Alphabets, start again from 'A'
{
text3[i] = text3[i] - 26;
}
else if (text3[i] < 65)
{
text3[i] += 26;
}
}
else if (0 != islower(text[i])) // checking for lowercase
{
text3[i] = text[i];
text3[i] = text3[i] + position;
if(text3[i] > 122) // If exceeds Alphabets, start again from 'a'
{
text3[i] = text3[i] - 26;
}
else if(text3[i] < 97)
{
text3[i] += 26;
}
}
}
else
{
text3[i] = text[i]; // All other non letters are simply replaced
}
i++;
}while(text[i] != '\0' );
if (trial== 2)
{
printf("\n");
fputs(text3, stdout);
printf("\nCode decrypted? (0)NO (1)YES : ");
scanf("%d", &trial);
printf("\n");
}
if (trial == 0 && n != k) // Code not decrypted, letters have different frequency
{
n++;
trial = 2;
}
if (trial == 0 && n == k) // Code not decrypted, letters have same frequency
{
l++;
n = 0;
trial = 2;
}
if (trial == 3) // First line of code is decrypted, following lines will decrypted using same shift position
{
trial = 1;
}
}while(trial != 1);
fputs(text3, stdout); //Show on console window
fputs(text3, pout);
memset(text3,'\0',100); // Reset text3 array
memset(text,'\0',100); // Reset text array
trial = 3; // First line of code decrypted, shift position is saved
}
fclose(pin);
fclose(pout);
}
int main()
{
int shift, choice1, choice2;
char message[MAX];
do{
printf("Selection: \n");
printf("(1) Encode/Decode\n");
printf("(2) Decode Textfile\n");
printf("(3) End Programme\n");
printf("User input: ");
scanf("%d", &choice1);
fflush(stdin);
switch(choice1){
case 1:
printf("\nEnter message to be encrypted: ");
gets(message);
printf("Enter shift amount (1-25): ");
scanf("%d", &shift);
printf("\nSelection: \n");
printf("(1) Encode\n");
printf("(2) Decode\n");
printf("User input: ");
scanf("%d", &choice2);
switch(choice2)
{
case 1:
encode(message, shift);
break;
case 2:
decode(message, shift);
break;
}
break;
case 2:
textfile_decode();
break;
}
printf("\n\n");
}while(choice1!=3);
printf("\n");
return 0;
}
A Caesar ciphre changes characters by shifting them n places.
There are two very simple approaches to solving a shift ciphre:
Print all 25 possible solutions. Manually select the one that contains readable text.
Get the frequency of the characters (not the words). Then perform the shift that best aligns with a frequency table of the language the message was written in (English in your case?).
To break the code you can use 3 different approaches:
The first one is what you cited: count the frequency of words in a text ( I would rather use a Map for that, using the string as key and rising the number of hits as value.), and guessing the letters by comparing it to the frequency of words used in normal texts.
The second solution would be to do same with letters and guessing the meaning by comparing your frequency with the frequency of letters in a normal text.
The third solution would be to take single words of the text and trying all possible shiftings of the letters until you get words that mean something.
Here you can find some good sources!

Resources