the int value changed in For loop without being calculated - c

i am new to c, and I am building a cipher text converter. I have a main function to take a Key value (int k) from the user and pass that value to this function:
int ciphertextCoverter (int k)
{
printf("key=%i\n",k);
char ciphertext[] = "";
string plaintext = get_string("plaintext: ");
for (int n = 0, x = strlen(plaintext); n < x; n++)
{
printf("key in FOR loop: %i",k);
if isupper(plaintext[n])
{
printf("key in IF loop: %i",k);
ciphertext[n] = (plaintext[n] - 'A'+ k ) % 26 + 65;
printf("plaintext- %i %c %i %i %i %i %i\n",k, plaintext[n],plaintext[n], plaintext[n]-'A', (plaintext[n] - 'A'+ k), (plaintext[n] - 'A'+ k) % 26, (plaintext[n] - 'A'+ k) % 26+ 65);
}
else
{
ciphertext[n] = (plaintext[n] - 'a'+ k) % 26 + 97;
}
}
printf("ciphertext: %s\n",ciphertext);
return 0;
}
I used printf to find out that the value of int k which I passed on from the main function has changed value in the for loop, but I want to stay as a const. Please help me! what have I done wrong?

You are declaring ciphertext as an array of size 1, so you cannot write any data to it. Give it some size; something like:
string plaintext = get_string("plaintext: ");
char ciphertext[strlen(plaintext) + 1];
should work. Just remember to write the null terminator at the end: ciphertext[x] = '\0'

You have declared character array of size 1. And you are storing x characters in ciphertext[]. First declare array of any size or create array dynamically.
char ciphertext[] = "";

Related

Why does my C array remember old data from a previous function call?

When I run the following C code I get the values:
222222222
312222222
102222222
I was expecting the values:
222222222
31
10
Why does the char number[] defined in my intToStr function remember previous values? I thought once the function call ended all local data was more or less destroyed.
#include <stdio.h>
void intToStr(int n);
int main(void)
{
intToStr(222222222);
intToStr(31);
intToStr(10);
return 0;
}
void intToStr(int n)
{
char number[10];
int l = 0;
if (n < 0)
{
l++;
number[0] = '-';
n *= -1;
}
int nCopy = n;
while (nCopy > 9)
{
nCopy /= 10;
l++;
}
int r;
while (n > 9)
{
r = n % 10;
n /= 10;
number[l--] = r + '0';
}
number[l] = n + '0';
printf("%s\n", number);
}
the array should not remember the old data
For each program, the C standard either:
specifies what the program should do
says that it is not specified what the program should do
It hardly ever says that the program should not do something in particular.
In this case, the standard says that it is not specified what characters should be in the array at the start of the function. They can be anything at all. Characters from the previous call is one particular case of "anything at all".
That's undefined behavior. If only the first 3 character are set, it may print 312222222 or it may print 312???????????????????
The last characters in char number[10] are not initialized, that means the compiler may decide to leave it alone and the old values stay, or something else happens.
Otherwise printf doesn't know where the string end, it keeps printing until it randomly hits a zero.
If there is buffer overrun printf finds a different set of characters in memory (which we are not supposed to be accessing) and the program keeps printing those same characters until it randomly hits a zero and finally stops.
To fix it, simply make sure there is '\0' at the end. You can also add additional check to make sure the length does not exceed the buffer size
Working example:
char number[10];
int l = 0;
if (n < 0)
{
l++;
number[0] = '-';
n *= -1;
}
if (n < 0) return;
int nCopy = n;
while (nCopy > 9)
{
nCopy /= 10;
l++;
}
int len = l;
if (len + 1 > sizeof(number))
return;
number[len + 1] = '\0';
int r;
while (n > 9)
{
r = n % 10;
n /= 10;
number[l--] = r + '0';
}
number[l] = n + '0';
printf("%s\n", number);

Decrypting Vernam Cipher

I'm creating a code for encryption and decryption for Vernam Cipher.
Initially, to encrypt a message, I would have to use a function that would generate my OTP. This function produces random numbers from 1-26 (to signify the english alphabet) and would be stored in an array of integers. The size is equal to the length of the message to be encrypted.
I was able to do that. My problem is how I would decrypt it.
I have this code.
My OTP array, since each element is randomized between 1-26, would signify an nth letter of the alphabet. e.g. 25 would signify the letter 'y' and so on.
The logic of my encryption is that since the size of my OTP array is equal to the length of my message, I would do XOR on each of the character of my message and my OTP. This is after converting my OTP array to corresponding letters of the alphabet depending on each element's randomized assigned number.
I was able to do the encryption part already. But whenever I try to decrypt, I get a different message from what I initially inputted.
void encryptiondecryption(char msg[], char key[]){
int i,j=0,x,m=0;
char output[100];
char output2[100];
/* Loop to remove all spaces in the message here*/
/*Encryption*/
int modd;
for(x = 0; msg[x]!='\0'; x++) {
printf("\nletter:%c - key:%c",msg[x], key[x] );
modd = (msg[x] ^ key[x]);
if(modd == 26){
output[x] = 'a'+ (modd%26)+25;
}else{
output[x] = 'a'+ (modd%26)-1;
}
}
output[x]='\0';
printf("\nEncrypted Message:\n");
for(x = 0; output[x]!='\0'; x++) {
printf("%c",output[x]);
}
/* decryption */
int modd2,diff,sum, toXOR;
printf("\n\ndecryption\n");
for(x = 0; output[x]!='\0'; x++) {
printf("\nletter:%c - key:%c",output[x], key[x] );
diff = output[x] - 'a';
if(diff == 25){
sum = diff - 25;
toXOR = sum + 26;
output2[x] = toXOR ^ key[x];
}else{
sum = diff + 1;
toXOR = sum + 26;
output2[x] = toXOR ^ key[x];
}
}
output2[x]='\0';
printf("\n Output for Decryption\n");
for(i = 0; output2[i]!='\0'; i++) {
printf("%c",output2[i]);
}
}
In addition, this is my generateOTP function.
char* generateKey(char msg[]){
srand(time(NULL));
int len = strlen(msg);
int numbers[len];
int x,y=0, m=0,a;
for(x=0;x<len;x++){
if(msg[x]!='_') m++;
}
printf("generated key is . . .\n");
int *getOTP = malloc (sizeof (int)*len);
for(x=0;x<m;x++){
getOTP[x] = rand() % (26 - 1 + 1) + 1;
}
for(x=0;x<m;x++){
printf("%d ", getOTP[x]);
}
char *letterOTP = malloc (sizeof (char) * len);
int getOTP2[m];
for(x=0;x<m;x++){
getOTP2[x] = getOTP[x];
}
int md;
for(x=0;x<m;x++){
md = (getOTP2[x]) % 26;
if(md ==0){
letterOTP[x] =( 97 + (md));
}else{
letterOTP[x] =( 97 + (md) - 1);
}
}
letterOTP[x] = '\0';
return letterOTP;
}
Basically, what this does as I have mentioned above, is that assigns a letter of an alphabet depending on what number an element in the array was randomly assigned to (e.g. 25 = 'y', 5 = 'e')

Cipher Function Producing Unwanted Results in the Last Character of Output

I have been spending all day trying to figure out what I did wrong with this enciphering function I created.
The function works by taking in a keyword which it then converts to an ASCII values and then takes that value and formats it into something that will work with an alphabetical index eg: A= 0, B= 1, C= 2, etc... It then converts all of the plain text using the same method. After that it shifts over the characters of the plain text and then adds the characters value from the keyword iterating over the keyword in a loop until it is done encrypting the plain text.
It works for all my tests except for one which went like this:
Keyword is BaZ
input:
plaintext: BaRFoo
output:
ciphertext: CaQGoh
but the desired output is
ciphertext: CaQGon
I am using the following encipher function:
void encipher(char* plainText, char*key)
{
printf("ciphertext: ");
char alphabeticalIndex[26] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int currentKeyChar = 0;
for(int i = 0, n = strlen(plainText); i < n; i++)
{
// check if the end of they key has been reached, if so then reset it
if(currentKeyChar >= strlen(key)) currentKeyChar = 0;
if(isalpha(plainText[i]) == false) printf("%c", plainText[i]);
if(isupper(plainText[i]))
{
// find the cipher character as an int then add it as the key to captialCharNum
int capitalCipherCharNum = ((int) key[currentKeyChar] - 65);
int capitalCharNum = (((int) plainText[i] - 65) + capitalCipherCharNum) % 26;
printf("%c", toupper(alphabeticalIndex[capitalCharNum]));
}
if(islower(plainText[i]))
{
// same as it was for capitals but in this case its lowercase
int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);
int lowerCharNum = (((int) plainText[i] - 97) + lowerCipherCharNum) % 26;
printf("%c", tolower(alphabeticalIndex[lowerCharNum]));
}
currentKeyChar++;
}
printf("\n");
}
Your error is here:
int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);
When key[currentKeyChar] is uppercase, lowerCipherCharNum is negative, resulting in your cipher value being wrong. To fix the problem you need:
int lowerCipherCharNum;
if (islower (key[currentKeyChar]))
lowerCipherCharNum = key[currentKeyChar] - 'a';
else
lowerCipherCharNum = key[currentKeyChar] - 'A';
This will correct your expected output.
While there is nothing wrong with using array indexing to work your way down each string, using pointer arithmetic can greatly simplify your code. (you also have unnecessary and repeated calls to strlen that should be removed (or at least minimized by computing the length of key once rather than every time you check it.))
An example of how using pointer arithmetic can simplify your logic (and shortening your variable names because I don't like to type), you could do something similar to the following:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
void encipher (const char *plaintext, const char *key)
{
const char *aidx = "abcdefghijklmnopqrstuvwxyz",
*p = plaintext,
*k = key;
printf ("ciphertext: ");
while (*p) {
if (isalpha (*p) == 0) printf ("%c", *p);
if (isupper (*p)) {
/* find the cipher character as an int then add it as the key */
int ccicn = (*k - 'A');
int ccnum = (*p - 'A' + ccicn) % 26;
putchar (toupper (aidx[ccnum]));
}
if (islower (*p)) {
/* same as it was for capitals but in this case its lowercase */
int lcicn = islower (*k) ? *k - 'a' : *k - 'A';
int lcnum = (*p - 'a' + lcicn) % 26;
putchar (aidx[lcnum]);
}
p++;
if (*k) k++;
if (!*k) k = key;
}
putchar ('\n'); /* don't use printf for one-character */
}
int main (int argc, char **argv) {
const char *s = argc > 1 ? argv[1] : "BaRFoo",
*key = argc > 2 ? argv[2] : "BaZ";
encipher (s, key);
return 0;
}
Example Use/Output
$ ./bin/encipher
ciphertext: CaQGon
(note: the comment /* don't use printf for one-character */)
While not an error, the standard coding style for C avoids the use of camelCase or MixedCase variable names in favor of all lower-case while reserving upper-case names for use with macros and constants. It is a matter of style -- so it is completely up to you, but failing to follow it can lead to the wrong first impression in some circles.
Below is an "edited" version of your encipher function with a few additional thoughts in comments and the code spaced a little wider (which you may appreciate more as your eyes get older)
/* if plainText and key are not modified, pass them as 'const char *' */
void encipher (const char *plainText, const char *key)
{
/* place variables before executed code if you have the option...
* (just increases portability to older compilers (like Win7))
*/
char alphabeticalIndex[26] = "abcdefghijklmnopqrstuvwxyz";
int currentKeyChar = 0;
size_t keylen = strlen (key);
printf ("ciphertext: ");
for (int i = 0, n = strlen (plainText); i < n; i++)
{
// check if the end of they key has been reached, if so then reset it
if (currentKeyChar >= (int)keylen) currentKeyChar = 0;
if (isalpha (plainText[i]) == 0) putchar (plainText[i]);
if (isupper (plainText[i]))
{
// find the cipher character as an int then add it as the key
int capitalCipherCharNum = ((int) key[currentKeyChar] - 65);
int capitalCharNum = (plainText[i] - 65 + capitalCipherCharNum) % 26;
putchar (toupper (alphabeticalIndex[capitalCharNum]));
}
if (islower (plainText[i]))
{
// same as it was for capitals but in this case its lowercase
// int lowerCipherCharNum = ((int) key[currentKeyChar] - 97);
int lowerCipherCharNum;
if (islower (key[currentKeyChar]))
lowerCipherCharNum = key[currentKeyChar] - 'a';
else
lowerCipherCharNum = key[currentKeyChar] - 'A';
int lowerCharNum = (plainText[i] - 97 + lowerCipherCharNum) % 26;
putchar (tolower (alphabeticalIndex[lowerCharNum]));
}
currentKeyChar++;
}
putchar ('\n'); /* don't use printf for one-character */
}
Look things over and let me know if you have further questions.

Formatting text file into columns with sprintf with C

I have a basic text file I point my program at to run that has numbers line by line such as:
3
30
300
3000
30000
300000
3000000
30000000
300000000
-3
-30
-300
-3000
-30000
-300000
-3000000
-30000000
-300000000
and I need to print them out into evenly spaced columns and I want them to fit into 40 characters (4 columns wide). I want to use the sprintf function to do this. So basically print each number out plus 2 spaces for formatting and fit within 40 characters total. So far this is what I have.
int main(int argc, char *argv[]){
int a, b, num[1000], nums = 0;
char str[40];
FILE *pt;
int col, max, w;
if(argc < 2){
printf("Usage %s <No Files>\n", argv[0]);
return 1;
}
if((pt = fopen(argv[1], "r")) == NULL){
printf("Unable to open %s for reading.\n", argv[1]);
return 1;
}
while(fscanf(pt, "%d", &b) == 1){
num[nums++] = b;
}
w = sprintf(str, "%*d", num[a]);
if(max < w){
col = 40 / (max + 2);
printf("%d %d\n", w, num[a]);
}
return 0;
}
I just get garbage when I point it to the text file mentioned in the above. Any advice?
To print N numbers in 4 columns with width 10 characters use printf("%10d") inside the loop that add new line (\n) after each 4th printing, e.g.:
for (int i = 1; i <= nums; i++)
{
printf("%10d", num[i-1]); // or printf("%-10d", num[i-1]);
if (i % 4 == 0)
printf("\n"); // or putchar ('\n')
}
sign - in the format %-10d change alignment.
As you see sprinf is not used here, I use printf for each number to print the value at screen (standard output).
UPDATE:
If you want to find optimal width of the column, and use it for output, e.g. using the number of digits in your biggest number (let it be maxValue an integer value found in the array num), you can find the minimum required number of digits (let it be minWidth), like:
char buff[20] = {0};
int minWidth = strlen(_itoa(maxValue,buff,10));
and then change the printing loop like:
for (int i = 1; i <= nums; i++)
{
printf("%*d", minWidth + 1, num[i - 1]);
if (i % 4 == 0) putchar('\n');
}
here vlaue minWidth + 1 will be used in format specifier %*d instead of *, and +1 is used for minimum separation between columns in one space (of course, there can be 2 or 3).
Finally, having the column width calculated, you can find the number of column for your screen and use this value for starting new line, e.g.:
const int screenWidth = 80;
int colWidth = minWidth + 2; // here 2 is added for minimum separation of columns
int colNum = screenWidth / colWidth;
for (int i = 1; i <= nums; i++)
{
printf("%*d", colWidth, num[i - 1]);
if ( !(i % colNum) ) putchar('\n'); // !(i % colNum) is the same to i % colNum == 0
}
This is my second answer for the same question, but this answer more close to the topic - here output is made to the string with sprintf.
So, lets we have array of numbers int num[1000] and we need to print nums of them to several string (length is limited by value stringMaxLength) using formatting as columns with width depending on length of number representation (maximum number in the array).
The following snippet has comments for all operations
// string that will be made from numbers
const int stringMaxLength = 120;
char str[stringMaxLength + 1]; // just one string
// find longest number considering sign
char buff[20] = { 0 };
int maxNumWidth = 0, numWidth;
int n;
for (n = 0; n < nums; n++)
{
numWidth = strlen(_itoa(num[n], buff, 10));
if (numWidth > maxNumWidth)
maxNumWidth = numWidth;
}
int colWidth = maxNumWidth + 1; // a column size with one space between columns
int colNum = stringMaxLength / colWidth; // number of columns in one string
int s, i; // i - nums counter, s - strings counter
for (i = 0, s = 1; i < nums; s++) // loop counts strings but with condition for nums
{
int sizeCnt = 0; // start making new string str
// loop works while there are numbers and the line is not filled completely
while (i < nums)
{
// add next number (column) to the string and increase string size
sizeCnt += sprintf(str + sizeCnt, "%*d", colWidth, num[i++]);
if (i % colNum == 0) // if string has colNum numbers it is full
{
break; // stop while loop
}
}
// next string is ready and can be used
printf("%d : %s\n", s, str); // e.g. for output
}

Rearranging string letters

I was doing a program to copy all string words other than its first 2 words and putting a x at the end of it.
However i cant put x at its end. Please help!!!!
Below is my code.
#include<stdio.h>
#include<string.h>
int main()
{
char a[25], b[25];
int i, j, count = 0, l, k;
scanf("%[^\n]s", a);
i = strlen(a);
if (i > 20)
printf("Given Sentence is too long.");
else
{/* checking for first 2 words and counting 2 spaces*/
for (j = 0; j < i; j++)
{
if (a[j] == ' ')
count = count + 1;
if (count == 2)
{
k = j;
break;
}
}
/* copying remaining string into new one*/
for (j = 0; j < i - k; j++)
{
b[j] = a[j + k];
}
b[j + 1] = 'x';
printf("%s", b);
}
}
you are removing first two index. But you wrote k=j and if you check the current value j there it's 1. so you are updating wrongly k because you removed 2 indexes. So k value should be 2. So checked the below code
/* copying remaining string into new one*/
for (j = 0; j < i - 2; j++)
{
b[j] = a[j + 2];
}
b[j + 1] = 'x';
printf("%s", b);
Your index is off by one. After your second loop, the condition j < i-k was false, so j now is i-k. Therefore, the character after the end of what you copied is b[j], not b[j+1]. The correct line would therefore be b[j] = 'x';.
Just changing this would leave you with something that is not a string. A string is defined as a sequence of char, ending with a '\0' char. So you have to add b[j+1] = 0; as well.
After these changes, your code does what you intended, but still has undefined behavior.
One problem is that your scanf() will happily overflow your buffer -- use a field width here: scanf("%24[^\n]", a);. And by the way, the s at the and doesn't make any sense, you use either the s conversion or the [] conversion.
A somewhat sensible implementation would use functions suited for the job, like e.g. this:
#include<stdio.h>
#include<string.h>
int main(void)
{
// memory is *cheap* nowadays, these buffers are still somewhat tiny:
char a[256];
char b[256];
// read a line
if (!fgets(a, 256, stdin)) return 1;
// and strip the newline character if present
a[strcspn(a, "\n")] = 0;
// find first space
char *space = strchr(a, ' ');
// find second space
if (space) space = strchr(space+1, ' ');
if (space)
{
// have two spaces, copy the rest
strcpy(b, space+1);
// and append 'x':
strcat(b, "x");
}
else
{
// empty string:
b[0] = 0;
}
printf("%s",b);
return 0;
}
For functions you don't know, google for man <function>.
In C strings are array of chars as you know and the way C knows it is end of the string is '\0' character. In your example you are missing at the last few lines
/* copying remaining string into new one*/
for(j=0;j<i-k;j++)
{
b[j]=a[j+k];
}
b[j+1]='x';
printf("%s",b);
after the loop ends j is already increased 1 before it quits the loop.
So if your string before x is "test", it is like
't', 'e', 's', 't','\0' in char array, and since your j is increased more than it should have, it gets to the point just right of '\0', but characters after '\0' doesnt matter, because it is the end, so your x will not be added. Simple change to
b[j]='x';

Resources