Validation of password input in C [closed] - c

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I have no idea how to go further with this program that I'm about to create. This is the idea:
Validate the password input to check if the password has at least one
uppercase letter, lowercase letter and a number.
Some parts of it is broken at the moment. For instance the false, true statements. And the "undynamic" char array in the main function. I don't know how to make that at the moment either. But it explains what I'm looking for.
So how can I validate this without writing too much code?
This is my current code:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int passval(char pw[])
{
int x;
for (x = 0; x < sizeof(pw); x++) {
if ( (isalnum(pw[x])) || (ispunct(pw[x])) ) {
return 0;
} else {
return 1;
}
}
return 0;
}
int main()
{
char password[20];
printf("Enter password: ");
scanf("%s", password);
if (passval(password) == TRUE) {
printf("Password is TRUE");
}
return 0;
}

#include <stdio.h>
#include <string.h>
#include <ctype.h>
int
password_validate(const char *pass)
{
int upper = 0, lower = 0, digit = 0;
if (pass == NULL || strlen(pass) == 0)
return -1;
do
{
if (isupper(*pass))
upper = 1;
if (islower(*pass))
lower = 1;
if (isdigit(*pass))
digit = 1;
} while ((!lower || !upper || !digit) && *(++pass));
return (*pass != '\0' ? 0 : (upper == 0 ? -2 : (lower == 0 ? -3 : -4)));
}
Please view the below link to a code sample to be sure to understand some of the corner cases (thank you Alex Pogue for highlighting additional cases) and how this function handles them.
https://ideone.com/GiOGkj

Scan for the string.
If the characters to be found exists, raise flags.
Say "valid" iff all of the required flags are raised.
Example implementation:
#include <ctype.h>
int passval(const char pw[])
{
size_t x;
unsigned char c; /* making this unsigned is important:
char may be negative and passing it to isupper(), etc. may invoke undefined behavior */
int upperExists = 0, lowerExists = 0, numberExists = 0;
for (x = 0; pw[x] != '\0'; x++) {
/* fetch the character */
c = pw[x];
/* raise flags when the character is required kind */
upperExists = upperExists || isupper(c);
lowerExists = lowerExists || islower(c);
numberExists = numberExists || isdigit(c);
}
/* check if all of required flags are raised */
return upperExists && lowerExists && numberExists;
}

Arrays that are passed to a function decay into pointers so you cannot do sizeof() in your function, instead pass the string length strlen()
I would do something like this
#include <ctype.h>
#include <stdbool.h>
bool validatePassword(const char* pw, const int len)
{
int x;
bool upperCase = false;
bool lowerCase = false;
bool number = false;
for (x = 0; x < len; x++)
{
if ( pw[x] == toupper(pw[x]) )
{
upperCase = true;
}
else if ( pw[x] == tolower(pw[x]) )
{
lowerCase = true;
}
else if ( isdigit(pw[x]) )
{
number = true;
}
}
return upperCase && lowerCase && number;
}

My solution is based on parsing a string that ends with a \0 character, check for at least one capital char, small char, and a digit like how an OR gate functions..
Try Online
int passval(char * p)
{
int capital=0, small=0, digit=0;
while (*p && !(capital && small && digit))
capital = (*p>='A' && *p<='Z' ? 1 : capital),
small = (*p>='a' && *p<='z' ? 1 : small ),
digit = (*p>='0' && *p<='9' ? 1 : digit ),
p++ ;
return capital && small && digit;
}

Related

Long Long overflow

I have been working on a small program that converts strings into integers.
I started the program and I was first trying to save in an array but the program is not working.
Its iterating only once and there is no error.I tried it but I think the error is at when I convert the string by subtracting it by 48 in storing it in the array.You can see the code
Sorry this is an edited message tnow the program is working properly but when I give input -"-91283472332"(as per leetcode) I am getting a wrong answer
you can see for yourself -
#include <stdio.h>
int myAtoi(char *s)
{
int i = 0; // for iterating the character
int isNegative = 0; // for checking if the umber is negative
long long res = 0; // for result
while (s[i] != '\0')
{
printf("%d\n",res);
if (48 <= s[i] && s[i]<= 57)
{
res=(res*10)+(s[i]) - 48;
}
else if (s[i] == 45)
{
isNegative = 1;
}
else if (s[i] == ' ')
{
;
}
else
{
break;
}
i++;
}
if (isNegative)
{
res = res-(res*2);
}
printf("%d",res);
return res;
}
int main()
{
char a[] = "-91283472332";
myAtoi(a);
return 0;
}
Your solution is rather more complex than it needs to be.
We can use pointer arithmetic to iterate over the string, and include a condition for our for loop that automatically terminates at the end of the string or when the current character is no longer a digit.
The result can be built up by multiplying it by ten on each loop and adding the current digit's numeric value to it.
A negative sign can be accommodated by checking the first character. It's it's '-' we can set a flag negative to 1 for true and increment the str pointer past the first character. At the end of the function, we can determine whether to result -result or result based on that flag.
#include <string.h>
#include <stdio.h>
#include <ctype.h>
int my_atoi(char *str) {
int result = 0;
int negative = 0;
if (*str == '-') {
negative = 1;
str++;
}
for (; *str && isdigit(*str); str++) {
result *= 10;
result += *str - '0';
}
return negative ? -result : result;
}
int main(void) {
char foo[] = "3456gfghd";
printf("%d\n", my_atoi(foo));
return 0;
}

how to check if the string contains only numbers or word in c

My teacher gave us code that Write a function declared as "int categorize(char *str)" which accepts a string as an input parameter and categorize the string. The function should return the category number as decribed below:
Category 1: If the string contains only capital letters (e.g. ABCDEF), the function should return 1.
Category 2: If the string contains only small letters (e.g. abcdef), the function should return 2.
Category 3: If the string contains only letters but no other symbols (e.g. ABCabc), the function should return 3.
Category 4: If the string contains only digits (e.g. 12345), the function should return 4.
Category 5: If the string contains both letters and digits but no other symbols (e.g. Hello123), the function should return 5.
Category 6: Otherwise, the function should return 6.
I write this but not working
#include<stdio.h>
#include<string.h>
// Write your categorize function here
int categorize(char *str) {
int x=0;
while(str[x]!= '\0'){
if((*str>='A'&&*str<='Z') && (*str>='a'&&*str<='z') && (*str>='0'&&*str<='9'))
return 5;
else if((*str>='A'&&*str<='Z') && (*str>='a'&&*str<='z'))
return 3;
if((*str>='A') && (*str<='Z'))
return 1;
else if((*str>='a')&&(*str<='z'))
return 2;
else if((*str>='0')&&(*str<='9'))
return 4;
x++;
}
return 6;
}
///////////////////////////////////////
// Test main()
// DO NOT MODIFY main()
// or your code will not be evaluated
int main() {
char str[100];
scanf("%s",str);
int c = categorize(str);
printf("%d\n",c);
return 0;
}
///////////////////////////////////////
*str this is a pointer to the first character of the string so along your cycle it only checks this first character.
Furthermore you are returning values before checking the entire string, you need to use flags and set them along the cycle for digits caps and small letters, and in the end return the values according to those flags.
There is the <ctype.h> library which has functions like isalpha and isdigit and can make your job easier, for that I refer you to #DevSolar answer as a better method.
If you can't use it this is the way to go:
Live demo
int categorize(char *str) {
int x = 0;
int is_digit, is_cap, is_small;
is_cap = is_digit = is_small = 0;
while (str[x] != '\0') {
if (!(str[x] >= 'a' && str[x] <= 'z') && !(str[x] >= 'A' && str[x] <= 'Z') && !(str[x] >= '0' && str[x] <= '9'))
return 6;
if (str[x] >= 'A' && str[x] <= 'Z' && !is_cap) //if there are caps
is_cap = 1;
if (str[x] >= '0' && str[x] <= '9' && !is_digit) //if there are digits
is_digit = 1;
if (str[x] >= 'a' && str[x] <= 'z' && !is_small) //if there are smalls
is_small = 1;
x++;
}
if ((is_small || is_cap) && is_digit){
return 5;
}
if(is_small && is_cap){
return 3;
}
if(is_digit){
return 4;
}
if(is_small){
return 2;
}
if(is_cap){
return 1;
}
return 6;
}
Note that this kind of character arithmetic works well in ASCII but fails in other character encodings like EBCDIC which don't have sequencial order for alphabetic characters.
You can do this in O(n) as follows:
#include <ctype.h>
#include <stdio.h>
int check_str(char* str)
{
int category = 0; // 0b001 -> Uper | 0b010 -> Lower | 0b100 -> Number
for ( ; *str != 0; str++) {
if (isupper(*str)) {
category |= 1;
}
else if (islower(*str)) {
category |= 2;
}
else if (isdigit(*str)) {
category |= 4;
}
else
return 6;
}
if (category == 1)
return 1;
if (category == 2)
return 2;
if (category == 3)
return 3;
if (category == 4)
return 4;
if (category == 7)
return 5;
return 6;
}
int main()
{
printf("%d\n", check_str("ABCDEF"));
printf("%d\n", check_str("abcdef"));
printf("%d\n", check_str("ABCabc"));
printf("%d\n", check_str("12345"));
printf("%d\n", check_str("Hello123"));
printf("%d\n", check_str("Hello World 123"));
return 0;
}
OUTPUT
1
2
3
4
5
6
EDIT
Since 0b... is not portable, binary numbers are changed to their decimal equivalents
The standard header <ctype.h> literally has everything you are looking for:
Category 1 is if isupper() is true for all characters.
Category 2 is if islower() is true for all characters.
Category 3 is if isalpha() is true for all characters.
Category 4 is if isdigit() is true for all characters.
Category 5 is if isalnum() is true for all characters.
A quick-and-dirty approach could just iterate through the input once for each of the above:
int categorize( char * str )
{
char * s;
for ( s = str; *s; ++s )
{
/* Need the cast to unsigned char here; negative values
are reserved for EOF!
*/
if ( ! isupper( (unsigned char)*s ) )
{
break;
}
}
if ( ! *s )
{
/* True if the loop ran its full course without breaking */
return 1;
}
/* Same for the other categories */
return 6;
}
Once you got this done, you could start getting funny with the logic, putting all the checks into one loop and keeping track of conditions met.
You seem to have a pretty good start for your project. You capture a String, and then categorize it.
Where you need to improve is the logic for categorization. I would start by making each of your categories into a function.
int isOnlyCapital(char* string)
might return 1 if the string is only comprised of capital letters, and 0 otherwise. The logic might look like
char* position = string;
while (position != '\0') {
if (*position < 'A' || *position > 'Z') {
return false;
}
position++;
}
return true;
Note that you can only return true if you managed to check all charaters with the above code, as you have looped over all characters until you hit the NULL character \0.
With some work, you can modify the above loop to handle your other cases. That would make your logic for the overall top level look like.
if (isOnlyCapital(string)) return 1;
if (isOnlyLowercase(string)) return 2;
... and so on...

segmentation fault on chars array [closed]

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 5 years ago.
Improve this question
I need to count how many strings there is in a "string list". Each string ends as usual with a NUL char ('\0'), and the list ends with two NUL chars in succession.
I wrote a function but I keep getting a segmentation fault:
int numStrsInList(const char* strList) {
int count = 0;
int flag = 0;
if(!(*strList))
return -1;
while (flag != 2) {
if (!(*strList)) {
count++;
flag++;
}
else
flag = 0;
strList++;
}
return count;
}
for example:
const char* empty = "\0";
const char* one = "Hell0 \t\n\v\f\rw0r1d\0";
const char* two = "Hello\0 \t\0";
const char* simple = "Hello\0world\0!\0";
the invocation for example:
numStrsInList(empty)
numStrsInList(one)
numStrsInList(two)
numStrsInList(simple)
for this strings the output should be:
0
1
2
3
There are several issues with your code....
int numStrsInList(const char* strList) {
int count = 0;
int flag = 0;
if(!(*strList)) // this is not right, numStrsInList("\0") returns -1 instead of 0
return -1; // did you mean if (!strlist) ??
while (flag != 2) {
if (!(*strList)) { // maybe using this notation if (!strlist[0])
count++; // would help in avoiding the error above
flag++; // c library has strlen() functions
} // that are much faster and will make your code more readable
else
flag = 0;
strList++;
}
return count;
}
}
Compare to, overall length added per request :)
int numStrsInList(const char* strList, int maxlen)
{
// returns the number of strings in a null terminated array of
// contiguous null-terminated strings.
// maxlen is the maximum overall length of the buffer,
// can be 0 to defeat length checking
const char* s;
int result = 0;
if (!strList) return -1;
for (s = strlist;
s > (char*)1 && s[0] != 0;
s = (maxlen) ? (memchr(s, 0, maxlen - (s - strlist)) + 1)
: (s + strlen(s) + 1) )
{
if ((s - strlist) > maxlen) return -1;
++result;
}
return result;
}
Just use standard C function strchr declared in the header <string.h>.
For example
#include <stdio.h>
#include <string.h>
size_t numStrsInList(const char *s)
{
size_t n = 0;
if (!(s[0] == '\0' && s[1] == '\0'))
{
do
{
s = strchr(s, '\0');
++n;
} while (*++s);
}
return n;
}
int main( void )
{
printf("The number of substrings is %zu\n", numStrsInList("\0"));
printf("The number of substrings is %zu\n", numStrsInList("Hell0 \t\n\v\f\rw0r1d\0")) ;
printf("The number of substrings is %zu\n", numStrsInList("Hello\0 \t\0"));
printf("The number of substrings is %zu\n", numStrsInList("Hello\0world\0!\0"));
}
The program output is
The number of substrings is 0
The number of substrings is 1
The number of substrings is 2
The number of substrings is 3
Without using the standard function strchr the function can be implemented the following way
size_t numStrsInList(const char *s)
{
size_t n = 0;
if (!(s[0] == '\0' && s[1] == '\0'))
{
do
{
while (*s) ++s;
++n;
} while (*++s);
}
return n;
}
Take into account that for example this string
"\0A\0"
contains two substrings: "" and "A". While this string "\0" contains neither substring.
As for your code then already this statement
if(!(*strList))
return -1;
does not make sense.
It seems you mean
if(!strList)
return -1;
that is that the pointer strList is not equal to NULL. However by analogy with standard string functions it is better when the caller checks whether the pointer is equal to NULL.

Separating string to multiple integers [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 9 years ago.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Improve this question
please, how I can convert this:
char infix[] = "123+354*87/156=" (can be variable)
How to separate number's from this string (to integers, like 123 354 87 156, no to 1 2 3 3 5 4...) and char (chars + * / ).
I suppose you need to build a simple calculator... If you're planning to do this from scratch, you gonna need some background from Compiling Theory, and use concepts like Finite State Machine, Parsing, etc.
But there are a lot of tools that can make this task easier: lex/yacc (C), flex/bison (C++) or COCO/R (many languages).
This is a SIMPLE example in C that splits the string in numbers (state=NUM) and symbols (state=SYM):
#include <string.h>
#include <ctype.h>
#define NONE 0
#define NUM 1
#define SYM 2
int _tmain(int argc, char* argv[])
{
char infix[] = "123+354*87/156=";
char buffer[10];
int i, j;
int state = NONE;
char c;
i = 0;
j = 0;
while(i < strlen(infix)) {
c = infix[i];
switch(state) {
case NUM:
if ( isdigit(c) ) {
buffer[j++] = c;
buffer[j] = 0;
i++;
}
else {
printf("%s\n", buffer);
j = 0;
state = NONE;
}
break;
case SYM:
i++;
printf("%c\n", c);
state = NONE;
break;
case NONE:
if ( isdigit(c) ) state = NUM;
else state = SYM;
break;
}
}
getchar();
return 0;
}
When you use C++ and each operator has a length of one char, and string has the form "number operator number operator ... number operator" (that means begins with number, ends with operator and switches always between both) then use istringstream:
#include <sstream>
using namespace std;
void main()
{
char infix[] = "123+345*87/156=";
istringstream is(infix);
double nums[999]; // maybe you need more than 999
char chars[999];
int nums_pos = 0;
int chars_pos = 0;
bool number = true; // begin with number
while (!is.eof())
{
if (number)
{
is >> nums[nums_pos];
nums_pos++;
number = false;
}
else
{
is >> chars[chars_pos];
chars_pos++;
number = true;
}
}
// you got nums_pos-1 numbers and chars_pos chars
}
Here's yet another possible way but in C as you asked...
#include <stdio.h>
main()
{
char infix[] = "123+354*87/156=";
int curVal = 0;
// For each character in infix
for(char *p = infix; *p != '\0'; ++p)
{
// If it is not a ascii numeral
if(*p > '9' || *p < '0')
{
// Output value
printf("%d\n", curVal/10);
// Output char
printf("%c\n", *p);
curVal = 0;
}
else
{
// Accumulate the individual digits
curVal += (*p) - '0';
curVal *= 10;
}
}
}
It will output:
123
+
354
*
87
/
156
=
You can do this as
#include<stdio.h>
int main()
{
char infix[] = "123+354*87/156=";
char *p = infix;
while(1)
{
if(*p == '\0')
break;
if(*p == '+' || *p == '*' ||*p == '/' ||*p == '=' || *p == '-')
{
printf(" ");
}
else
printf("%c", *p);
p++;
}
printf("\n");
return 0;
}
Output:
123 354 87 156

Searching a particular word in a matrix of characters

I was trying to search for a particular word in a matrix of characters through C but was unable to come to a fixed solution.
For ex:
Suppose I have to search for the word INTELLIGENT in a matrix of characters (3*9)
(Once you have picked a character from the matrix to form a sentence, you cannot pick it again to form the same sentence.There is a path from any cell to all its neighboring cells. A neighbor may share an edge or a corner.)
IIIINN.LI
....TTEGL
.....NELI
Output: YES (the word INTELLIGENT can be found)
Can anybody please give a solution to the above problem !!!!
Use a depth first search.
You can do this using a recursive algorthm. Find all the (unused) places containing the first letter then see if it is possible to find the rest of the word on the remaining board by starting from one of the adjacent squares.
#include <stdio.h>
char Matrix[3][9] = {
{ 'I','I','I','I','N','N','.','L','I'},
{ '.','.','.','.','T','T','E','G','L'},
{ '.','.','.','.',',','N','E','L','I'}
};
char Choice[3][9] = { { 0 }, { 0 }, { 0 } };
const char WORD[] = "INTELLIGENT";
const int Len = sizeof(WORD)-1;
int Path[sizeof(WORD)-1] = { 0 };
char get(int row, int col){
if(1 > col || col > 9) return '\0';
if(1 > row || row > 3) return '\0';
if(Choice[row-1][col-1] || Matrix[row-1][col-1] == '.')
return '\0';
else
return Matrix[row-1][col-1];
}
#define toLoc(r, c) (r)*10+(c)
#define getRow(L) L/10
#define getCol(L) L%10
int search(int loc, int level){
int r,c,x,y;
char ch;
if(level == Len) return 1;//find it
r = getRow(loc);
c = getCol(loc);
ch = get(r,c);
if(ch == 0 || ch != WORD[level]) return 0;
Path[level]=toLoc(r,c);
Choice[r-1][c-1] = 'v';//marking
for(x=-1;x<=1;++x){
for(y=-1;y<=1;++y){
if(search(toLoc(r+y,c+x), level + 1)) return 1;
}
}
Choice[r-1][c-1] = '\0';//reset
return 0;
}
int main(void){
int r,c,i;
for(r=1;r<=3;++r){
for(c=1;c<=9;++c){
if(search(toLoc(r,c), 0)){
printf("YES\nPath:");
for(i=0;i<Len;++i){
printf("(%d,%d)", getRow(Path[i]), getCol(Path[i]));
}
printf("\n");
return 0;
}
}
}
printf("NO\n");
return 0;
}
I think this is what you mean..... Though it seems simpler to what you currently have been offered, so I may have misunderstood the question.
I use Numpy to reshape an arbitrary array into a single
list of letters, then we create a mask of the search term and
a copy of the input list.
I tick off each letter to search for while updating the mask.
import numpy as np
import copy
def findInArray(I,Word):
M=[list(x) for x in I]
M=list(np.ravel(M))
print "Letters to start: %s"%"".join(M)
Mask=[False]*len(Word)
T = copy.copy(M)
for n,v in enumerate(Word):
try:
p=T.index(v)
except ValueError:
pass
else:
T[p]=''
Mask[n]=True
print "Letters left over: %s"%"".join(T)
if all(Mask):print "Found %s"%Word
else:print "%s not Found"%Word
print "\n"
return all(Mask)
I=["IIIINN.LI","....TTEGL",".....NELI"]
findInArray(I,"INTEL")
findInArray(I,"INTELLIGENT")
findInArray(I,"INTELLIGENCE")
Example output
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: IIIN.I....TGL.....NELI
Found INTEL
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: II.I.........NLI
Found INTELLIGENT
Letters to start: IIIINN.LI....TTEGL.....NELI
Letters left over: II.I....T.....NLI
INTELLIGENCE not Found
#include <stdio.h>
#define ROW 1
#define COL 11
char Matrix[ROW][COL] = { { 'I','N','T','E','L','L','I','G','E', 'N', 'T'} };
char Choice[ROW][COL] = { { 0 } };
const char WORD[] = "INTELLIGENT";
const int Len = sizeof(WORD)-1;
int Path[sizeof(WORD)-1] = { 0 };
char get(int row, int col){
if(1 > col || col > COL) return '\0';
if(1 > row || row > ROW) return '\0';
if(Choice[row-1][col-1] || Matrix[row-1][col-1] == '.')
return '\0';
else
return Matrix[row-1][col-1];
}
#define toLoc(r, c) (r)*16+(c)
#define getRow(L) L/16
#define getCol(L) L%16
int search(int loc, int level){
int r,c,x,y;
char ch;
if(level == Len) return 1;//find it
r = getRow(loc);
c = getCol(loc);
ch = get(r,c);
if(ch == 0 || ch != WORD[level]) return 0;
Path[level]=toLoc(r,c);
Choice[r-1][c-1] = 'v';//marking
for(x=-1;x<=1;++x){
for(y=-1;y<=1;++y){
if(search(toLoc(r+y,c+x), level + 1)) return 1;
}
}
Choice[r-1][c-1] = '\0';//reset
return 0;
}
int main(void){
int r,c,i;
for(r=1;r<=ROW;++r){
for(c=1;c<=COL;++c){
if(search(toLoc(r,c), 0)){
printf("YES\nPath:");
for(i=0;i<Len;++i){
printf("(%d,%d)", getRow(Path[i]), getCol(Path[i]));
}
printf("\n");
return 0;
}
}
}
printf("NO\n");
return 0;
}

Resources