I'm implementing in c the vigenère algorithme.
Unfortunately when testing the program I'm experiencing a segmentation error. I'm compiling with clang on mac.
How could I avoid that error ?
Source Code:
#include <ctype.h>
#include <stdio.h>
#include <string.h>
/**
* Function: invalidUsage
* --------------------
* Shows usage information and returns 1
*/
int
invalidUsage();
/**
* Function: cryptCaesar
* --------------------
* Returns encrypted char using caesar cipher
*/
char
cryptCaesar(const char plain, const int key);
/**
* Function: parseAlphaKey
* --------------------
* Converts an alpha string to a usable key (array of char from 0 to 25)
* Returns true if conversion successful, false if not
*/
bool
parseAlphaKey(const char* input_string, char** output_key);
// === Main ===
int main(int argc, const char *argv[])
{
// === Argument validation ===
char *output_key;
if (argc != 2
|| !parseAlphaKey(argv[1], &output_key))
return invalidUsage();
// === Read plain text ===
// === Output cipher text ===
//printf("%s\n", key);
return 0;
}
int
invalidUsage()
{
printf("Usage : vigenere <key>\n\n");
printf("KEY:\n");
printf(" Must be a string of alpha characters\n");
return 1;
}
char
cryptCaesar(const char plain, const int key)
{
char cipher;
if (islower(plain)) {
cipher = (plain - 'a' + key) % 26 + 'a';
} else if (isupper(plain)) {
cipher = (plain - 'A' + key) % 26 + 'A';
} else {
cipher = plain;
}
return cipher;
}
bool
parseAlphaKey(const char* input_string, char** output_key)
{
//output_key = NULL;
*output_key = malloc(strlen(input_string) * sizeof(char));
for (int i = 0, n = strlen(input_string); i < n; ++i) {
if (isupper(input_string[i]))
*output_key[i] = input_string[i] - 'A';
else if (islower(input_string[i]))
*output_key[i] = input_string[i] - 'a';
else {
//free(*output_key);
return false;
}
}
return true;
}
Debug output:
$ lldb vigenere -- test
Current executable set to 'vigenere' (x86_64).
(lldb) run
Process 48854 launched: '/Users/.../vigenere' (x86_64)
Process 48854 stopped
* thread #1: tid = 0x549580, 0x0000000100000d9f vigenere`parseAlphaKey(input_string=0x00007fff5fbff941, output_key=0x00007fff5fbff6a8) + 207 at vigenere.c:87, queue = 'com.apple.main-thread, stop reason = EXC_BAD_ACCESS (code=1, address=0x2)
frame #0: 0x0000000100000d9f vigenere`parseAlphaKey(input_string=0x00007fff5fbff941, output_key=0x00007fff5fbff6a8) + 207 at vigenere.c:87
84 if (isupper(input_string[i]))
85 *output_key[i] = input_string[i] - 'A';
86 else if (islower(input_string[i]))
-> 87 *output_key[i] = input_string[i] - 'a';
88 else {
89 //free(*output_key);
90 return false;
(lldb) kill
Process 48854 exited with status = -1 (0xffffffff) SIGKILL
(lldb) exit
Regards
Two problems:
1) you're not terminating your output string - change:
*output_key = malloc(strlen(input_string) * sizeof(char));
to:
*output_key = malloc(strlen(input_string) + 1);
and make sure you add a '\0' terminator, e.g. in parseAlphaKey add a line:
(*output_key)[n] = '\0';
after the loop.
2) you're getting bitten by operator precedence - change, e.g.
*output_key[i] = input_string[i] - 'A';
to:
(*output_key)[i] = input_string[i] - 'A';
Related
I created this function to convert a number 'd' in base 10 to a number x in base 'b', unfortunately the function does not print, could someone help me?
// I don't understand why it doesn't print me the encode
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 20
// the function created to convert a number 'd' in base 10 to a number in base 'b'
char *encode(unsigned int d, unsigned char b){
if(b<2||b>16) return NULL;
char * resto = calloc (SIZE, sizeof(char));
int i=1;
while(d>0){//rimanenza d%b
char rimanenza = d%b ;
d = d/b;
if (b>10 && b<=16){//if the base is between 10 and 16 'rimanenza' can't be a number
if (rimanenza == 10) rimanenza = 'A';
if (rimanenza == 11) rimanenza = 'B';
if (rimanenza == 12) rimanenza = 'C';
if (rimanenza == 13) rimanenza = 'D';
if (rimanenza == 14) rimanenza = 'E';
if (rimanenza == 15) rimanenza = 'F';
}// save into resto from the end
resto [SIZE - i] = rimanenza;
i++;
}
return resto ;
}
int main (){
unsigned int d = 126;
unsigned char b = 3;
char *encoded = encode (d,b);
printf ("%u in base %u = %s\n",d,b,encoded);
free(encoded);
}
At least these problems:
Digit not converted to correct character when rimanenza < 10
When rimanenza is in the [0...9] range, convert it to characters ['0'...'9'].
rimanenza += '0';
while(d>0){ fails to form "0" when d originally 0.
Return wrong offset
return resto ; fails to return the beginning of the populated part of resto[].
More like:
// return resto ;
return memmove(resto, &resto[SIZE - i - 1], SIZE - i);
Fails to test if calloc() failed
Size too small
#define SIZE 20 is insufficient for encode(UINT_MAX, 2). #M Oehm
Lack of trailing null character
Code needs a '\0' after all the characters to be a string.
Code allocation is not sized to the data
Consider only allocating what is needed.
Untested repairs
#include <limits.h>
#define ENCODE_SZ (sizeof (unsigned) * CHAR_BIT + 1) // Size buffer to base 2 worst case
char* encode(unsigned d, unsigned b) {
if (b < 2 || b > 16) {
return NULL;
}
char buffer[ENCODE_SZ];
char *p = &buffer[ENCODE_SZ - 1]; // Point to last array element.
*p = '\0'; // Terminate array with a null character.
// Use a do loop to make sure code assigns at least 1 character.
do {
unsigned digit = d % b;
// Look-up character;
char ch = "0123456789ABCDEF"[digit];
p--;
*p = ch;
d /= b;
} while (d > 0);
// Determine string length
unsigned length = &buffer[ENCODE_SZ - 1] - p;
unsigned size = length + 1;
char *resto = malloc(size);
if (resto == NULL) {
return NULL;
}
// Copy and return.
return strcpy(resto, p);
}
I have tried out many ideas from SO. One of them worked (output was DEC 49 for HEX 31) when I tested it in here onlinegdb.
But, when I implemented it in my application, it didn't produce same results. (output was 31 for 31 again).
The idea is to use a string value (full of HEX pairs);
An example; 313030311b5b324a1b5b324a534f495f303032371b
I need to convert each integer pair (HEX) into equivalence decimal value.
e.g.
HEX => DEC
31 => 49
30 => 48
I will then send the DEC value using UART value by value.
The code I test the behavior is below and here;
But, it doesn't have to be that code, I am open to all suggestions as long as it does the job.
#include <stdio.h>
int isHexaDigit(char p) {
return (( '0' <= p && p <= '9' ) || ( 'A' <= p && p <= 'F'));
}
int main(int argc, char** argv)
{
char * str = "31";
char t[]="31";
char* p = t;
char val[3]; // 2 hexa digit
val[2] = 0; //and the final \0 for a string
int number;
while (isHexaDigit(*p) && isHexaDigit(*(p+1))) {
val[0] = *p;
val[1] = *(p+1);
sscanf(val,"%X", &number); // <---- Read hexa string into number
printf("\nNum=%i",number); // <---- Display number to decimal.
p++;
//p++;
if (!*p) break;
p++;
}
return 0;
}
EDIT
I minimized the code.
Odd-length string is ignored for the time being.
The code sends out the data byte by byte. In the terminal application,
I get the values as HEX, e.g. HEX 31 instead of DEC 49. They are actually same. But, a device I use requires DEC 49 version of the value (which is ASCII = 1)
Any pointer highly appreciated.
You can use strtol function to convert your hex string to binary and then convert it to a decimal string in a single line:
snprintf(str_dec, 4, "%ld", strtol(str_hex, NULL, 16));
Your code becomes:
#include <stdio.h>
#include <stdlib.h>
int isHexaDigit(char p) {
return (( '0' <= p && p <= '9' ) || ( 'A' <= p && p <= 'F'));
}
int main(int argc, char** argv)
{
char * str = "31";
char t[]="31";
char* p = t;
char str_hex[3] = {0,};
char str_dec[4] = {0,};
while (isHexaDigit(*p) && isHexaDigit(*(p+1))) {
str_hex[0] = *p;
str_hex[1] = *(p+1);
/* Convert hex string to decimal string */
snprintf(str_dec, 4, "%ld", strtol(str_hex, NULL, 16));
printf("str_dec = %s\n", str_dec);
/* Send the decimal string over UART1 */
if (str_dec[0]) UART1_Write(str_dec[0]);
if (str_dec[1]) UART1_Write(str_dec[1]);
if (str_dec[2]) UART1_Write(str_dec[2]);
/* Reset str_dec variable */
str_dec[0] = 0;
str_dec[1] = 0;
str_dec[2] = 0;
p++;
if (!*p) break;
p++;
}
return 0;
}
Can anyone help in writing a C parser (using Codewarrior) to parse the following file? I tried many C language json parser, but unfortunately didn't get the idea or they make it difficult.
[
[0,"Door1","Door1Drv","Calculator","Alarm"],
[1,"Door3","Door3Drv","Calculator","Alarm"],
[2,"Door2","Door2Drv","Calculator","Alarm"]]
For advance application, recommend to use Frozen. If your application has fix data format as shown above, see below for your ref.
Quite basic version look like below:
#include <stdio.h>
#define MAX_PRAM 4
struct param_t {
int id;
// FIXME: use pointer & malloc to allocate if possible
char data[MAX_PRAM][30];
};
static int parse(const char *buff, int start, const int end,
struct param_t *out)
{
char *ptr = out->data[0];
int state = 0;
int index = 0;
int param_index = 0;
printf("\t> parse next record<%d:%d>\n", start, end);
while((start < end) && (param_index < MAX_PRAM)) {
char ch = buff[start];
// printf("\t> state: %d, char '%c'\n", state, ch);
switch (state) {
case 0: // searching for start point
if ((ch >= '0') && (ch <= '9')) {
out->id = ch - '0';
state++;
}
break;
case 1: // parse number
if ((ch < '0') || (ch > '9')) {
printf ("\t> number %d\n", out->id);
state++;
if (ch == '"')
state++;
} else
out->id = (out->id * 10) + (ch - '0');
break;
case 2: // search string
if (ch == '"') {
index = 0;
state++;
}
break;
case 3: // get string
if (ch == '"') { // finish one string, parse next one if need
ptr[index] = '\0';
printf ("\t> string '%s', length %d\n",
out->data[param_index], index);
param_index++;
ptr = out->data[param_index];
state--;
} else
ptr[index++] = ch;
break;
default: // EOS - exit
break;
}
start++;
}
return (param_index >= 4) ? start : 0;
}
//
// main entry
//
int main(int argc, char *argv[]) {
int file = open("test.txt", 0 /* 0 ~ O_RDONLY in fcntl.h */ );
if (file) {
char buff[1024] = { 0 };
struct param_t param = { 0 };
int len = read(file, buff, 1024);
int pos = 0;
while((pos = parse(buff, pos, len, ¶m)) > 0) {
printf ("\t%d\n", param.id);
printf("[%4d] %d - %-10s | %-10s | %-15s | %-10s \n",
pos, param.id, param.data[0], param.data[1], param.data[2],
param.data[3]);
}
close(file);
}
}
With input:
[[10,"Door0",
"Door0Drv","Calculator0","Alarm0"],
[15,"Door1","Door1Drv","Calculator1","Alarm1"],
[230,"Door2","Door2Drv","Calculator2",
"Alarm2"]]
Output looks like:
> number 10
> string 'Door0', length 5
> string 'Door0Drv', length 8
> string 'Calculator0', length 11
> string 'Alarm0', length 6
10
[ 49] 10 - Door0 | Door0Drv | Calculator0 | Alarm0
> number 15
> string 'Door1', length 5
> string 'Door1Drv', length 8
> string 'Calculator1', length 11
> string 'Alarm1', length 6
15
[ 100] 15 - Door1 | Door1Drv | Calculator1 | Alarm1
> number 230
> string 'Door2', length 5
> string 'Door2Drv', length 8
> string 'Calculator2', length 11
> string 'Alarm2', length 6
230
[ 158] 230 - Door2 | Door2Drv | Calculator2 | Alarm2
Feel free to customize.
I cannot figure out why this thing doesn't scramble correctly. I read some other posts on this cipher and as far as I can tell I'm using the exact same algorithm as they are...
The areas commented out are tests I tried to make sure everything was passing through correctly. I believe it all goes through correctly then fails in the algorithm.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
string get_message(void);
string scramble(string key, string message);
int main(int argc, string argv[])
{
if(argc == 2)
{
string key;
string message;
key = argv[1];
//printf("KEY: %s<<",key);
message = get_message();
scramble(key, message);
}
else
{
printf("Please enter 2 arguments.\n");
return 1;
}
}
string get_message(void)
{
string message = "";
do
{
message = GetString();
}
while(strlen(message) < 1);
return message;
}
string scramble(string key,string message)
{
for(int i = 0, len = strlen(message), key_len = strlen(key); i < len; i++)
{
int letter = message[i];
//int Tkey = atoi(key[i % key_len]);
//printf("KEY: %d<<\n",Tkey);
if(islower(letter))
{
//printf("KEY(%d)",(key[i % key_len]-97));
letter = (((letter - 97) + (key[i % key_len])) % 26 + 97);
//printf("(%d)",(letter - 97) + (key[i % key_len])%26);
printf("%c",letter);
}
else if(isupper(letter))
{
//printf("(%d)", key[i]);
//printf("(%c)",letter); WE HAVE CORRECT LETTER
letter = (((letter - 65) + (key[i % key_len])) % 26 + 65);
printf("%c",letter);
}
}
printf("\n");
return 0;
}
I think your calculation is wrong:
You currently have
encryptedLetter = (letter - firstLetterOffset) + key[position % keyLength] % 26 + firstLetterOffset
by check the C operator precedence table we notice that % is evaluated before - or +, meaning that your code actually mean :
encryptedLetter = (letter - firstLetterOffset) + ( key[position % keyLength] % 26 ) + firstLetterOffset
Where you wanted :
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] ) % 26 + firstLetterOffset
Conclusion : you need to put more parenthese to specify in which order you which to evaluate your expression.
In addition you took the letter number for the text character but not for the key !
Correct expression
encryptedLetter = ( (letter - firstLetterOffset) + key[position % keyLength] - firstLetterOffset ) % 26 + firstLetterOffset
Demonstration in javascript
A general explanation of the Vigenere Cipher:
The Vigenere Cipher is a method of encryption that is similar to the Caesar Cipher. This Cipher takes in a word as an argument and interprets the alphabets of the word as follows- a as 0, b as 1, c as 2 and so on.
So if your input key is abc and you want something like "hi hello" to be encrypted, the output would entail h remaining the same, i shifting by 1 place, h shifting by 2 places, e again remaining the same (as it is being shifted by 0), l shifting by 1 place, the other l by 2 and so on so forth.
The basic idea is that each letter shifts by the corresponding letter in the argument and the spaces and other punctuation marks are ignored. If the argument is shorter than the message (as it is in most cases), the argument simply loops around the message.
My problem:
My message is just being encrypted by the first alphabet of the Vignere Cipher.
For example, ./vc bc ----> message: ABCDE ABCDE becomes BCDEF BCDEF. In other words, the entire message is just being shifted by the value of b when it should instead be shifted by the value of bc (+1 for the first alphabet and +2 for every other alphabet.)
I don't understand why is this happening despite being within a loop.
CODE:
# include <cs50.h>
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <ctype.h>
int main(int argc, string argv[])
{
string word = argv[1];
int i = 0;
int j = 0;
if (argc != 2 || isalpha(word[j]) == false)
{
printf("Please enter a valid command line argument! \n");
return 1;
}
else if (isalpha(word[j]))
{
printf("Message: ");
string message = GetString();
for (int n = strlen(message); i < n; i++)
{
int plaintext = message[i];
int ciphertext = word[j];
int uppcb = (plaintext - 65 + ciphertext - 65);
int upcipher1 = (uppcb) % 26;
int uplc = (plaintext - 65 + ciphertext - 97);
int upcipher2 = (uplc) % 26;
int lopcb = (plaintext - 97 + ciphertext - 97);
int locipher1 = (lopcb) % 26;
int lolp = (plaintext - 97 + ciphertext - 65);
int locipher2 = (lolp) % 26;
if (isupper(word[j]) && isupper(message[i]))
{
j = (j+1)%strlen(word);
int upcode = (upcipher1 + 65);
printf("%c", upcode);
}
else if (isupper(message[i]) && islower(word[j]))
{
j = (j+1)%strlen(word);
int upcode1 = (upcipher2 + 65);
printf("%c", upcode1);
}
else if (islower(message[i]) && islower(word[j]))
{
j = (j+1)%strlen(word);
int locode = (locipher1 + 97);
printf("%c", locode);
}
else if (islower(message[i]) && isupper(word[j]))
{
j = (j+1)%strlen(word);
int locode1 = (locipher2 +97);
printf("%c", locode1);
}
else
{
printf("%c", message[i]);
}
}
printf("\n");
}
}