Password checker in c language - c

I want to take input as a string and evaluate if it is a valid password. The password is valid if it has numbers, capital and small alphabets, and a length of at least 7 characters. Also, when all these requirements are satisfied, the output should be "Strong", else "Weak". Code:
#include<stdio.h>
#include<string.h>
#define N 20
int main()
{
char pass[N];
int i, x=0, p;
printf("Enter a password: ");
scanf("%s", &pass);
if(strlen(pass)>=7)
{
p=strlen(pass);
for (i = 0; i < p; i++)
{
if ((pass[i] >= 'a' && pass[i] <= 'z') || (pass[i] >= 'A' && pass[i <= 'Z') || (pass[i] >= '0' && pass[i] <= '9'))
printf("Sucess! ");
}
}
else
printf("Try Again..");
return 0;
}
Somethings are not working like: 1. After execution, it prints "Sucess!!" multiple times.. 2. In the inner if block, when i replace || with &&, it didn't print anything.
Please help.

You could change this section of code:
p=strlen(pass);
for (i = 0; i < p; i++)
{
if ((pass[i] >= 'a' && pass[i] <= 'z') || (pass[i] >= 'A' && pass[i <= 'Z') || (pass[i] >= '0' && pass[i] <= '9'))
printf("Sucess! ");
}
... to something like this:
int lower_case_count = 0;
int upper_case_count = 0;
int digit_count = 0;
p=strlen(pass);
for (i = 0; i < p; i++) {
if (pass[i] >= 'a' && pass[i] <= 'z') ++lower_case_count;
if (pass[i] >= 'A' && pass[i] <= 'Z') ++upper_case_count;
if (pass[i] >= '0' && pass[i] <= '9') ++digit_count;
}
if (lower_case_count > 0 && upper_case_count > 0 && digit_count > 0) {
printf("Strong\n");
}
In the loop you just want to count how many of each type of characters is present.
Once the loop is done, you can check whether all requirements are satisfied and take appropriate action.

You made me thinking and I came up with this rather simple solution - two series of ifs, one wrapped within a while loop. It checks for lower and uppercase, numbers and special characters, reporting the exact error a user had eventually made.
//A program for password validation
#include <stdio.h>
#include <ctype.h>//for islower(), isupper(), isdigit() and ispunct()
#include <string.h>//for strlen()
int main(void)
{
char pass[30];
printf("Enter your password: ");
scanf("%[^\n]s", pass);//so that password may contain space char
int i = 0,
lower_count = 0,
upper_count = 0,
digit_count = 0,
punct_count = 0;
int length = strlen(pass);
//loop goes through the password as array
while (pass[i]) {
if(islower(pass[i]))//if there is lowercase
lower_count++;
if(isupper(pass[i]))//if there is uppercase
upper_count++;
if (isdigit(pass[i]))//if there is a number
digit_count++;
if (ispunct(pass[i]))//if there is a special chars
punct_count++;
i++;
}
if(strlen(pass) < 8)
{
printf("The password must have at least 8 chars\n");
return 1;
}
if(lower_count == 0)
{
printf("You need lowercases\n");
}
if(upper_count == 0)
{
printf("You need an uppercase\n");
}
if(digit_count == 0)
{
printf("You need digits\n");
}
if(punct_count == 0)
{
printf("You need a special character\n");
}
if(upper_count != 0 && digit_count != 0 && punct_count != 0 &&
length > 12)
{
printf("Your password is strong!\n");
}
if(upper_count != 0 && digit_count != 0 && punct_count != 0 &&
length <= 12)
{
printf("Your password is OK\n");
}
return 0;
}

Related

CS50-pset2: Readability. Incorrect outcome

When I run my code, the outcome has failed to show the exact result based on the texts given in the problem set. Although, it showed the grade, the result is incorrect. The text is : "Would you like them here or there? I would not like them here or there. I would not like them anywhere."(Grade 2)
enter image description here
Supposedly, the result for the text is "Grade 2". However, it shows all grades instead.
enter code here
int main(void)
{
string s = get_string("Text: ");
printf("%s\n",s);
int count_letters = 0; //To count letters (uppercase & lowercase)
int count_words = 1; //To count words
int count_sentences = 0; //To count sentences
for (int i = 0; i < strlen(s); i++)
if (isalpha(s[i]))
{
if ((s[i] >= 'a' && s[i] <= 'z' )||( s[i] >= 'A' && s[i] <= 'Z'))
{
count_letters++;
}
if (s[i] == ' ')
{
count_words++;
}
if (s[i] == '.' || s[i] =='!' || s[i] == '?')
{
count_sentences++;
}
//printf("%i count_letter(s)\n", count_letters);
//printf("%i count_words(s)\n", count_words);
//printf("%i sentence(s)\n", count_sentences);
//Coleman-Liau index
float L = (count_letters / (float) count_words) * 100;
float S = (count_sentences / (float) count_words) * 100;
int grade = round (0.0588 * L - 0.296 * S -15.8);
if (grade < 1)
{
printf("Before Grade 1\n");
}
else if (grade >= 16)
{
printf("Grade 16+\n");
}
else
{
printf("Grade %.d\n", grade);
}
}
}
Is there any problem with my code? How can I fix my code in order to receive the exact outcome. I've been doing this problem set for almost 2 days :'/. Thanks in advance
Calculate the number of letters, sentences, and words inside of the loop and calculate Coleman-Liau's index outside of the loop.
Don't calculate something in a loop and try to get specific output from within it as well, it never ends well. So in conclusion, calculate your values in the loop and do everything else outside of it.
int count_letters = 0; //To count letters (uppercase & lowercase)
int count_words = 1; //To count words
int count_sentences = 0; //To count sentences
for (int i = 0; i < strlen(s); i++){
// get the amounts in the loop
if (isalpha(s[i]))
{
if ((s[i] >= 'a' && s[i] <= 'z') || (s[i] >= 'A' && s[i] <= 'Z'))
{
count_letters++;
}
if (s[i] == ' ')
{
count_words++;
}
if (s[i] == '.' || s[i] == '!' || s[i] == '?')
{
count_sentences++;
}
}
}
//Calculate Coleman-Liau outside of it and get the correct grade from your if statements
Since you have three distinct categories to count, I would create a function for each of these.
For example, based on your code, you could create a function to count characters (you don't need isdigit function here, non-digit characters are already filtered out by the algorithm itself):
int get_letters_count(char *text_str)
{
int count_letters = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if ( (text_str[i] >= 'a' && text_str[i] <= 'z')
|| (text_str[i] >= 'A' && text_str[i] <= 'Z')
|| (text_str[i] >= '0' && text_str[i] <= '9')) {
count_letters++;
}
}
return count_letters;
}
This approach of breaking down your program will make it much easier to develop.
Here is a very crude implementation based on the Coleman–Liau index Wikipedia page:
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
int get_letters_count(char *text_str)
{
int count_letters = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if ( (text_str[i] >= 'a' && text_str[i] <= 'z')
|| (text_str[i] >= 'A' && text_str[i] <= 'Z')
|| (text_str[i] >= '0' && text_str[i] <= '9')) {
count_letters++;
}
}
return count_letters;
}
int get_words_count(char *text_str)
{
int count_words = 0;
int text_len = strlen(text_str);
for (int i = 0; i < text_len; i++) {
if (text_str[i] == ' ') {
count_words++;
}
}
if (count_words)
count_words++;
return count_words;
}
bool word_is_acronym(char *word)
{
bool ret = true;
for (; *word && *word != ' '; word++) {
if ( *word != '.'
&& *word < 'A' || *word > 'Z') {
ret = false;
}
}
return ret;
}
int get_sentences_count(char *text_str)
{
int count_sentences = 0;
int text_len = strlen(text_str);
char *last_word = &text_str[0];
for (int i = 0; i < text_len; i++) {
if ( text_str[i] == ' '
&& i < (text_len - 1)) {
last_word = &text_str[i + 1];
}
bool end_mark = text_str[i] == '.'
|| text_str[i] == '!'
|| text_str[i] == '?';
if ( end_mark
&& word_is_acronym(last_word) == false) {
count_sentences++;
}
}
return count_sentences;
}
int main(void)
{
char text_str[] = "Existing computer programs that measure readability are based "
"largely upon subroutines which estimate number of syllables, "
"usually by counting vowels. The shortcoming in estimating syllables "
"is that it necessitates keypunching the prose into the computer. "
"There is no need to estimate syllables since word length in letters "
"is a better predictor of readability than word length in syllables. "
"Therefore, a new readability formula was computed that has for its "
"predictors letters per 100 words and sentences per 100 words. "
"Both predictors can be counted by an optical scanning device, and "
"thus the formula makes it economically feasible for an organization "
"such as the U.S. Office of Education to calibrate the readability of "
"all textbooks for the public school system.";
int count_letters = get_letters_count(text_str);
int count_words = get_words_count(text_str);
int count_sentences = get_sentences_count(text_str);;
if ( count_letters > 0
&& count_words > 0
&& count_sentences > 0) {
float L = ((count_letters * 100) / count_words);
float S = ((count_sentences * 100) / count_words);
float grade = 0.0588 * L - 0.296 * S - 15.8;
printf("grade = %.01f\n", grade);
} else {
printf("bad input\n");
}
}
Ouput:
$ gcc main.c && ./a.out
grade = 14.5
Parsing text can be very trick, though.
Once you get a first version working with a known input such as this, try to expand your data set and keep improving your program.
This program is also far from being computationally efficient. If that becomes a bottleneck, you could optimize the functions or maybe reduce the number of loops grouping the functions in a single loop.
Certainly most times it's better to start with a crude working solution and improve from there instead of attempting a more sophisticated/complete solution right from the beginning.

there is a test that stuck at infinity loop can you find it?

int main() {
int s, b;
int hist[26] = { 0 };
int hist2[26] = { 0 };
char char1, char2;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
scanf("%c", &char2);
while (char2 != '$') {
if (char2 >= 'A' && char2 <= 'Z')
char2 = char2 + 32;
int char3 = char2 - 'a';
hist2[char3]++;
scanf("%c", &char2);
if (char2 < 0)
break;
}
printf("How many times would you like to loop?\n");
if (!scanf("%d", &s))
return 0;
printf("Enter the string you would like to be checked ending with $:\n");
scanf("%c", &char1);
if (char1 >= 'A' && char1 <= 'Z')
char1 = char1 + 32;
while (char1 != '$' && char1 > 0) {
int char3 = char1 - 'a';
hist[char3]++;
scanf("%c", &char1);
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
b = 0;
break;
} else {
b = 1;
}
}
if (b)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}
//so basically this a homewrok in my university they asked us to do the program input is char and a loop and it compare it with one more input how many times you can loop each letter (no need to check that the input is true but the loop number int
Your program has many problems:
scanf() returns the number of successful conversions. Compare the return value to 1 in your program instead of testing 0, which would never happen for "%c" anyway. Furthermore, the char2 would not be modified if the stream is at end of file.
You must check of char2 is a letter before indexing into the array, otherwise you may access beyond the array boundaries and have undefined behavior.
presentation is important: use proper indentation and spacing for the program to be readable.
include the necessary headers such as <stdio.h>
Here is an improved version:
#include <stdio.h>
int main() {
int hist[26] = { 0 };
int hist2[26] = { 0 };
int s;
char c;
printf("Hello Netta, enter the letters you would like us to repeat ending with $:\n");
while ((scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist2[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist2[c - 'a']++;
}
printf("How many times would you like to loop?\n");
if (scanf("%d", &s) != 1)
return 1;
printf("Enter the string you would like to be checked ending with $:\n");
while (scanf("%c", &c) == 1 && c != '$') {
if (c >= 'A' && c <= 'Z')
hist[c - 'A']++;
else if (c >= 'a' && c <= 'z')
hist[c - 'a']++;
}
for (int i = 0; i < 26; i++) {
if (hist[i] > s * hist2[i]) {
printf("Not enough letters\n");
break;
}
}
if (i == 26)
printf("Congratulations! you have enough letters to create your song and win the Eurovision!\n");
return 0;
}

Dividing the alphabet into parties for elections - C language

I want to write a program that takes an input from the user of "leading camps", and divides 26 letters in alphabet into 3 parties. for example if I choose the leading camps to be A-E-H, the three parties will be: 1) A,B,C,D 2) E,F,G 3) H-Z, and they the next input will be the votes (which are announced online), for example, if I enter the series of votes "fDFFGCcdC", the leading party will be the one that includes letters A-D, because it got 5 votes, and the others took 4 and zero, and so on.
Here is what I wrote so far:
Notes: Lead* are the leading camps.
#include <stdio.h>
int main()
{
char Lead_1,Lead_2,Lead_3, vote;
int counter_1=0,counter_2=0,counter_3=0;
printf("Please enter the camps leaders:");
scanf("%c%c%c", &Lead_1,&Lead_2,&Lead_3);
printf("please enter the votes:");
scanf(" %c", &vote);
while(vote != '!')
{
scanf("%c", &vote);
if((vote >= Lead_1) && (vote < Lead_2) || (vote >= (Lead_1 + 32) && vote < (Lead_2 +32)))
counter_1++;
if((vote >= Lead_2) && (vote < Lead_3) || (vote >= (Lead_2 + 32) && vote < (Lead_3 +32)))
counter_2++;
if((vote >= Lead_3) || (vote >= (Lead_3 + 32)))
counter_3++;
if (counter_1 > counter_2 && counter_1 > counter_3)
printf("%c", Lead_1);
else if (counter_2 > counter_1 && counter_2 > counter_3)
printf("%c", Lead_2);
else if (counter_3 > counter_1 && counter_3 > counter_2)
printf("%c", Lead_3);
else
{
if((vote >= Lead_1) && (vote < Lead_2) || (vote >= (Lead_1 + 32) && vote < (Lead_2 + 32)))
printf("%c", vote);
if((vote >= Lead_2) && (vote < Lead_3) || (vote >= (Lead_2 + 32) && vote < (Lead_3 + 32)))
printf("%c", vote);
if((vote >= Lead_3) || (vote >= (Lead_3 + 32)))
printf("%c", vote);
}
}
return 0;
}
I'm having a problem with the output. for example if I enter the leading camps AEH, and enter the votes bAzz! the output is AzHH instead of AAAH.
I'm assuming that based on the votes "fDFFGCcdC", we have to come up with parties A-E-H. Besides, A is the leading party , E is the second leading party & H is the third party {based on number of votes they got}.
If my understanding is right, you can follow this:
Create a hash table for 26 letters and initialize it.
hash[26] = {0}
get the count of characters in votes.
hash[vote[i] - 'a'] ++
Now you got the array of count of votes. {which has max, second max, min}
Based on maximum, second maximum and minimum values, set the ranges and parties.
#include <stdio.h>
#include <ctype.h>
int main(void){
char party[4][2];
int votes[3] = {0};
int i;
char ch;
*party[3] = 'Z' + 1;//sentinel
//input format [alphabet for party1]-[alphabet for party2]-[[alphabet for party3]
puts("input devide party :");
if(3==scanf("%1[A-Z]-%1[A-Z]-%1[A-Z]", party[0], party[1], party[2])
&& *party[0] < *party[1] && *party[1] < *party[2] && *party[2] < *party[3]){
for(i = 0; i < 3; i++){
printf("party%d : ", i + 1);
for(ch = *party[i]; ch < *party[i+1]; ++ch){
if(ch != *party[i])
putchar(',');
putchar(ch);
}
puts("");
}
puts("input votes :");
ch = '_';
while(scanf(" %c", &ch) && ch != '!'){
if(isalpha(ch)){
ch = toupper(ch);
if(ch < *party[1])
++votes[0];
else if(ch < *party[2])
++votes[1];
else if(ch < *party[3])
++votes[2];
}
}
for(i = 0; i < 3; ++i){
printf("vote of party%d : %d\n", i+1, votes[i]);
}
} else {
puts("invalid input!");
}
return 0;
}

How to check if a string is a number?

I want to check if a string is a number with this code. I must check that all the chars in the string are integer, but the while returns always isDigit = 1. I don't know why that if doesn't work.
char tmp[16];
scanf("%s", tmp);
int isDigit = 0;
int j=0;
while(j<strlen(tmp) && isDigit == 0){
if(tmp[j] > 57 && tmp[j] < 48)
isDigit = 0;
else
isDigit = 1;
j++;
}
Forget about ASCII code checks, use isdigit or isnumber (see man isnumber). The first function checks whether the character is 0–9, the second one also accepts various other number characters depending on the current locale.
There may even be better functions to do the check – the important lesson is that this is a bit more complex than it looks, because the precise definition of a “number string” depends on the particular locale and the string encoding.
if(tmp[j] >= '0' && tmp[j] <= '9') // should do the trick
More obvious and simple, thread safe example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv)
{
if (argc < 2){
printf ("Dont' forget to pass arguments!\n");
return(-1);
}
printf ("You have executed the program : %s\n", argv[0]);
for(int i = 1; i < argc; i++){
if(strcmp(argv[i],"--some_definite_parameter") == 0){
printf("You have passed some definite parameter as an argument. And it is \"%s\".\n",argv[i]);
}
else if(strspn(argv[i], "0123456789") == strlen(argv[i])) {
size_t big_digit = 0;
sscanf(argv[i], "%zu%*c",&big_digit);
printf("Your %d'nd argument contains only digits, and it is a number \"%zu\".\n",i,big_digit);
}
else if(strspn(argv[i], "0123456789abcdefghijklmnopqrstuvwxyz./") == strlen(argv[i]))
{
printf("%s - this string might contain digits, small letters and path symbols. It could be used for passing a file name or a path, for example.\n",argv[i]);
}
else if(strspn(argv[i], "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(argv[i]))
{
printf("The string \"%s\" contains only capital letters.\n",argv[i]);
}
}
}
if ( strlen(str) == strlen( itoa(atoi(str)) ) ) {
//its an integer
}
As atoi converts string to number skipping letters other than digits, if there was no other than digits its string length has to be the same as the original.
This solution is better than innumber() if the check is for integer.
#include <stdio.h>
#include <string.h>
char isNumber(char *text)
{
int j;
j = strlen(text);
while(j--)
{
if(text[j] > 47 && text[j] < 58)
continue;
return 0;
}
return 1;
}
int main(){
char tmp[16];
scanf("%s", tmp);
if(isNumber(tmp))
return printf("is a number\n");
return printf("is not a number\n");
}
You can also check its stringfied value, which could also work with non Ascii
char isNumber(char *text)
{
int j;
j = strlen(text);
while(j--)
{
if(text[j] >= '0' && text[j] <= '9')
continue;
return 0;
}
return 1;
}
In this part of your code:
if(tmp[j] > 57 && tmp[j] < 48)
isDigit = 0;
else
isDigit = 1;
Your if condition will always be false, resulting in isDigit always being set to 1. You are probably wanting:
if(tmp[j] > '9' || tmp[j] < '0')
isDigit = 0;
else
isDigit = 1;
But. this can be simplified to:
isDigit = isdigit(tmp[j]);
However, the logic of your loop seems kind of misguided:
int isDigit = 0;
int j=0;
while(j<strlen(tmp) && isDigit == 0){
isDigit = isdigit(tmp[j]);
j++;
}
As tmp is not a constant, it is uncertain whether the compiler will optimize the length calculation out of each iteration.
As #andlrc suggests in a comment, you can instead just check for digits, since the terminating NUL will fail the check anyway.
while (isdigit(tmp[j])) ++j;
I need to do the same thing for a project I am currently working on. Here is how I solved things:
/* Prompt user for input */
printf("Enter a number: ");
/* Read user input */
char input[255]; //Of course, you can choose a different input size
fgets(input, sizeof(input), stdin);
/* Strip trailing newline */
size_t ln = strlen(input) - 1;
if( input[ln] == '\n' ) input[ln] = '\0';
/* Ensure that input is a number */
for( size_t i = 0; i < ln; i++){
if( !isdigit(input[i]) ){
fprintf(stderr, "%c is not a number. Try again.\n", input[i]);
getInput(); //Assuming this is the name of the function you are using
return;
}
}
None of these deal appropriately with negative numbers or floating point numbers.
How about:
bool
is_realnumber(char *instring) {
if (*instring != '-' && *instring != '.' && !isdigit(*instring)) return false;
if (strspn(instring+1, "0123456789.") < strlen(instring+1)) return false;
int c = 0;
while (*instring) if (*instring++ == '.') if (++c > 1) return false;
return true;
}
I can extend Marcelo's answer supporting floating numbers also as following:
char isnumber(const char *str)
{
int decpos = -1, pmpos = -1, engpos = strlen(str) - 1, epmpos = strlen(str) - 1;
for (int i = 0; i < strlen(str); i++)
/* check if it is integer */
if (str[i] > 47 && str[i] < 58)
continue;
/* check if it is decimal seperator and used once*/
else if (str[i] == 46 && decpos == -1)
{
decpos = i;
continue;
}
/* check if it is +/-, at the begining*/
else if ((str[i] == 43 || str[i] == 45) && i == 0)
{
pmpos = 1;
continue;
}
/* check if it is engineering format e/E, used once, after decimal and before +/-*/
else if ((str[i] == 69 || str[i] == 101) && engpos == strlen(str) - 1 && i > 0 && i > decpos && i < epmpos)
{
engpos = 1;
continue;
}
/* check if it is engineering format +/-, used once, after decimal and after engineering e/E*/
else if ((str[i] == 43 || str[i] == 45) && epmpos == strlen(str) - 1 && i > 0 && i > decpos && i > engpos)
{
epmpos = 1;
continue;
}
else
return 0;
return 1;
}
You can implement the function as following:
bool isNumeric(const char* s){
while(*s){
if(*s < '0' || *s > '9')
return false;
++s;
}
return true;
}
If you intend to use that number in integer/long form in the future, you will be calling atoi or atol anyway, in which case you might want to just check the return value.
char tmp[16];
scanf("%s", tmp); // unsafe!!!
long tmp_long = atol(&tmp);
if (tmp_long == 0){
printf("%s: is not a number.\n", &tmp);
}
tutorialspoint on atol
Your condition says if X is greater than 57 AND smaller than 48. X cannot be both greater than 57 and smaller than 48 at the same time.
if(tmp[j] > 57 && tmp[j] < 48)
It should be if X is greater than 57 OR smaller than 48:
if(tmp[j] > 57 || tmp[j] < 48)
rewrite the whole function as below:
bool IsValidNumber(char * string)
{
for(int i = 0; i < strlen( string ); i ++)
{
//ASCII value of 0 = 48, 9 = 57. So if value is outside of numeric range then fail
//Checking for negative sign "-" could be added: ASCII value 45.
if (string[i] < 48 || string[i] > 57)
return FALSE;
}
return TRUE;
}
The problem is that the result of your code "isDigit" is reflecting only the last digit test. As far as I understand your qustion, you want to return isDigit = 0 whenever you have any character that is not a number in your string. Following your logic, you should code it like this:
char tmp[16];
scanf("%s", tmp);
int isDigit = 0;
int j=0;
isDigit = 1; /* Initialised it here */
while(j<strlen(tmp) && isDigit == 0){
if(tmp[j] > 57 || tmp[j] < 48) /* changed it to OR || */
isDigit = 0;
j++;
}
To get a more understandable code, I'd also change the test:
if(tmp[j] > 57 || tmp[j] < 48)
to the following:
if(tmp[j] > '9' || tmp[j] < '0')
Can check every char by isdigit().
#include <string.h>
#include <ctype.h>
int is_digit_str(char* str){
int digit_count = 0;
for (int i = 0; i < strlen(str); i++) {
if(isdigit(str[i]))
digit_count++;
else
break;
}
return digit_count == strlen(str);
}
int being_number(char string[]){
int l=strlen(string);
for (int i = 0; i < l; i++)
{
if(string[i] >= '0' && string[i] <= '9'){
i=i;
}
else{
return(0);
}
}
return(1);
}

How to ignore special characters when incrementing and how to use % to loop through ASCII?

#include <stdio.h>
int main()
{
char msg[31] = {'\0'};
char encrypted[31] = {'\0'};
int key;
printf("Please enter a message under 30 characters: ");
fgets(msg, 31, stdin);
printf("Please enter an encryption key: ");
scanf("%d", &key);
int i = 0;
if (msg[i] && (('a' >= msg[i] && msg[i]>= 'z') || ('A' >= msg[i] && msg[i] >= 'Z')))
{
i++;
} else {
while (msg[i] && (('a' <= msg[i] && msg[i]<= 'z') || ('A' <= msg[i] && msg[i] <= 'Z')))
{
encrypted[i] = (msg[i] + key);
i++;
}
}
printf("%s\n", msg);
printf("%d\n", key);
printf("%s\n", encrypted);
}
I've got my code to work but i don't know how to make the incrementing ignore special characters and spaces. Also how do i use % to loop back to 'a' and 'A' to keep all the capitalization in the message the same?
You can't do range tests like this:
'a' <= msg[i] <= 'z'
This evaluates as 'a' <= msg[i] becomes true or false (1 or 0), which is always less than 'z'.
So to start you need:
( msg[i] >= 'a' && msg[i] <= 'z' || msg[i] >= 'A' && msg[i] <= 'Z' )
Now, you have put this condition on your loop, so it will terminate as soon as you encounter a special character. If you want to have different behaviour for letters, check them inside the loop:
for( i = 0; msg[i] != 0; i++ ) {
if( msg[i] >= 'a' && msg[i] <= 'z' || msg[i] >= 'A' && msg[i] <= 'Z' ) {
encrypted[i] = msg[i] + key;
} else {
encrypted[i] = msg[i];
}
}
Now the second part of your question. You appear to want to rotate your letters. Try this:
// Sanity -- to avoid overflowing `char`
key %= 26;
while( key < 0 ) key += 26;
for( i = 0; msg[i] != 0; i++ ) {
if( msg[i] >= 'a' && msg[i] <= 'z' ) {
encrypted[i] = 'a' + ((msg[i]-'a' + key) % 26);
} else if( msg[i] >= 'A' && msg[i] <= 'Z' ) {
encrypted[i] = 'A' + ((msg[i]-'A' + key) % 26);
} else {
encrypted[i] = msg[i];
}
}
If you don't want non-letters in the encrypted string at all, then make another index:
int e = 0;
encrypted[e++] = etc; // Only when you want to add something to the string.
And don't forget after the loop:
encrypted[e] = 0; // terminate string.

Resources