Cipher and decipher string by shifting +1 using pointer - c

Hi I am stuck while trying to cipher and decipher string using pointer. i need to shift the alphabet by +1.
example: Hello will be Ifmmp. And i also need to eliminate other characters such as $%^^. so when the string is 'z' +1 would give me 'a'
Here is my code.
char *cipher(char *s) {
int i =0;
int shift = 1;
while(*(s+i)!= '\0') {
if (*(s+i)) {
*(s+i)+= (shift);
}
i++;
}
}
char *decipher(char *s) {
int i =0;
int shift = -1;
while(*(s+i)!= '\0') {
if (*(s+i) +shift) {
*(s+i)+= (shift);
}
i++;
}
}
my current output is:
To cipher: abcxyz -> bcdyz{
To decipher: bcdyz{ -> abcxyz
Thanks

First of all, change the while to For-Loop, if you increase itearator at the for loop and its your condition the best readable code is For-Loop
Second, you need to add condtion-
If the letter is 'z' assign 'a'
else do the same thing
Third if you want to avoide another letters you need to add condition:
if((*s+i)<'a' || (*s+i)>'z'){
do what you want
} else {
avoide
} /// it will work if you use character encoding that the alphebet is by order and continuous
I add the code with change at chipher function, you will add the same to the next function
char *cipher(char *s){
int shift = 1;
for(int i=0; *(s+i)!= '\0'; i++){
if (*(s+i)){
//i add that condtion for 'z' you need to add the same condition to the next function
if(*(s+i)=='z'){
*(s+i)='a';
}else{
*(s+i)+= (shift);
}
}
}
}
char *decipher(char *s){
int shift = -1;
for(int i=0 ;*(s+i)!= '\0'; i++){
if (*(s+i) +shift){
*(s+i)+= (shift);
}
}
}

i need to shift the alphabet by +1
Shift only characters a-z. So code must detect those
char *shift_AZ(char *s, int shift) {
// Bring shift into 0-25 range
shift %= 26;
if (shift < 0) shift += 26;
// loop until at end of string
// while(*(s+i)!= '\0') {
while(*s) {
// Assuming ASCII, detect select characters
if ((*s >= 'a') && (*s <= 'z')) {
// Do the shift, wrap around via %26
*s = (*s - 'a' + shift)%26 + 'a';
}
s++; // next chraracter
}
char *cipher(char *s) {
return shift_AZ(s, 1);
}
char *decipher(char *s) {
return shift_AZ(s, -1);
}

Related

camelCase function in C, unable to remove duplicate chars after converting to uppercase

void camelCase(char* word)
{
/*Convert to camelCase*/
int sLength = stringLength(word);
int i,j;
for (int i = 0; i < sLength; i++){
if (word[i] == 32)
word[i] = '_';
}
//remove staring char '_',*,numbers,$ from starting
for (i = 0; i < sLength; i++){
if (word[i] == '_'){
word[i] = toUpperCase(word[i + 1]);
}
else
word[i] = toLowerCase(word[i]);
}
word[0] = toLowerCase(word[0]);
//remove any special chars if any in the string
for(i = 0; word[i] != '\0'; ++i)
{
while (!((word[i] >= 'a' && word[i] <= 'z') || (word[i] >= 'A' && word[i] <= 'Z') || word[i] == '\0') )
{
for(j = i; word[j] != '\0'; ++j)
{
word[j] = word[j+1];
}
word[j] = '\0';
}
}
}
int main()
{
char *wordArray;
wordArray = (char*)malloc(sizeof(char)*100);
// Read the string from the keyboard
printf("Enter word: ");
scanf("%s", wordArray);
// Call camelCase
camelCase(wordArray);
// Print the new string
printf("%s\n", wordArray);
return 0;
}
I am writing a function that takes in this for example _random__word_provided, and I am to remove any additional underscores or special characters, capitalize the first word after an underscore and reprint the word without any underscores. The above example would come out like this randomWordProvided.
When I run my code though this is what I am getting rrandomWwordPprovided. I am unsure where my loop is having issues. Any guidance would be appreciated. Thank you!
You are WAY over-processing the string...
First measure the length. Why? You can find the '\0' eventually.
Then convert ' 's to underscores (don't use magic numbers in code).
Then force almost everything to lowercase.
Then try to "strip out" non-alphas, cajoling the next character to uppercase.
(The non-alpha '_' has already been replaced with an uppercase version of the next character... This is causing the "thewWho" duplication to remain in the string. There's no indication of '$' being addressed as per your comments.)
It seems the code is traversing the string 4 times, and the state of the string is in flux, leading to hard-to-understand intermediate states.
Process from beginning to end in one pass, doing the right thing all the way along.
char *camelCase( char word[] ) { // return something usable by the caller
int s = 0, d = 0; // 's'ource index, 'd'estination index
// one sweep along the entire length
while( ( word[d] = word[s] ) != '\0' ) {
if( isalpha( word[d] ) ) { // make ordinary letters lowercase
word[ d ] = tolower( word[ d ] );
d++, s++;
continue;
}
// special handling for non-alpha. may be more than one!
while( word[s] && !isalpha( word[s] ) ) s++;
// end of non-alpha? copy alpha as UPPERCASE
if( word[s] )
word[d++] = toupper( word[s++] );
}
// make first character lowercase
word[ 0 ] = tolower( word[ 0 ] );
return word; // return modified string
}
int main() {
// multiple test cases. Add "user input" after algorithm developed and tested.
char *wordArray[] = {
"_random__word_provided",
" the quick brown fox ",
"stuff happens all the time",
};
for( int i = 0; i < 3; i++ )
puts( camelCase( wordArray[i] ) );
return 0;
}
randomWordProvided
theQuickBrownFox
stuffHappensAllTheTime
There may come comments pointing out that the ctype.h functions receive and return unsigned datatypes. This is a "casting" elaboration that you can/should add to the code if you ever expect to encounter something other than 7-bit ASCII characters.
In my opinion, there's a very simple algorithm that just requires you to remember the last character parsed only:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void camelCase(char* source)
{
/*Convert to camelCase*/
char last = '_',
*dest = source;
/* while we are not at the string end copy the char values */
while ((*dest = *source++) != '\0') {
/* if the char is a lower case letter and the previous was a '_' char. */
if (islower(*dest) && last == '_')
*dest = toupper(*dest);
/* update the last character */
last = *dest;
/* to skip on the underscores */
if (*dest != '_') dest++;
}
} /* camelCase */
int main()
{
char wordArray[100]; /* better use a simple array */
// Read the string from the keyboard
printf("Enter identifiers separated by spaces/newlines: ");
/* for each line of input */
while (fgets(wordArray, sizeof wordArray, stdin)) {
for ( char *word = strtok(wordArray, " \t\n");
word;
word = strtok(NULL, " \t\n"))
{
printf("%s -> ", word);
// Call camelCase
camelCase(word);
// Print the new string
printf("%s\n", word);
}
}
return 0;
}
if you actually want to skip the first character (and don't convert it to uppercase), you can initialize last with a different char (e.g. '\0')

C program to capitalize a word inside quotation marks

I need to build a function that gets an input and capitalizes only the first letter, doesn't print numbers, capitalizes after a . for a new sentence, and capitalizes all words between a double quotation marks ".
This is what I got until now:
#include <stdio.h>
#define MAX 100
int main()
{
char str[MAX] = { 0 };
int i;
//input string
printf("Enter a string: ");
scanf("%[^\n]s", str); //read string with spaces
//capitalize first character of words
for (i = 0; str[i] != '\0'; i++)
{
//check first character is lowercase alphabet
if (i == 0)
{
if ((str[i] >= 'a' && str[i] <= 'z'))
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
if (str[i] == '.')//check dot
{
//if dot is found, check next character
++i;
//check next character is lowercase alphabet
if (str[i] >= 'a' && str[i] <= 'z')
{
str[i] = str[i] - 32; //subtract 32 to make it capital
continue; //continue to the loop
}
}
else
{
//all other uppercase characters should be in lowercase
if (str[i] >= 'A' && str[i] <= 'Z')
str[i] = str[i] + 32; //subtract 32 to make it small/lowercase
}
}
printf("Capitalize string is: %s\n", str);
return 0;
}
I cant find a way to remove all numbers from input and convert all lowercase to uppercase inside a " plus code for not printing numbers if user input them.
if I input
I am young. You are young. All of us are young.
"I think we need some help. Please" HELP. NO, NO NO,
I DO NOT
NEED HELP
WHATSOEVER.
"Today’s date is
15/2/2021"...
I am 18 years old, are you 20 years old? Maybe 30 years?
output:
I am young. You are young. All of us are young.
"I THINK WE NEED SOME HELP. PLEASE" help. No, no no,
i do not
need help
whatsoever.
"TODAY’S DATE IS
//"...
I am years old, are you years old? maybe years?
The C standard library provides a set of functions, in ctype.h, that will help you
Of particular interest, would be:
isdigit() - returns true if digit
isalpha() - returns true if alphabet character
isalnum() - returns true if alpha/numeric character
islower() - returns true if lower case character
isupper() - returns true if upper case character
tolower() - converts character to lower case
toupper() - converts character to upper case
So, for example, you could replace the test/modify with:
if ( islower( str[i] ) )
{
str[i] = toupper( str[i] );
}
Pedantically, islower() and toupper() return an unsigned int but that's a separate matter...
You can remove letters from a string if you keep two indices, one for reading and one for writing. The following loop will remove all digits from a string:
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (!isdigit(c)) str[j++] = c;
}
str[j] = '\0';
(I've used to character classification functions from <ctype.h> mentioned in Andrew' answer.)
This is safe, because j will always be smaller or equal to i. Don't forget to mark the end of the filtered string with the nullterminator, '\0'. You can combine this filtering with your already existing code for replacing characters.
In your code, you capitalize letters only if they are directly behind a full stop. That's usually not the case, there's a space between full stop and the next word. It's better to establish a context:
shift: capitalize the next letter (beginning or after full stop.)
lock: capitalize all letters (inside quotation marks.)
When you read a letter, decide whether to capitalize it or not depending of these two states.
Putting the filtering and the "shift context§ together:
#include <stdio.h>
#include <ctype.h>
int main(void)
{
char str[] = "one. two. THREE. 4, 5, 6. \"seven\", eight!";
int shift = 1; // Capitalize next letter
int lock = 0; // Capitalize all letters
int j = 0; // writing index, j <= i
int i; // reading index
for (i = 0; str[i]; i++) {
int c = (unsigned char) str[i];
if (isdigit(c)) continue;
if (isalpha(c)) {
if (shift || lock) {
str[j++] = toupper(c);
shift = 0;
} else {
str[j++] = tolower(c);
}
} else {
if (c == '"') lock = !lock;
if (c == '.') shift = 1;
str[j++] = c;
}
}
str[j] = '\0';
puts(str);
printf("(length: %d)\n", j);
return 0;
}
In order to remove some characters, you should use 2 index variables: one for reading and one for writing back to the same array.
If you are allowed to use <ctype.h>, it is a much more portable and efficient way to test character types.
Also do not use scanf() with protection against buffer overflow. It is as bad as using gets(). Given the difficulty in specifying the maximum number of bytes to store into str, you should use fgets() instead of scanf().
Here is a modified version:
#include <ctype.h>
#include <stdio.h>
#define MAX 100
int main() {
char str[MAX];
int i, j;
unsigned char last, inquote;
//input string
printf("Enter a string: ");
if (!fgets(str, sizeof str, stdin)) { //read string with spaces
// empty file
return 1;
}
last = '.'; // force conversion of first character
inquote = 0;
//capitalize first character of words
for (i = j = 0; str[i] != '\0'; i++) {
unsigned char c = str[i];
//discard digits
if (isdigit(c)) {
continue;
}
//handle double quotes:
if (c == '"') {
inquote ^= 1;
}
//upper case letters after . and inside double quotes
if (last == '.' || inquote) {
str[j++] = toupper(c);
} else {
str[j++] = tolower(c);
}
if (!isspace(c) && c != '"') {
// ignore spaces and quotes for the dot rule
last = c;
}
}
str[j] = '\0'; // set the null terminator in case characters were removed
printf("Capitalized string is: %s", str);
return 0;
}

remove a character from the string which does not come simultaneously in c

for example, given the string str1 = "120jdvj00ncdnv000ndnv0nvd0nvd0" and the character ch = '0', the output should be 12jdvj00ncdnv000ndnvnvdnvd. That is, the 0 is removed only wherever it occurs singly.
this code is not working
#include<stdio.h>
char remove1(char *,char);
int main()
{
char str[100]="1o00trsg50nf0bx0n0nso0000";
char ch='0';
remove1(str,ch);
printf("%s",str);
return 0;
}
char remove1(char* str,char ch)
{
int j,i;
for(i=0,j=0;i<=strlen(str)-1;i++)
{
if(str[i]!=ch)
{
if(str[i+1]==ch)
continue;
else
str[j++]=str[i];
}
}
str[j]='\0';
}
Your code looks for an occurrence of something other than the character to be removed with "if(str[i]!=ch)", then if the next character is the one to be removed it skips (i.e. does not keep the characters it has just seen), otherwise it copies the current character. So if it sees 'a0' and is looking for '0' it will ignore the 'a'.
What you could do is copy all characters other than the one of interest and set a counter to 0 each time you see one of them (for the number of contiguous character of interest you've seen at this point). When you find the one of interest increment that count. Now whenever you find one that is not of interest, you do nothing if the count is 1 (as this is the single character you want to remove), or put that many instances of the interesting character into str if count > 1.
Ensure you deal with the case of the string ending with a contiguous run of the character to be removed, and you should be fine.
char *remove1(char* str, char ch){
char *d, *s;
for(d = s = str;*s;++s){
if(*s == ch){
if(s[1] == ch)
while(*s == ch)
*d++=*s++;
else
++s;//skip a ch
if(!*s)break;
}
*d++ = *s;
}
*d = '\0';
return str;
}
Code to copy the basic
for(d = s = str;*s;++s){
*d++ = *s;
}
*d = '\0';
Special processing to be added.
for(d = s = str;*s;++s){
if(find a character that is specified){
Copy that in the case of continuously than one character
if one letter then skip
}
*d++ = *s;
}
*d = '\0';
Here is the working code
output is : "1o00trsg5nfbxnnso0000"
#include<stdio.h>
char remove1(char *,char);
int main()
{
char str[100]="1o00trsg50nf0bx0n0nso0000";
char ch='0';
remove1(str,ch);
printf("%s",str);
return 0;
}
char remove1(char* str,char ch)
{
int j,i;
int len = strlen(str);
for(i = 0;i < (len - 1);i++){
if(str[i] == ch){
/* if either of check prev and next character is same then contd. without removal */
if((str[i+1] == ch) || (str[i-1] == ch))
continue;
/* replacing the char and shifting next chars left*/
for(j = i;j < (len - 2);j++) {
str[j] = str[j + 1];
}
/* string length is decrementing due to removal of one char*/
len--;
}
}
str[len] = '\0';
}

Advanced thinking on Caesar Cipher program in C

#include <stdio.h>
void caesar (char cipher[], int shift);
int main ()
{
char cipher[200];
int shift;
printf("Enter text to be encrypted (in small letter): ");
gets(cipher);
printf("Number of shift to right? : ");
scanf("%d", &shift);
caesar (cipher, shift);
return 0;
}
void caesar (char cipher[], int shift)
{
int i = 0;
while (cipher[i] != '\0')
{
if ((cipher[i] + shift) >= 97 && (cipher[i] + shift) <= 122)
{
cipher[i] += (shift);
}
else
{
cipher[i] += (shift - 25);
}
i++;
}
printf("%s", cipher);
}
How can I ignore the operation of spaces? I mean, I want to add spaces in my converted/decrypted string. While I running this program it vanishes the spaces from the encrypted string. How can I do this? Suppose that, "this is a pen" is would become: "uijt jt b qfo" if right shift by 1.
You should check whether a character is a letter before shifting. Your code shifts everything and checks only whether a character is a valid letter afterwards to detect wrapping. (It also doesn't make the puctuation and spaces vanish, it converts them to non-printable characters with ASCII values below 32.)
You could also enforce correct wrapping by using the modulo operator:
void caesar(char cipher[], int shift)
{
char *p = cipher;
while (*p)
{
if ('a' <= *p && *p <= 'z') {
*p = 'a' + (*p - 'a' + shift) % 26;
}
p++;
}
}
If you want to auto-detect the shift, just use brute force for all 26 possible shifts and check for common expected substrings:
int autocaesar(char cipher[])
{
int shift = 0;
while (shift < 26) {
if (strstr(cipher, "the")) return shift;
if (strstr(cipher, "this")) return shift;
if (strstr(cipher, "that")) return shift;
caesar(cipher, 1);
shift++;
}
return -1;
}
The function strstr is in <string.h> and finds a substring in an string. This is done very crudely here: It is not enforced that "the" is a word of its own. Also, the check is case sensitive.
Note that the cipher is shifted by one character at a time, because the original string will be shifted continuously. If nothing os found, it will have wrapped over to contain the original string.

Pointer and Array in C

I'm new to C and programming. I got stuck at a homework exercise. My output only shows the first character in upper case, and the following characters in some weird numbers. Can someone take a look at my code and give me some tips on what I've done wrong and ways to fix the issue? Your help is greatly appreciated!
"Write a function void sticky(char* word) where word is a single word such as “sticky” or “RANDOM”. sticky() should modify the word to appear with “sticky caps” (http://en.wikipedia.org/wiki/StudlyCaps), that is, the letters must be in alternating cases(upper and lower), starting with upper case for the first letter. For example, “sticky” becomes “StIcKy” and “RANDOM” becomes “RaNdOm”. Watch out for the end of the string, which is denoted by ‘\0’. You can assume that legal strings are given to the sticky() function."
#include <stdio.h>
#include <stdlib.h>
/*converts ch to upper case, assuming it is in lower case currently*/
char toUpperCase(char ch)
{
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch)
{
return ch-'A'+'a';
}
void sticky(char* word){
/*Convert to sticky caps*/
for (int i = 0; i < sizeof(word); i++)
{
if (i % 2 == 0)
{
word[i] = toUpperCase(word[i]);
}
else
{
word[i] = toLowerCase(word[i]);
}
}
}
int main(){
/*Read word from the keyboard using scanf*/
char word[256];
char *input;
input = word;
printf("Please enter a word:\n");
scanf("%s", input);
/*Call sticky*/
sticky(input);
/*Print the new word*/
printf("%s", input);
for (int i = 0; i < sizeof(input); i++)
{
if (input[i] == '\n')
{
input[i] = '\0';
break;
}
}
return 0;
}
you need to use strlen not sizeof to find the length of a char* string
Modify your change upper and change lower function
/*converts ch to upper case,*/
char toUpperCase(char ch)
{
if(ch>='a' && ch<='z')/*If condition just to make sure current letter is in lower case*/
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch)
{
if(ch>='A' && ch<='Z')/*If condition just to make sure current letter is in Upper case*/
return ch-'A'+'a';
}
Also, only four characters are converted since you are using sizeof for finding the string length.sizeof always returns 4(depends upon machine).
use strlen(word) to find the length of string word in following for loop:
for (int i = 0; i < strlen(word); i++)
{
}
You should use strlen instead of sizeof.
Also, you must check whether your letter is already upper or lower case:
for (int i = 0; i < strlen(word); i++)
{
if (i % 2 == 0)
{
if ( isLowerCase(word[i]) )
{
word[i] = toUpperCase(word[i]);
}
else
{
// do nothing.
}
}
else
{
if ( isUpperCase(word[i]) )
{
word[i] = toLowerCase(word[i]);
}
else
{
// do nothing.
}
}
}
Note that I haven't implemented the isUpperCase and isLowerCase functions ;D
Function sizeof() is used to calculate the size of the datatype, not the size allocated to the pointer.
So you can not use it like sizeof(word). Instead, iterate over a characters until you stumble upon a \0, which indicates end of string.
On example:
int i = 0;
while ( word[i] != 0 ) {
// do lower/upper case conversion.
}
sizeof (word) is the size of a char *, you must pass another parameter with the array size... or use strlen ().
Something is wrong in your code : you are making odd characters upper case and even ones lower but you do no check whether they were lower or upper case in the first place. But lowering an already lower-case letter gives you a wrong value (the same is true for "uppering" an already upper-case letter).
So you should do :
char toUpperCase(char ch)
{
if ((ch >= 'a') && (ch <= 'z')) {
return ch-'a'+'A';
} else {
return ch;
}
}
and the same for toLowerCase.
Thank you so much for the tips! Using your suggestions, I modified my code and it's working now.
Below is my revised code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*converts ch to upper case, assuming it is in lower case currently*/
char toUpperCase(char ch){
return ch-'a'+'A';
}
/*converts ch to lower case, assuming it is in upper case currently*/
char toLowerCase(char ch){
return ch-'A'+'a';
}
void sticky(char* word)
{
/*Convert to sticky caps*/
for (int i = 0; i < strlen(word); i++)
{
if (i % 2 == 0)
{
if (word[i] >= 'a' && word[i] <= 'z')
{
word[i] = toUpperCase(word[i]);
}
}
else
{
if (word[i] >= 'A' && word[i] <= 'Z')
{
word[i] = toLowerCase(word[i]);
}
}
}
}
int main(){
/*Read word from the keyboard using scanf*/
char word[256];
char *input;
input = word;
printf("Please enter a word:\n");
scanf("%s", input);
/*Call sticky*/
sticky(input);
/*Print the new word*/
printf("%s", input);
for (int i = 0; i < sizeof(input); i++)
{
if (input[i] == '\n')
{
input[i] = '\0';
break;
}
}
return 0;
}

Resources