I am writing a simple Caesar implementation for Amharic- one of the languages widely spoken in Ethiopia. Here is the code
main(){
setlocale(LC_ALL, " ");
int i, key=0;
wchar_t message[20];
wprintf(L"Enter message:>");
fgetws(message, sizeof(message), stdin);
wprintf(L"Enter cipher key:>");
wscanf(L"%d", &key);
/* basic input validation goes here */
for(i=0;message[i]!='\0'; i++){
message[i]=message[i]+key;
}
wprintf(L"The cipher is: %ls", message);
wprintf(L"\n");
return 0;
}
The code compiles without a warning. Works fine if key is less or equal to 5. The problem comes when key value is 6 and above. It prints one additional char so far as I tested it. I ran it through gdb to see where it's picking up the additional char. But couldn't make much sense. Here are my question:
Why does it work for the key 0 to 5 but not above?
Where does it get the additional char it prints for key grater than 5?
If it helps the sizeof wchar on my machine is 4byte.
Thank you
EDIT:
sample input:
message: ተደለ
key: 6
output: ቶዶሎ 0010
output I expect ቶዶሎ
The 0010 is displayed like those chars without a corresponding symbol on the unicode table.
Thanks again.
The extra char you see is the wide-char newline (0x000a) that is kept at the end of the string you read with fgetws and that you shift by 6 chars, resulting in 0x0010. That doesn't seem to be a printable character and the terminal decides to print the character code as plain hex numbers.
Remove the trailing new-line before shifting or shift only printable characters.
Related
I was doing a caesar cypher in c to practice and I make a functioning one; but it shows a strange behavior. The code is the one follows:
#define lenght 18
char * caesar ( char * cyphertext, int key){
static char result [lenght];
for ( int i= 0; i < lenght ; i++){
result [i] =(char)(((int) cyphertext[i]) + key) % 255;
}
return result;
}
int main(){
char * text = caesar("Hola buenas tardes", 23 );
printf("%s \n" , text );
char * check = caesar( text , 256 - 23);
printf("%s \n" , check);
return 0;
}
The encrypted version is _x7y|x7x{|; a shorter number; but when i run the second caesar cypher with the decryption
key it decrypts it with no problem to the original state. I have been looking around and it probably is about how
the characters are stored. I will very grateful for any help
The encrypted version is _x7y|x7x{|; a shorter number;
No, what printf prints is the above. Or even more precisely, that's how your terminal displays what printf prints. If you want to be certain exactly what the encrypted version is then you should run your program in a debugger, and use it to examine the bytes of the encoded version.
Your approach will encode some character codes from the printable ASCII range (codes 32 - 126 decimal) as codes outside that range. How your terminal handles those bytes depends on your configuration and environment, but if it expects UTF-8-encoded data then it will trip over invalid code sequences in the output, and if it expects an ISO-8859 encoding then some of the output codes will be interpreted as control characters from the C1 set. There are other possibilities.
Usually, a Caesar-cypher program is careful to map all printable characters to other printable characters, leaving others alone. The typical academic exercise is even more narrowly scoped, asking for a program that maps only the upper- and lowercase Latin letters, preserving case, and leaves all others (punctuation, digits, control characters) alone. This is, accordingly, left as an exercise.
The printf function should not be used to print the cipher text, it mainly support ascii characters and you have random unprintable characters. Consider converting it to a hexadecimal string.
My code asks a the 10 digit number, it reads it as a string, pass it to another function that checks if the user's input is a real number and has no characters or symbols with ASCII, and then if it's good, with atof it changes the string into a number for a variable.
I want the user to only introduce 10 digits/characters on the input console, I mean, if the user would put a 11 character for example, the console just don't grab it, or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit, the problem is, when i tried to use this method, for example if i put some big numbers like a 40 digit number, then the program goes crazy and send just incomprehensible results like "1.#J", or if I put a character in middle of the numbers, then it sends the corresponding error message i set for the user to not put characters, but it still grabs part of the number and accept it as it is nothing wrong, here's the main of code I tried:
int main() {
char chain[10];
float N;
int valid=0;
do{
printf("introduce real numbers: ");
fgets(chain, sizeof(chain), stdin);
if( chain[strlen(chain)-1] == '\n')
chain[strlen(chain)-1] = '\0';
valid=validate_numbers(chain);
}while(valid==0);
N=atof(chain);
printf("float number is: %.2f", N);
getche();
return 0;
}
Here's the rest of the code for more extense check: Pastebin
And sorry if there's some novice errors or the question is plain simple, im quite new programing.
Change this:
char chain[10];
to this:
char chain[11]; // +1 for the NULL terminator
since C-strings should be NULL terminated, thus we need one cell reserved for the NULL-terminator in our array (which will store our string).
I mean, if the user would put a 11 character for example, the console just don't grab it
Not possible in C.
or in the case this is impossible for C, make that if the user put more than 12 characters on the input, then the program launches an error message saying it exceeds the limit.
Yes, let's do that! Read the string, and if the length of it is more than 10 characters, then print an error message.
Allow chain array to be of size 12 (10 for the maximum length of the valid input, 1 for an extra character (if any) and 1 for the NULL-terminator), so that we can store the extra character, if any.
Example:
#include <stdio.h>
#include <string.h>
int main(void)
{
char chain[12];
printf("introduce real numbers:\n");
fgets(chain, sizeof(chain), stdin);
chain[strcspn(chain, "\n")] = '\0';
if(strlen(chain) > 10)
{
printf("Error: Maximum length of chain is 10! Exiting..\n");
return 1;
}
return 0;
}
Note: You could use EXIT_SUCCESS and EXIT_FAILURE, instead of plain numbers (1 and 0 respectively): Should I return 0 or 1 for successful function?
Irrelevant to OP's question: In the full version of your code though, there is a plethora of problems, such as this top line of code int valid=validate_numbers(char number[]);, which wishes to declare the method. It should be just validate_numbers(char number[]);. The same holds true for the definition of the method too. Make sure you go through all your code again, and read the messages the compiler gifts to you. :)
What about using scanf instead of fgets? This should read 9 characters and save them as a string:
scanf("%9s" , &chain)
I'd suggest reading https://en.m.wikipedia.org/wiki/Scanf_format_string and man pages as well.
I've been trying to make a program on Vernam Cipher which requires me to XOR two strings. I tried to do this program in C and have been getting an error.The length of the two strings are the same.
#include<stdio.h>
#include<string.h>
int main()
{
printf("Enter your string to be encrypted ");
char a[50];
char b[50];
scanf("%s",a);
printf("Enter the key ");
scanf("%s",b);
char c[50];
int q=strlen(a);
int i=0;
for(i=0;i<q;i++)
{
c[i]=(char)(a[i]^b[i]);
}
printf("%s",c);
}
Whenever I run the code, I get output as ????? in boxes. What is the method to XOR these two strings ?
I've been trying to make a program on Vernam Cipher which requires me to XOR two strings
Yes, it does, but that's not the only thing it requires. The Vernam cipher involves first representing the message and key in the ITA2 encoding (also known as Baudot-Murray code), and then computing the XOR of each pair of corresponding character codes from the message and key streams.
Moreover, to display the result in the manner you indicate wanting to do, you must first convert it from ITA2 to the appropriate character encoding for your locale, which is probably a superset of ASCII.
The transcoding to and from ITA2 is relatively straightforward, but not so trivial that I'm inclined to write them for you. There is a code chart at the ITA2 link above.
Note also that ITA2 is a stateful encoding that includes shift codes and a null character. This implies that the enciphered message may contain non-printing characters, which could cause some confusion, including a null character, which will be misinterpreted as a string terminator if you are not careful. More importantly, encoding in ITA2 may increase the length of the message as a result of a need to insert shift codes.
Additionally, as a technical matter, if you want to treat the enciphered bytes as a C string, then you need to ensure that it is terminated with a null character. On a related note, scanf() will do that for the strings it reads, which uses one character, leaving you only 49 each for the actual message and key characters.
What is the method to XOR these two strings ?
The XOR itself is not your problem. Your code for that is fine. The problem is that you are XORing the wrong values, and (once the preceding is corrected) outputting the result in a manner that does not serve your purpose.
Whenever I run the code, I get output as ????? in boxes...
XORing two printable characters does not always result in a printable value.
Consider the following:
the ^ operator operates at the bit level.
there is a limited range of values that are printable. (from here):
Control Characters (0–31 & 127): Control characters are not printable characters. They are used to send commands to the PC or the
printer and are based on telex technology. With these characters, you
can set line breaks or tabs. Today, they are mostly out of use.
Special Characters (32–47 / 58–64 / 91–96 / 123–126): Special characters include all printable characters that are neither letters
nor numbers. These include punctuation or technical, mathematical
characters. ASCII also includes the space (a non-visible but printable
character), and, therefore, does not belong to the control characters
category, as one might suspect.
Numbers (30–39): These numbers include the ten Arabic numerals from 0-9.
Letters (65–90 / 97–122): Letters are divided into two blocks, with the first group containing the uppercase letters and the second
group containing the lowercase.
Using the following two strings and the following code:
char str1 = {"asdf"};
char str1 = {"jkl;"};
Following demonstrates XORing the elements of the strings:
int main(void)
{
char str1[] = {"asdf"};
char str2[] = {"jkl;"};
for(int i=0;i<sizeof(str1)/sizeof(str1[i]);i++)
{
printf("%d ^ %d: %d\n", str1[i],str2[i], str1[i]^str2[i]);
}
getchar();
return 0;
}
While all of the input characters are printable (except the NULL character), not all of the XOR results of corresponding characters are:
97 ^ 106: 11 //not printable
115 ^ 107: 24 //not printable
100 ^ 108: 8 //not printable
102 ^ 59: 93
0 ^ 0: 0
This is why you are seeing the odd output. While all of the values may be completely valid for your purposes, they are not all printable.
i am programming in C and i have a problem while casting an int into a char.
I am using my mac with Xcode to program c.
The code is:
int main(){
int t = 2;
printf("test %s\n", (char)t); //EXC_BAD_ACCESS
return 0;
}
I tried all I found in many post, I really don't know what is going on... any suggestion?
Please include the goal of your code in your question not in a comment below.
If you want the output
test 2
your have to change %s to %d
printf("test %d\n", t);
I guess you got the wrong idea about the %s. It does not tell the printf that you want to have the int as string, it does tell printf that the parameter is a string! It is obviously not, so you got the exception.
if you use %c you tell the printf function that you want to output your number as character from your current ASCII table. For example 65 is 'A'.
If you have a concatenation situation like
strcpy(str_buscar, "controlID='");
strcat(str_buscar, (char) t);
strcat(str_buscar, "'");
you need itoa instead of the cast:
strcat(str_buscar, (char) t);
you need the follow:
char buffer[32]; // enough space for a "number as string"
itoa(t,buffer,10);
strcat(str_buscar, buffer);
a (IMHO) shortcut is to "print" to a buffer with sprintf
sprintf(str_buscar,"controlID='%d'",t);
instead of printing to a console sprintf prints into the given buffer. Make shure that your buffer str_buscar is big enough.
The %s format specifier represents a string, not an individual character. Printf thinks that the number 2 you're passing it is a string's address. It tries to access the memory address 2 and fails, because that address doesn't exist.
If you want to print a character, you'll want the %c specifier. This tells printf to print the character whose ASCII code is 2. The ASCII character number 2 is, according to the ASCII table, a control character that cannot be printed, which is why you're getting strange output.
If you actually want to print the character '2' (which has a different code, 50), you will want to use something like:
printf("test: %c", (char)('0' + c));
This example leverages the fact that all ASCII characters have consecutive codes, starting with 48 ('0'). This way, if you wanted to print the digit 0, you'd end up printing the '0' character (ASCII code 48 = 48 + 0). If you want to print the digit 2, you'll end up printing the '2' character (50 = 48 + 2).
This way, however, is a bit clunky and fails when encountering numbers larger than 9 (i.e. it only works with digits). The easier way consists of no longer working with characters at all and, instead, using the '%d' specifier (used for printing whole number):
int t = 0;
printf("test: %d", t);
I have an application that needs to take the MsgId from a Websphere MQ message and write that as a file name on the file system....but have the HEX value string....
Note that a MsgId on Websphere MQ is actually a byte array of 24 long, and this is where I think my problem is coming in.
So here are some snippets of the code:
#define MSGID_LEN 24
#define MSGID_HEX_LEN 48
...
...
char *uuid = NULL;
char *buffer = NULL;
char msgid_hex[MSGID_HEX_LEN];
char *pmsgid_hex = msgid_hex;
char msgid[MSGID_LEN];
memcpy(msgid, md.MsgId, MSGID_LEN);
convertMsgIdToHex(pmsgid_hex, msgid);
uuid = malloc(MSGID_HEX_LEN * sizeof(char));
memcpy(uuid, pmsgid_hex, MSGID_HEX_LEN);
..
..
int convertMsgIdToHex(char *msgid_hex, char msgid[MSGID_LEN]){
int len = strlen(msgid);
int i;
for(i=0; i<len;i++){
sprintf(msgid_hex, "%02X", (unsigned char)msgid[i]);
msgid_hex +=2;
};
}
The problem is that their are sometime funny characters in the MSGID on Wensphere MQ and it seems I do not know how to convert these into there HEX equivalent.
For example, if I debug the application the MsgId is:
"AMQ QM01 \327\354\254N\027\232\002 "
And the hex string I get after the function above is:
"414D5120514D30312020202020202020D7ECAC4E179A0220"
This is fine, but sometimes I get funny characters like little hearts and symbols and when I try write the HEX string as a file name it works but has "invalid encoding" in the string as well....
What is the correct way I should work here? Should I convert from BYTE array to HEX string? If so do someone have a snippet of code on how I could possible change my function above to work with bytes instead of chars?
Should I be declaring my "char" variables are unsigned chars?
Thanks for the help ;-)
Lynton
You shouldn't use strlen to determine the message length: strlen should be used only for null-terminated strings. Since the message here is in a binary encoding, it may include embedded zeroes (which will cause the message to be truncated) or it may contain no zeroes - which will cause a buffer overflow since you will read past the end of the message.
Since apparently the message length is MSGID_LEN here, you should use that for the length.
Additionally, you need to make sure you output buffer is large enough. Its size should be at least 2*MSGID_LEN + 1: 2 characters for each input byte, plus one for the null terminator.