I'm working on an encryption program for a class in C. I use modulo 27 math to perform the encryption. I add each encrypted character to an array but I've noticed that unprinted characters are also being added to my string at the end. I realized this when I checked the word count of the encrypted text and it contained more characters than the original text that was encrypted. Can anyone explain why this is happening? This is taking into account the newline at the end of the texts.
Plaintext = THE RED GOOSE FLIES AT MIDNIGHT STOP - wc is 37
Ciphertext = ACBVKWNOGMMMPQHNI XL QBJXDPNVIQVSNZN - wc is 40
//Go through each character of the plaintext
for (i = 0; i < size; i++)
{
//Convert the characters to an integer
PlainNums[i] = charInt(plaintext[i]);
KeyNums[i] = charInt(key[i]);
//Add the int from plain text and the key together
CipherNums[i] = PlainNums[i] + KeyNums[i];
if (CipherNums[i] > 27) //Wrap around if the number exceeds 27
{
CipherNums[i] -= 27;
}
CipherNums[i] = CipherNums[i] % 27; //Use modulo 27 math to generate a new integer
cipherText[i] = IntChar(CipherNums[i]);
}
int charInt(char c)
{
switch (c)
{
case 'A': return 0;
case 'B': return 1;
case 'C': return 2;
case 'D': return 3;
case 'E': return 4;
case 'F': return 5;
case 'G': return 6;
case 'H': return 7;
case 'I': return 8;
case 'J': return 9;
case 'K': return 10;
case 'L': return 11;
case 'M': return 12;
case 'N': return 13;
case 'O': return 14;
case 'P': return 15;
case 'Q': return 16;
case 'R': return 17;
case 'S': return 18;
case 'T': return 19;
case 'U': return 20;
case 'V': return 21;
case 'W': return 22;
case 'X': return 23;
case 'Y': return 24;
case 'Z': return 25;
case ' ': return 26;
default: return -1;
}
}
char IntChar(int n)
{
switch(n)
{
case 0: return 'A';
case 1: return 'B';
case 2: return 'C';
case 3: return 'D';
case 4: return 'E';
case 5: return 'F';
case 6: return 'G';
case 7: return 'H';
case 8: return 'I';
case 9: return 'J';
case 10: return 'K';
case 11: return 'L';
case 12: return 'M';
case 13: return 'N';
case 14: return 'O';
case 15: return 'P';
case 16: return 'Q';
case 17: return 'R';
case 18: return 'S';
case 19: return 'T';
case 20: return 'U';
case 21: return 'V';
case 22: return 'W';
case 23: return 'X';
case 24: return 'Y';
case 25: return 'Z';
case 26: return ' ';
default: return '!'; //error
}
}
Try adding cipherText[size] = '\0'; at the end of the loop to make sure the encoded string only contain the encoded data.
Initialize the cipherText before for loop using memset in your code like the following way.
memset(cipherText,0,sizeof(cipherText));
for (i = 0; i < size; i++)
{
//Convert the characters to an integer
PlainNums[i] = charInt(plaintext[i]);
//....
// rest of the code
You must need to include<string.h.
And it works.
Related
I am creating a program for an online coding course which takes a poker hand and calculates the odds of the hand winning. I am currently in the early stages, writing the functions necessary to advance to the next part of the assignment. I have isolated my issues to one function, card_from_letters.
I created my-test-main.c to test card_from_letters. It creates two chars, representing the suit and value of a poker card. It then creates the struct testCard2.
A card_t struct has two components: an unsigned int for value, and an enumerated type for suit between SPADES and CLUBS. I cannot change the struct card_t.
int main(void) {
char sui = 'c';
char val = 'Q';
card_t testCard2 = card_from_letters(val, sui);
printf("last test! My card %c%c is value %d, and suit %d!\n", val, sui, testCard2.value, testCard2.suit);
}
This is my function card_from_letters:
card_t card_from_letters(char value_let, char suit_let) {
card_t temp;
assert(suit_let == 'd' ||'h' || 'c' || 's');
assert((value_let >= '2' && value_let <= '9') || (value_let = '0' || 'K' || 'Q' || 'J' || 'A'));
switch (value_let) {
case '2': temp.value = 2; break;
case '3': temp.value = 3; break;
case '4': temp.value = 4; break;
case '5': temp.value = 5; break;
case '6': temp.value = 6; break;
case '7': temp.value = 7; break;
case '8': temp.value = 8; break;
case '9': temp.value = 9; break;
case '0': temp.value = 10; break;
case 'K': temp.value = 13; break;
case 'Q': temp.value = 12; break;
case 'J': temp.value = 11; break;
case 'A': temp.value = 14; break;
}
switch (suit_let) {
case 's': temp.suit = SPADES; break;
case 'h': temp.suit = HEARTS; break;
case 'd': temp.suit = DIAMONDS; break;
case 'c': temp.suit = CLUBS; break;
}
return temp;
}
When val is set between '2' and '9', I am able to run card_from_letters with no problem. When I run my-test-main.c as it is here through gdb, the execution arrow makes it to switch (value_let), but then skips all cases and enters switch (suit_let), where it returns the correct suit. What am I missing here? How come card_from_letters works for chars 2 to 9, but not 0 to A?
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
I'm getting output of a - 0000520 when I input a while i should get 0001010 as per the code I've assigned. Also the default runs every time (tested using a printf statement) for unexplained reason. My code is here:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int splitWord(char* word, int count);
int sunCode(char letter);
int main()
{
char inputString[100];
char splitStrings[10][10];
int i, j, count;
printf("Enter the message.\n");
fgets(inputString, 100, stdin);
j = count = 0;
for (i = 0; i <= (strlen(inputString)); i++) {
if (inputString[i] == ' ' || inputString[i] == '\0') {
splitStrings[count][j] = '\0';
count++;
j = 0;
}
else {
splitStrings[count][j] = inputString[i];
j++;
}
}
printf("\nOriginal String is: %s\n", inputString);
for (i = 0; i < count; i++) {
/*for(j=0;j<=strlen(splitStrings[i]);j++){
printf("%s",splitStrings[i][j]);
}*/
splitWord(splitStrings[i], count);
}
return 0;
}
int splitWord(char* word, int count)
{
int i;
int strLength = strlen(word);
for (i = 0; i <= strLength; i++) {
sunCode(word[i]);
// printf("%c\n",word[i]);
}
return 0;
}
int sunCode(char letter)
{
char letr = tolower(letter);
int code = 0;
switch (letr) {
case '0':
code = 0000000;
break;
case '1':
code = 0000001;
break;
case '2':
code = 0000010;
break;
case '3':
code = 0000011;
break;
case '4':
code = 0000100;
break;
case '5':
code = 0000101;
break;
case '6':
code = 0000110;
break;
case '7':
code = 0000111;
break;
case '8':
code = 0001000;
break;
case '9':
code = 0001001;
break;
case 'a':
code = 0001010;
break;
case 'b':
code = 0001011;
break;
case 'c':
code = 0001100;
break;
case 'd':
code = 0001101;
break;
case 'e':
code = 0001110;
break;
case 'f':
code = 0001111;
break;
case 'g':
code = 0010000;
break;
case 'h':
code = 0010001;
break;
case 'i':
code = 0010010;
break;
case 'j':
code = 0010011;
break;
case 'k':
code = 0010100;
break;
case 'l':
code = 0010101;
break;
case 'm':
code = 0010110;
break;
case 'n':
code = 0010111;
break;
case 'o':
code = 0011000;
break;
case 'p':
code = 0011001;
break;
case 'q':
code = 0011010;
break;
case 'r':
code = 0011011;
break;
case 's':
code = 0011100;
break;
case 't':
code = 0011101;
break;
case 'u':
code = 0011110;
break;
case 'v':
code = 0011111;
break;
case 'w':
code = -010000;
break;
case 'x':
code = 010001;
break;
case 'y':
code = 010010;
break;
case 'z':
code = 010011;
break;
case ' ':
code = 45;
printf("\nis space\n");
break;
default:
break;
}
printf("%c - %07d\n", letr, code);
}
I tried to see if it's giving ASCII values (it isn't)
the letter is being passed properly in the sunCode function (it is)
I do not understand why it is behaving like this, verified the syntax and conditions of switch too.
I am using gcc 7.3.0 on Ubuntu.
Leading zeros indicate that the number is expressed in octal, or base 8; thus, 010 = 8.
https://stackoverflow.com/a/1661378/10479742
0001010 in octal is 520 in decimal, and that's why you get that result. Either remove leading zeros, or change code to string.
This the line from the csh script
./model2grd $model -D$nx/$ny/$nz -O$x0/$y0 -I$dx/$dy -L$layer -C$coverage -Avel.dat -Gvel.grd
This is part of the model2grd.c
for (i = 2; i < argc; i++) {
if (argv[i][0] == '-') {
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
case 'C':
cov = &argv[i][2];
lcov = TRUE;
break;
case 'A':
xyzfile = &argv[i][2];
lxyz = TRUE;
break;
case 'D':
sscanf(&argv[i][2],"%d/%d/%d",&nx,&ny,&nz);
break;
case 'I':
sscanf(&argv[i][2], "%lf/%lf", &dx, &dy);
break;
case 'O':
sscanf(&argv[i][2], "%lf/%lf", &xmin, &ymin);
break;
case 'L':
layer = atoi(&argv[i][2]);
break;
case 'N':
nan = (float)atof(&argv[i][2]);
break;
case 'Z':
cvalue = (float)atof(&argv[i][2]);
break;
case 'V':
verbose = TRUE;
break;
default:
break;
}
}
}
Does this mean that it takes with D(nx,ny,nz),with O(xmin and ymin),with L layer and with C coverage?Are Avel.dat and Gvel.grd input files or not?
Avel.dat and Gvel.grd are not input files. Look at the argument parsing again.
switch (argv[i][1]) {
case 'G':
grdfile = &argv[i][2];
lgrd = TRUE;
break;
Consider that with this argument:
-Gvel.grd
In plain English, the switch examines the second character of each argument. In this case -Gvel.grd is the argument, so it looks at the G. Passing that test, the case statement then derives the address of the character that comes immediately after the G within the character string. In other words, the v.
Therefore, the file name is actually vel.grd. You should be able to apply this same logic to the rest of the arguments that follow the same pattern.
I am currently working on my OS. I've started building it since a-day before yesterday. My OS is command-based.
This is my Kernel.c(The main file):
#include "include/screen.h"
#include "include/kb.h"
#include "include/string.h"
#include "data/userdata.c"
kmain()
{
clearScreen();
print("Halcyon OS 1.05 Beta ");
while (1)
{
print("\nhalcyon#halcyon ~\n$ ");
string ch = readStr();
if(strEql(ch,"cmd")!=0)
{
print("\nYou are already in cmd\n");
}
else if(strEql(ch,"clear")!=0)
{
clearScreen();
}
else if(strEql(ch,"help")!=0)
{
print("Halcyon help.");
}
else if(strEql(ch,"")!=0)
{
continue;
}
else
{
print("\nNo command found:");print(ch);
break;
}
}// end while loop!
}
And here is kb.h (I've made it for keyboard support.):
#ifndef KB_H
#define KB_H
#include "screen.h"
#include "system.h"
#include "types.h"
string readStr()
{
char buff;
string buffstr;
uint8 i = 0;
uint8 reading = 1;
while(reading)
{
if(inportb(0x64) & 0x1)
{
switch(inportb(0x60))
{
/*case 1:
printch('(char)27); Escape button
buffstr[i] = (char)27;
i++;
break;*/
case 2:
printch('1');
buffstr[i] = '1';
i++;
break;
case 3:
printch('2');
buffstr[i] = '2';
i++;
break;
case 4:
printch('3');
buffstr[i] = '3';
i++;
break;
case 5:
printch('4');
buffstr[i] = '4';
i++;
break;
case 6:
printch('5');
buffstr[i] = '5';
i++;
break;
case 7:
printch('6');
buffstr[i] = '6';
i++;
break;
case 8:
printch('7');
buffstr[i] = '7';
i++;
break;
case 9:
printch('8');
buffstr[i] = '8';
i++;
break;
case 10:
printch('9');
buffstr[i] = '9';
i++;
break;
case 11:
printch('0');
buffstr[i] = '0';
i++;
break;
case 12:
printch('-');
buffstr[i] = '-';
i++;
break;
case 13:
printch('=');
buffstr[i] = '=';
i++;
break;
case 14:
printch('\b');
i--;
buffstr[i] = 0;
break;
/* case 15:
printch('\t'); Tab button
buffstr[i] = '\t';
i++;
break;*/
case 16:
printch('q');
buffstr[i] = 'q';
i++;
break;
case 17:
printch('w');
buffstr[i] = 'w';
i++;
break;
case 18:
printch('e');
buffstr[i] = 'e';
i++;
break;
case 19:
printch('r');
buffstr[i] = 'r';
i++;
break;
case 20:
printch('t');
buffstr[i] = 't';
i++;
break;
case 21:
printch('y');
buffstr[i] = 'y';
i++;
break;
case 22:
printch('u');
buffstr[i] = 'u';
i++;
break;
case 23:
printch('i');
buffstr[i] = 'i';
i++;
break;
case 24:
printch('o');
buffstr[i] = 'o';
i++;
break;
case 25:
printch('p');
buffstr[i] = 'p';
i++;
break;
case 26:
printch('[');
buffstr[i] = '[';
i++;
break;
case 27:
printch(']');
buffstr[i] = ']';
i++;
break;
case 28:
// printch('\n');
// buffstr[i] = '\n';
i++;
reading = 0;
break;
/* case 29:
printch('q'); Left Control
buffstr[i] = 'q';
i++;
break;*/
case 30:
printch('a');
buffstr[i] = 'a';
i++;
break;
case 31:
printch('s');
buffstr[i] = 's';
i++;
break;
case 32:
printch('d');
buffstr[i] = 'd';
i++;
break;
case 33:
printch('f');
buffstr[i] = 'f';
i++;
break;
case 34:
printch('g');
buffstr[i] = 'g';
i++;
break;
case 35:
printch('h');
buffstr[i] = 'h';
i++;
break;
case 36:
printch('j');
buffstr[i] = 'j';
i++;
break;
case 37:
printch('k');
buffstr[i] = 'k';
i++;
break;
case 38:
printch('l');
buffstr[i] = 'l';
i++;
break;
case 39:
printch(';');
buffstr[i] = ';';
i++;
break;
case 40:
printch((char)44); // Single quote (')
buffstr[i] = (char)44;
i++;
break;
case 41:
printch((char)44); // Back tick (`)
buffstr[i] = (char)44;
i++;
break;
/* case 42: Left shift
printch('q');
buffstr[i] = 'q';
i++;
break;
case 43: \ (< for somekeyboards)
printch((char)92);
buffstr[i] = 'q';
i++;
break;*/
case 44:
printch('z');
buffstr[i] = 'z';
i++;
break;
case 45:
printch('x');
buffstr[i] = 'x';
i++;
break;
case 46:
printch('c');
buffstr[i] = 'c';
i++;
break;
case 47:
printch('v');
buffstr[i] = 'v';
i++;
break;
case 48:
printch('b');
buffstr[i] = 'b';
i++;
break;
case 49:
printch('n');
buffstr[i] = 'n';
i++;
break;
case 50:
printch('m');
buffstr[i] = 'm';
i++;
break;
case 51:
printch(',');
buffstr[i] = ',';
i++;
break;
case 52:
printch('.');
buffstr[i] = '.';
i++;
break;
case 53:
printch('/');
buffstr[i] = '/';
i++;
break;
case 54:
printch('.');
buffstr[i] = '.';
i++;
break;
case 55:
printch('/');
buffstr[i] = '/';
i++;
break;
/*case 56:
printch(' '); Right shift
buffstr[i] = ' ';
i++;
break;*/
case 57:
printch(' ');
buffstr[i] = ' ';
i++;
break;
}
}
}
buffstr[i] = 0;
return buffstr;
}
#endif
And at last the string.h(This has function to compare two strings.):
#ifndef STRING_H
#define STRING_H
#include "types.h"
uint16 strlength(string ch)
{
uint16 i = 1;
while(ch[i++]);
return --i;
}
uint8 strEql(string ch1,string ch2)
{
uint8 result = 1;
uint8 size = strlength(ch1);
if(size != strlength(ch2)) result =0;
else
{
uint8 i = 0;
for(i;i<=size;i++)
{
if(ch1[i] != ch2[i]) result = 0;
}
}
return result;
}
#endif
But the problem is that even if enter the correct command like 'cmd', it only sometimes says 'No command found: cm' and sometimes it works! It goes sometimes correct and says: 'You're already in cmd!'
Also, it is recognizing it as 'cm' not 'cmd'.
And if I write in kernel.c: "print("Hello");" then it will print: 'Hell' not 'Hello'! It misses the last character.
I don't know what's wrong with my program.
I use gcc to compile it, platform is Linux Ubuntu. The sometimes work and sometimes not. But if I compile my kernel with Windows the command never works.
Please help! Any help will be greatly appreciated.
Your string length function is wrong:
uint16 strlength(string ch)
{
uint16 i = 1;
while(ch[i++]);
return --i;
}
Assuming the string is "cmd", then you start and check if the second character, m, is null, then the third, then finally the fourth is null. i starts off with 1 and increases up to 3, and finally gets decremented to 2.
Also it would fail on zero length strings.
The consequence is, that you are not printing enough in your print function.
unit16 strlength(string ch) {
unit16 l = 0;
while (ch[l]) {
++l;
}
return l;
}
To find out why the comparison fails I'd need to know what type string actually is.
If it's a char *, then this is actually undefined behaviour, as your writing into some random memory.
If it's a char [N] then out won't work either, because that array decays to a pointer on return. And that pointer points to a local variable with automatic storage, so it is no longer valid after function return.
OK, it's a pointer. Pointers point to memory, where you then store the actual data. To have this working you need
Memory to store the data to
Set the pointer to point to that memory.
Normally one would allocate memory via malloc, but in the context of operating system development you'd first have to implement that yourself.
You cold use a buffer with automatic storage (on the stack) in the caller:
char buffer[20];
size_t num_read = read_into(buffer, 20);
// pass the pointer to the memory for the data plus the maximal characters this buffer can hold.
size_t read_into (char * buffer, size_t max) {
// read up to Max characters into the
// buffer, don't forget to count the 0 at the end.
}
Judging from the rest of your code, you seem to be fairly new to C programming. While writing an operating system kernel is a fun task, you'll have more fun doing it when you understand the basics first.
Since you're writing to random memory locations with those uninitialised char * you don't know where you store the data. This could be "normal", free memory. Then everything will work as expected. But you could also write to memory mapped device information or even your own code, making it impossible to predict what might happen.
switch(ch)
{
//input a number
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[g.y][g.x] = ch - '0';
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
// delete an input from the board
case '0':
case KEY_BACKSPACE:
case KEY_DC:
if(check_original())
{
int y = g.y;
int x = g.x;
g.board[y][x] = 0;
draw_numbers();
g.y = y;
g.x = x;
show_cursor();
}
}
Problem: Case '1' through case '9' worked fine. Then I added case '0', case KEY_BACKSPACE and case KEY_DC. Although it compiles, none of the cases now work, including cases '1' - '9'. What am I missing?
All of your cases are falling through. I assume that you should have a break; before case 0:.
You are missing a break;. In C, switch has fall-through semantics. Once a case is met, all subsequent cases are exceuted unless a break; stops execution.