Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 days ago.
Improve this question
I'm taking the course CS50 and in my early stage of learning how to code I want to have a habit of writing clean code. Can you check out my code below and give some advice on what am I doing wrong or what am I not seeing.
#include <cs50.h>
#include <stdio.h>
#include <ctype.h>
#include <string.h>
bool valid(string password);
int main(void)
{
string password = get_string("Enter your password: ");
if (valid(password))
{
printf("Your password is valid!\n");
}
else
{
printf("Your password needs at least one uppercase letter, lowercase letter, number and symbol\n");
}
}
// TODO: Complete the Boolean function below
bool valid(string password)
{
bool alphanumeric = false;
bool uppercase = false;
bool lowercase = false;
bool symbol = false;
for (int i = 0, n = strlen(password); i < n; i++)
{
// Checks for an uppercase letter
if (password[i] >= 'A' && password[i] <= 'Z')
{
uppercase = true;
}
// Checks for a lowercase letter
if (password[i] >= 'a' && password[i] <= 'z')
{
lowercase = true;
}
// Checks for numbers
if (password[i] >= 48 && password[i] <= 57)
{
alphanumeric = true;
}
// Checks for symbols
if ((password[i] >= 33 && password[i] <= 47)
|| (password[i] >= 58 && password[i] <= 64)
|| (password[i] >= 91
&& password[i] <= 96) || (password[i] >= 123 && password[i] <= 126))
{
symbol = true;
}
}
if (alphanumeric == true && uppercase == true && lowercase == true && symbol == true)
{
return true;
}
else
{
return false;
}
}
Can you check out this code I've written and fix/recommend on how I can modify my thought process in writing clean code?
Related
i should realize two very similar functions but i am having problems.
I have to read the string "username", this string can only contain letters (upper and lower case) and spaces.
I have to read the string "key", this string can only contain letters (upper and lower case) and numbers.
If the guidelines are not followed, the user must be able to retrieve the input.
Unfortunately, I cannot use special libraries (only stdio and stdlib).
I realized this:
void checkString(char *i){
int cont;
do {
scanf("%s", i);
if (checkStrLen(6, 6, i) != 0) { //function that controls the size of the string (min,max,string)
for(cont=0; cont<6;){
if((i[cont]>='0' && i[cont]<='9')||
(i[cont]>='A' && i[cont]<='Z')||
(i[cont]>='a' && i[cont]<='z')){
cont++;
}else{
printf("Not valid character");
printf("Try again");
}
}
}else{
printf("\nToo large string");
printf("\nTry again");
}
}while(1);
}
I was thinking of doing something similar.
For the first problem I would replace (i[cont]>='0' && i[cont]<='9') with (i[cont]==' ').
the problem is that I don't understand how to get out of the for if I find a forbidden character during the loop.
I was thinking of using a break, but that would get me out of the whole function.
any advice?
PS how does the function look like? can it be okay or is it completely wrong?
I think the do while loop is not necessary here. do the scanf and get user input first then call checkString. Inside checkString keep your if else statement.
char checkString(char *i){
int cont;
if (checkStrLen(6, 6, i) != 0) { //function that controls the size of the string (min,max,string)
for(cont=0; cont<6;){
if((i[cont]>='0' && i[cont]<='9')||
(i[cont]>='A' && i[cont]<='Z')||
(i[cont]>='a' && i[cont]<='z')){
cont++;
}else{
printf("Not valid character");
printf("Try again");
return i;
}
}
}
else{
printf("\nToo large string");
printf("\nTry again");
}
}
#include <stdio.h>
#define MAXSIZE 100
#define SIZELIM 6
#define true 1
#define false 0
// Returns length of string
// If possible, use strlen() from <string.h> instead
int strlen(char *str) {
char i;
for (i = 0; str[i] != 0 && str[i] != '\n'; i++);
return i;
}
// Returns 1 if strings are equal
// If possible, use strcmp() from <string.h> instead
int streq(const char *x, const char *y) {
char chrx = 1, chry = 1, i;
for (i = 0;
chrx != 0 && chry != 0 && chrx == chry;
chrx = x[i], chry = y[i], i++);
return chrx == chry;
}
// Returns 1 if chr is number or letter
// If possible, use isalnum() from <ctype.h> instead
int isalnum(const char chr) {
return (chr >= '0' && chr <= '9' ||
chr >= 'A' && chr <= 'Z' ||
chr >= 'a' && chr <= 'z');
}
// Checks if string contains numbers and letters only
int isvalid(const char *str) {
int valid = true;
for (int i = 0; str[i] != 0 && str[i] != '\n'; i++) {
if (!isalnum(str[i])) {
valid = false;
break;
}
}
return valid;
}
// Main
int main(void) {
char str[MAXSIZE];
for (;;) {
printf("> ");
fgets(str, MAXSIZE, stdin);
if (streq(str, "quit\n"))
break;
if (strlen(str) > SIZELIM || !isvalid(str)) {
if (strlen(str) > SIZELIM)
puts("String too large");
else if (!isvalid(str))
puts("Not a valid string");
puts("Try again"); }
}
return 0;
}
You can code those functions that you cannot import:
int letters_and_spaces(char c)
{
return c == ' ' || C >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
int letters_and_numbers(char c)
{
return c >= '0' && c <= '9' || C >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
And to use scanf to read spaces you can't use %s. You could change to:
scanf("%100[^\n]*c", i);
BE CAREFUL: I've put 100, supposing i has enough space for that. It will read up to 100 characters (or as many as the number you put there) or until find the \n.
Hi i'm trying to build a function in C language that checks if the string contains numbers , upper cases and lower cases and space, if the string contains any other character then those the function return -1.
float avg_word_len(char* str)
{
float check;
for (int i = 0; i < strlen(str); i++)
{
if (((str[i] >= '0') && (str[i] <= '9')&&(str[i] >= 'a') && (str[i] <= 'z') && (str[i] == ' ')&& (str[i] >= 'A') && (str[i] <= 'Z')))
check = 1;
else
check = -1;
}
str = '\0';
return check;
that's my code ,but the function keep return -1 please help
Some of your && must replaced by || because one character is a number OR a lower case OR a space OR an upper case, but it cannot be all these things at a time :
check = 1;
for (int i = 0; i < strlen(str); i++)
{
if (! (((str[i] >= '0') && (str[i] <= '9')) ||
((str[i] >= 'a') && (str[i] <= 'z')) ||
(str[i] == ' ') ||
((str[i] >= 'A') && (str[i] <= 'Z')))) {
check = -1;
break;
}
}
You can use these three function which are countain in the hreader #include <ctype.h>
isalpha : Checks if a character is alphabetic (upper or lower case).
isdigit : Checks if a character is a number.
isblank : Checks whether a character is blank or not.
#include <ctype.h>
#include <stdio.h>
float avg_word_len(char* string)
{int check=-1;
for(int i=0;string[i]!='\0';i++)
{
if(isalpha(string[i])||isdigit(string[i])||isblank(string[i]))
{
check=1;
}
}
return check;
}
int main()
{
char string[150];
printf("Give me a text :");
scanf("%s[^\n]",string);
printf("\n%.f\n",avg_word_len(string));
}
As Weather Vane commented, a lot of those &&s should be ||s - additionally, parentheses should surround each range (e.g. ('0' <= str[i] && str[i] <= '9'))).
To check whether the character is in a range, we use AND (i.e. the character is above the lower bound AND below the upper bound). To check whether the character is in one of multiple ranges, we use OR (i.e. the character is in range 1 OR it is in range 2 OR...).
If we were to only fix that, here's how the if condition would look:
(str[i] >= '0' && str[i] <= '9') || (str[i] >= 'a' && str[i] <= 'z') || (str[i] == ' ') || (str[i] >= 'A' && str[i] <= 'Z')
Having said that, I would suggest using the function isalnum from ctype.h in the standard library, which checks if a character is alphanumeric. It makes the code much simpler and avoids the assumption that characters are ordered in such a way that all lowercase letters lie between 'a' and 'z' (which is true in ASCII - which is what is used in practice - but is not standard).
In addition, I would suggest initializing check to -1 and breaking early from the loop once you find a non-alphanumeric, non-space character so that a -1 is not later overwritten by a 1 (as would happen in the current version of your code).
This is what it would look like:
float check = -1;
for (int i = 0; i < strlen(str); i++)
{
if (!isalnum(str[i]) && str[i] != ' ') {
check = 1;
break;
}
}
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am creating a program that requires the user to create a password that has at least one symbol, one uppercase letter, one lowercase letter, and a digit. However, I got so many errors. I fixed most of them but there are still a few I can't seem to figure out. It would be easier to just send a screenshot.
And here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> //To use isupper, isalpha, and isdigit
int main() {
//Declaring the variables
char userPassword;
int i;
int digit = 0;
int upper = 0;
int lower = 0;
int letter = 0;
int symbol = 0;
//User enters password
printf("Please create a password including at least 1 number, 1 uppercase letter, and one symbol: ");
scanf(" %c", &userPassword);
//strlen makes sure password is not less than 8 characters
if (strlen(userPassword) < 8) {
printf("INVALID PASSWORD.");
}
else {
//A for loop that checks if all the conditions are met
for (i = 0; i = 20; i++) {
//Makes sure password has a letter
if (isalpha(userPassword[i])) {
letter++;
}
//Makes sure password has an uppercase letter
else if (isupper(userPassword)) {
upper++;
}
//Makes sure password has a lowercase letter
else if (islower(userPassword)) {
lower++;
}
//Makes sure password has a digit
else if (isdigit(userPassword)) {
digit++;
}
//Makes sure password has a symbol
else if (userPassword == '!' || userPassword == '#' || userPassword == '#' || userPassword == '$' || userPassword == '%' || userPassword == '^' || userPassword == '&' || userPassword == '*' || userPassword == '(' || userPassword == ')' || userPassword == '-' || userPassword == '+' || userPassword == '_');
symbol++;
}
}
//If the password has all of them, it can be created
if (digit == 0 && upper == 0 && lower == 0 && letter == 0 && symbol == 0) {
printf("PASSWORD CREATED.");
}
else {
printf("INVALID PASSWORD.");
}
return 0;
}
Any help would be appreciated!
First of all, we need to address some error in syntax as well as logic. The following things are changed:
userPassword should be a character array. I assume you have chosen maximum length of password as 20 by looking at your for loop. Therefore, declare it as char userPassword[20].
The condition in the for loop is changed to for (i = 0; i < 20; i++).
There was a logical mistake in the algorithm to check the type of the character. Therefore, I have replaced the else if constructs to if.
Character array in C, should be scanned using the %s format specifier.
Also, don't forget to include string.h for the strlen() function.
Have a look a the corrected code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h> //To use isupper, isalpha, and isdigit
#include <string.h>
int main() {
//Declaring the variables
char userPassword[20]; //Assuming maximum length of password is 20.
int i;
int digit = 0;
int upper = 0;
int lower = 0;
int letter = 0;
int symbol = 0;
//User enters password
printf("Please create a password including at least 1 number, 1 uppercase letter, and one symbol: ");
scanf(" %s", userPassword);
//strlen makes sure password is not less than 8 characters
if (strlen(userPassword) < 8) {
printf("INVALID PASSWORD.");
}
else {
//A for loop that checks if all the conditions are met
for (i = 0; i < 20; i++) {
//Makes sure password has a letter
if (isalpha(userPassword[i])) {
letter++;
}
//Makes sure password has an uppercase letter
if (isupper(userPassword[i])) {
upper++;
}
//Makes sure password has a lowercase letter
if (islower(userPassword[i])) {
lower++;
}
//Makes sure password has a digit
if (isdigit(userPassword[i])) {
digit++;
}
//Makes sure password has a symbol
if (userPassword[i] == '!' || userPassword[i] == '#' || userPassword[i] == '#' || userPassword[i] == '$' || userPassword[i] == '%' || userPassword[i] == '^' || userPassword[i] == '&' || userPassword[i] == '*' || userPassword[i] == '(' || userPassword[i] == ')' || userPassword[i] == '-' || userPassword[i] == '+' || userPassword[i] == '_'){
symbol++;
}
}
//If the password has all of them, it can be created
if (digit > 0 && upper > 0 && lower > 0 && letter > 0 && symbol > 0) {
printf("PASSWORD CREATED.");
}
else {
printf("INVALID PASSWORD.");
}
}
return 0;
}
Test Cases:
Input 1: Rt%oi45u#
Output: PASSWORD CREATED.
Input 2: Rt%oiu#
Output: INVALID PASSWORD.
At a quick glance:
As the warning says, you'll want #include <string.h> to include the definition of strlen.
You declare userPassword as only one character, not as an array of characters (e.g. userPassword[32]) (which can hold a string up to 31 characters in length).
You should use scanf("%s", userPassword) (or preferably fgets with a maximum length) to read strings.
Your for loop condition is wrong; for (i = 0; i < strlen(userPassword); i++) { is likely what you're looking for.
All but the first if(isalpha...) condition are wrong; you're not indexing the password in the rest (userPassword[i] c.f. userPassword)
There's an extraneous ; after the special-character check, so symbol gets incremented every time
The check for whether all of the required character types exist is inverted; it'd create the password when none of the conditions match.
Your code have 3 errors.
You must include string.h for strlen function.
%c can only cover character. replace %c to %s in scanf(" %c", &userPassword);
And declare userPassword as char array. replace char userPassword[32]
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
So I'm trying to make this like a counter with two sets of digits, my logic seems right, it will increment till nine then the counter will "flip" the next digit and so on and so forth. When I run it though I just get pages of zeroes, I was wondering if anyone can help or point me in the right direction.
char ft_putchar(char c)
{
write(1, &c, 1);
return 0;
}
void ft_print_comb2(void)
{
char num1a = '0';
char num1b = '0';
char num2a = '0';
char num2b = '0';
while (num1a != '9' && num2a != '9')
ft_putchar(num1a);
ft_putchar(num1b);
ft_putchar(',');
ft_putchar(' ');
ft_putchar(num2a);
ft_putchar(num2b);
num2b++;
if (num2b == '9')
{
num2b ='0';
num2a++;
}
if (num2a == '9')
{
num2a ='0';
num1b++;
}
if (num1b == '9')
{
num1b='0';
num1a++;
}
}
You while has a single line body which is ft_putchar(num1a); due to the missing braces {..}
Try it like so
void ft_print_comb2(void)
{
char num1a = '0';
char num1b = '0';
char num2a = '0';
char num2b = '0';
while (num1a != '9' && num2a != '9')
{
ft_putchar(num1a);
ft_putchar(num1b);
ft_putchar(',');
ft_putchar(' ');
ft_putchar(num2a);
ft_putchar(num2b);
num2b++;
if (num2b == '9')
{
num2b ='0';
num2a++;
}
if (num2a == '9')
{
num2a ='0';
num1b++;
}
if (num1b == '9')
{
num1b='0';
num1a++;
}
}
}
My program should take in a char, and encode it using ROT13 if it is a letter, and otherwise leave it the same, and then print the result.
My code below works for all lowercase letters, and uppercase letters A-M, but fails on uppercase letters N-Z, and other symbols/numbers. Any help appreciated :)
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#define TRUE 1
#define FALSE 0
#define UPPER_START 65
#define UPPER_END 90
#define LOWER_START 97
#define LOWER_END 122
#define UPPER_MID 77
#define LOWER_MID 109
void testEncode (void); int isValid (char cipherChar); char encode (char letter);
int main (int argc, char* argv[]) {
char cipherChar;
scanf("%c", &cipherChar);
if (isValid(cipherChar) == TRUE) {
printf("%c", encode (cipherChar));
} else if (isValid(cipherChar) == FALSE) {
printf("%c", cipherChar);
}
return EXIT_SUCCESS;
}
int isValid (char cipherChar) {
int valid;
if ((cipherChar >= UPPER_START) &&
(cipherChar <= UPPER_END)) {
valid = TRUE;
} else if ((cipherChar >= LOWER_START) &&
(cipherChar <= LOWER_END)) {
valid = TRUE;
} else {
valid = FALSE;
}
return valid;
}
char encode (char letter) {
if ((letter <= UPPER_MID) || (letter <= LOWER_MID)) {
letter = letter + 13;
} else {
letter = (letter - 13);
}
return letter;
}
ROT13 generally doesn't affect characters other than [A-Za-z], so I'd say just ignore those. unless you have some reason to rotate them as well. For example, sometimes 0-9 are treated with ROT5.
In any case, your if statement with the clause (letter <= UPPER_MID) || (letter <= LOWER_MID) basically says, "any character before 'a' gets 13 added to it", so that's why [N-Z] aren't working correctly. Instead, try breaking out the upper- and lower-case logic and handling the wrap-around per-case, like this:
if (letter >= UPPER_START && letter <= UPPER_END) {
letter = letter + 13;
if (letter > UPPER_END) {
letter -= 13;
}
} else if (letter >= LOWER_START && letter <= LOWER_END) {
letter = (letter + 13);
if (letter > LOWER_END) {
letter -= 13;
}
}