Problems with strings (do/while loop and if logic) - c

This code glitches on two things that I cannot diagnose, but is isolated to the if statement: if (strlen(strA) > 8). Suppose I enter in the string "1234567*aA", the program tells me the password is too long, so then I enter in the string "12345", which then triggers the else if statement: else if (strlen(strA) < 9). But everything in the while loop while (j<=9) gets triggered (the program tells me there is a number, a special character, a lowercase letter, and an uppercase letter) and the do/while loop finishes, and the program prompts me to confirm the password. That's wrong. It should prompt me to enter in the password again.
The second issue I notice is if I enter in a string "1111111111111111111", which is obviously too long, the program says the password is too long, but the entire do/while loop terminates and it asks me to confirm my passcode. It should ask me to enter a password again.
If I take out the if statements: if (strlen(strA) > 8) and else if (strlen(strA) < 9), and just run the while loop: while (j<=9), the program works fine, as long as I don't enter in too many characters in the string.
Can anyone diagnose the problem?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
char strA[10];
char strB[10];
char strC[] = {'1','2','3','4','5','6','7','8','9','0'};
char strD[] = {'!','#','#','$','%','^','&','*','(',')'};
char strE[] = {'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'};
char strF[] = {'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 i, j, k;
do {
k = 0;
j = 0;
printf("Please enter your password: ");
scanf("%s", &strA);
printf("%s\n", strA);
if(strlen(strA) > 8) {
printf("That password is too long\n");
}
else if(strlen(strA) < 9) {
while (j <= 9) {
for(i = 0; i <= 9; i++) {
if(strA[j] == strC[i]) {
printf("there is a number in this string.\n");
k++;
j = 0;
while (j <= 9) {
for(i = 0; i <= 9; i++) {
if(strA[j] == strD[i]) {
printf("there is a character in this string.\n");
k++;
j = 0;
while(j <= 9) {
for(i = 0; i <= 25; i++) {
if(strA[j] == strE[i]) {
printf("there is a lowercase letter in this string.\n");
k++;
j = 0;
while(j <= 9) {
for(i=0;i<=25;i++) {
if(strA[j] == strF[i]) {
printf("there is an uppercase letter in this string.\n");
k++;
}
}
j++;
}
}
}
j++;
}
}
}
j++;
}
}
}
j++;
}
if(k < 4) {
printf("Your password must contain at least one uppercase letter, one lowercase letter, a number, and a special character.\n");
}
}
} while(k < 4);
printf("Please confirm your password: ");
scanf("%s",&strB);
while(strcmp(strA, strB) != 0) {
printf("%s\n",strB);
printf("Your passwords do not match.\nPlease confirm your password: ");
scanf("%s",&strB);
}
putchar('\n');
printf("%s\n", strA);
printf("%s\n", strB);
return 0;
}

I think following line is creating the problem:
char strA[10];
char strB[10];
Initialize with default values
memset(&strA,'\0', sizeof(strA));
memset(&strB,'\0', sizeof(strB));

Look at ASCII standards : there is a faster way to test if a char c is a digit (c>47 && c<58)! http://en.wikipedia.org/wiki/ASCII
More : look at ctype.h as stated here Determine if char is a num or letter
http://www.cplusplus.com/reference/locale/isalpha/
isalpha(c) : true if letter
isdigit(c) : true if digit
``isupper(c)` : true if upper case
islower(c) : true if lower case
Bye,
Francis

Related

Controlling user input in regards to strings in bidimensional arrays

I'm trying to allow the user to only write names of students in uppercase in C.
I've tried :
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main() {
int number_ofstudents, i, j;
char Name[100][20];
do {
printf("Enter number of students \n");
scanf("%i", &number_ofstudents);
} while ((number_ofstudents < 0) || (number_ofstudents > 100));
for (i = 0; i < number_ofstudents; i++) {
for (j = 0; j <= strlen(Name[i]) - 1; j++) {
printf("Enter the name of student number %i in uppercase \n", i + 1);
do {
fflush(stdin);
fgets(Name[i], 20, stdin);
} while ((Name[i][j] < 'A') || (Name[i][j] > 'Z'));
}
}
return 0;
}
I've also tried:
for (i = 0; i < number_ofstudents; i++) {
for (j = 0; j <= Name[i][j] != '\0'; j++) {
printf("Enter the name of student number %i in uppercase \n", i + 1);
do {
fflush(stdin);
fgets(Name[i], 20, stdin);
} while ((Name[i][j] < 'A') || (Name[i][j] > 'Z'));
}
}
What I'm expecting is for the program to keep demanding that I enter the name of the student number x until my input is all in uppercase, however once I execute none of my inputs are accepted and the phrase "Enter the name of student number 1 in uppercase " keeps repeating itself.
Does the issue lie in my 2nd for loop when I'm trying to manipulate the letter input? I haven't learned pointers or functions yet.

Problem with Hangman game letters changing order, or solution changing to just one letter

I'm trying to make a hangman game and everything looks fine until I reach the end where sometimes the game says that the solution is just one character, or if I guess a letter they start changing places to the right. I leave you here with the code and I hope that someone can help me to find my error, thank you!
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#define VOCABULARY_SIZE 8
#define MAX_STRING 32
#define MAX_GUESS 6
int random_number(int a, int b)
{
return a + rand() % (b - a + 1);
}
int main()
{
//random word selsection
srand((unsigned)time(NULL));
const char VOCABULARY[VOCABULARY_SIZE][MAX_STRING] = {"vehicle", "building", "shirt", "pencil", "batman", "dromedary", "peach", "hangman"};
char word[MAX_STRING];
int i;
i = random_number(0, VOCABULARY_SIZE - 1);
strcpy(word, VOCABULARY[i]);
//user word
int guesses = 0, length = strlen(word);
char letters[MAX_GUESS];
char input[MAX_STRING];
char temp_char;
char temp_input[MAX_STRING];
do
{
printf("\nYour entered letters are: ");
printf("%s", letters);
printf("\nYour letters found are: ");
for (int j = 0; j < length; j++)
{
if (word[j] == input[j])
{
printf("%c", word[j]);
}
else
{
printf("_");
}
}
printf("\n%d-letter word. %d out of %d failures. Enter a letter: ", length, guesses, MAX_GUESS);
scanf(" %c", &temp_char);
letters[guesses] = temp_char;
letters[guesses+1] = '\0';
for (int j = 0; j < length; j++)
{
if (word[j] == temp_char)
{
input[j] = word[j];
}
}
guesses++;
printf("\nWhat is the word to guess? ");
scanf(" %s", temp_input);
} while ((strcmp(input, word) != 0 || strcmp(temp_input, word) != 0) && guesses <= MAX_GUESS);
if (strcmp(input, word) == 0 || strcmp(temp_input, word) == 0)
{
printf("\nCongratulations, the word was %s!", word);
}
else if (guesses > MAX_GUESS)
{
printf("\nBetter luck next time... The word was %s", word);
}
}
Your letters array is one entry too small to hold the terminating nul character that you apply in this line:
letters[guesses+1] = '\0';
You also have an off-by-one error since guesses starts at zero and your loop tests if it's <= MAX_GUESS.
These two errors in combination mean that your letters array is two bytes too small. Likely it spills over into your word array, leaving the last guess and the terminating nul in there when you go to print it.

Letter guessing game in C using if else statements

I'm new to programming and am trying to do this guessing game by a simple C program below. When I input letters from the word "apple", every letter (p,l,e) executes the wrong guess try again statement except for the letter 'a'. I can't seem to understand what I'm doing wrong here. Any insights is highly appreciated.
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <stdlib.h>
#define size 10
int main() {
// initialize variables
char word[size] = "apple";
char guess;
char arrayofdashes[size] = "_____";
printf("guess a letter \n");
// input loop
for (int i = 0; i < strlen(word); i++)
{
scanf(" %c", &guess);
for (int j = 0; j< strlen(word); j++ )
{
if (guess == word[j])
{
arrayofdashes[j] = guess;
printf("%s \n", arrayofdashes);
}
else
{
printf("wrong guess. Try again \n");
break;
}
}
}
}
Remove the break and add a flag variable to check the correctness of the input letter. And you need a better way to check if the word spelling is complete.
char flag;
int count = 0;
// input loop
while (count < strlen(word))
{
scanf(" %c", &guess);
flag = 0;
for (int j = 0; j< strlen(word); j++ )
{
if (guess == word[j] && guess != arrayofdashes[j])
{
arrayofdashes[j] = guess;
count++;
flag = 1;
}
}
if (flag)
printf("%s \n", arrayofdashes);
else
printf("wrong guess. Try again \n");
}
the problem is that you're using break - this drops out of your inner for-loop after comparing your input against the first character, and prevents it from being compared with subsequent characters.
What strategies have you tried for debugging this yourself? You'll have a few more changes to make aside from removing break, but figuring them out is part of the fun
for (int j = 0; j < strlen(word); j++)//no two loop
{
scanf(" %c", &guess);
if (guess == word[j])
{
arrayofdashes[j] = guess;
printf("%s \n", arrayofdashes);
}
else
{
printf("wrong guess. Try again \n");
j--;
}
}
You don't need the input loop. And if the answer is not correct you should subtract one from j.

Limitation in the implementation of Brute Force

I have written a code which is supposed to crack a three digit numeric password. This code seems to work if the password is 888 or less than that. If the password is greater than 888, the code shows the following output:
Unable to crack password..
I'd like to know the reason behind this limitation and the solution to this problem. Thanks in advance.
#include <stdio.h>
#include <string.h>
int main()
{
char pswd[5];
char brute[4];
char crack[4];
printf("Program to crack a 3 digit numeric password\n ");
printf("Enter password: ");
scanf("%s", pswd);
int i, j, k;
int flag = 1;
for(i = 48; i < 57; ++i)
{
for(j = 48; j < 57; ++j)
{
for(k = 48; k < 57; ++k)
{
crack[0] = i;
crack[1] = j;
crack[2] = k;
crack[3] = 0;
if(strcmp(crack, pswd) == 0)
{
flag = 0;
break;
}
}
if(flag == 0) break;
}
if(flag == 0) break;
}
flag == 0 ? printf("Password cracked successfully.\
Your password is %s", crack) : printf("Unable to crack password..");
return 0;
}
The problem is that in your for-loops, the number 57 represents the character '9' but you added a strictly less than meaning you will not take the character '9', a simple fix would be to just add <='9' or <=57, so your code would look like:
#include <stdio.h>
#include <string.h>
int main()
{
char pswd[5];
char brute[4];
char crack[4];
printf("Program to crack a 3 digit numeric password\n ");
printf("Enter password: ");
scanf("%s", pswd);
int i, j, k;
int flag = 1;
for(i = '0'; i <= '9'; ++i)
{
for(j = '0'; j <= '9'; ++j)
{
for(k = '0'; k <= '9'; ++k)
{
crack[0] = i;
crack[1] = j;
crack[2] = k;
crack[3] = 0;
if(strcmp(crack, pswd) == 0)
{
flag = 0;
break;
}
}
if(flag == 0) break;
}
if(flag == 0) break;
}
flag == 0 ? printf("Password cracked successfully.\
Your password is %s", crack) : printf("Unable to crack password..");
return 0;
}
You could also change it to work for more than 3 digit numbers, my approach without arrays:
#include <stdio.h>
int main()
{
int pswd,brute = 0;
printf("Program to crack a positive password\n ");
do
{
printf("Enter password: ");
scanf("%d", &pswd);
} while(pswd<0);
while(brute != pswd)
brute++;
printf("The password is %d",brute);
getchar();
return 0;
}

String Sort and remove Duplicates

First I apologize for any mistype, for I am Brazilian and English is not my native language.
I am a freshman at my college and I got this algorithm to solve, from my teacher:
Make a program that creates a vector of n words, n being a size entered by the user (maximum 100). Your program should remove all duplicate words from the input vector and sort the words. Print the final vector without repeated and ordered words.
E.g. with 7 words to sort:
Input: 7 [enter]
hand ear leg hand hand leg foot
Output: ear foot hand leg
Note: Comment the program prints so that the output of the program is as shown in the example above (the numbers are separated by a spacebar, without space after last digit).
Note2: In case of invalid entry the program should print: "invalid entry" (all lower case).
Ok, I got it working but the I got confused with the notes and I can't find a way to fix the possible bugs, here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
char word[100][100], aux[100];
int i, j, num;
printf("Type how many words you want to order: ");
do
{
scanf("%d", &num);
}while (num>100 || num<=0);
for(i=0; i<num; i++)
scanf("%s",&word[i]);
for (i = 0; i < num; i++) //loop to sort alphabetically
{
for (j = i+1; j < num; j++)
{
if ((strcasecmp(word[i], word[j]) > 0)) //swapping words
{
strcpy(aux, word[j]);
strcpy(word[j], word[i]);
strcpy(word[i], aux);
}
}
}
for (i = 0; i < num; i++) //loop to remove duplicates
{
if ((strcasecmp(word[i], word[i+1]) == 0)) //finding the duplicates
{
for (j = i+1; j < num; j++) //loop to delete it
strcpy(word[j], word[j+1]);
num--;
i--;
}
}
printf("\nWords sorted and without duplicates:\n");
for(i=0; i<num-1; i++)
printf("%s ", word[i]); //output with spacebar
printf("%s", word[num-1]); //last output without spacebar
return 0;
}
When I type a word with more than 100 characters, the Code::Blocks closes with an error, else it works fine. What do you think I should change?
The teacher uses a Online Judge (Sharif Judge) to evaluate if the code is right, and I got error in 3 of the tests (that are not specified), all of them were "Time Limit Exceeded". Maybe it has do to with the size of the matrix, or the problem with words >100.
Thanks in advance, Vinicius.
I guess you input sanity check is causing the issue.
As mentioned in the comment section.
If n is always < 100. Definitely your sorting is not causing any time limit exceeded.
Looks like the n is given something greater than 100 and your scanf is waiting and causing the issue. Also, make sure your input numbers are taken properly. If the input is > 100 print 'invalid entry'.
Something like below should work.
scanf("%d", &num);
if (num > 100)
printf("invalid entry");
for (i = 0; i < num; i++) {
scanf("%s", word[i]);
if (strlen(word[i])>100)
printf("invalid entry");
}
Hope it helps!
of course you will get an error if you use woerds more than 100 length casue you
have this line: char word[100][50], aux[100];
that means that you word length limit is set to 50. use word[100][100];
also you may not delete duplicates, just skip them in output
lol of course if youre using judge , you should not output any symbols except the answer, this means you should delete all lines, like :
printf("Type how many words you want to order: ");
and check the input format, and check limitations, i mean max word length , max amounts of words
try smth like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define max_word_length = 101;
#define max_amount_of_words = 101;
int main() {
char word[max_amount_of_words][max_word_length] = {};
char aux[max_word_length];
int i, j, num;
scanf("%d", &num);
if (num < 0 || num > 100) {
printf("invalid entry");
return 0;
}
for (i = 0; i < num; i++) {
scanf("%s", word[i]);
}
for (i = 0; i < num; i++) {//loop to sort alphabetically
for (j = i + 1; j < num; j++) {
if ((strcasecmp(word[i], word[j]) > 0)) { //swapping words
strcpy(aux, word[j]);
strcpy(word[j], word[i]);
strcpy(word[i], aux);
}
}
}
bool is_joint = false;
for (i = 0; i < num; i++) { //loop to skip duplicates
if ((strcasecmp(word[i], word[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
if(is_joint) printf(" ");
printf("%s ", word[i]);
is_joint = true;
}
}
return 0;
}
I got 100% on Judge, I fixed the code and looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char word[101][101],aux[101]; //a number higher than the limit to comparisons
int i,j,num;
scanf("%d",&num);
if(num<=0||num>100){ // if words < 0 or >100
printf("invalid input");
return 0;
}
for(i=0;i<num;i++){
scanf("%s",&word[i]); //read n words
if(strlen(word[i])>100){ //if word >100 caracters
printf("invalid input");
return 0;
}
for(j=0;j<strlen(word[i]);j++){
if (word[i][j]>=65&&word[i][j]<=90){
word[i][j]= word[i][j]+32; // if word is uppercase, make them lowcase
}
else if (word[i][j]>122||word[i][j]<97){// if word is different from alphabet lowercase
printf("invalid input");
return 0;
}
}
}
for(i=0;i<num;i++){
for(j=i+1;j<num;j++){
if((strcmp(word[i],word[j])>0)){ //loop to sort words
strcpy(aux,word[j]);
strcpy(word[j],word[i]);
strcpy(word[i],aux);
}
}
}
for(i=0;i<num-1;i++){
if((strcmp(word[i],word[i+1])!=0)){ // output words with spacebar, without the last one
printf("%s ",word[i]);
}
}
printf("%s",word[num-1]); // last word without spacebar
return 0;
}
Thank you everyone who tried to help, I've learned a lot with your suggestions!
This project is actually pretty tough assignment for a programmer who just
started in C.
Run this program in your computer.
Before running against the Judge, make sure you run many times with your manual inputs. Once you are happy with the tests, try against the Judge.
Like I said, the hardest part is storing the user's inputs according to spec (accepting space or newline characters in multiple lines).
#include <stdio.h>
#include <string.h>
int
main(void)
{
int iNumW, iIndex;
int iWCnt = 0;
int iC;
char caTemp[100];
char caWords[100][100];
char *cpDelimeter = " \n";
char *cpToken;
char *cp;
short sIsWord = 1;
char caGarbage[100];
scanf("%d", &iNumW );
fgets(caGarbage, sizeof caGarbage, stdin); //Remove newline char
//Get word inputs
while( iWCnt < iNumW )
{
fgets(caTemp, sizeof caTemp, stdin );
for( cpToken = strtok( caTemp, cpDelimeter ); cpToken != NULL; cpToken = strtok( NULL, cpDelimeter)){
cp = cpToken;
while( *cp ){
sIsWord = 1;
//Check if alphabet
if( !isalpha(*cp) ){
sIsWord = 0;
break;
}
cp++;
}
if( sIsWord ){
strcpy( caWords[iWCnt], cpToken );
//printf( "%s\n", caWords[iWCnt]);
iWCnt++;
if( iWCnt >= iNumW ) break;
} else {
printf("invalid entry.\n");
}
//printf("%d\n", iWCnt);
}
}
int i,j ;
for (i = 0; i < iWCnt; i++) {//loop to sort alphabetically
for (j = i + 1; j < iWCnt; j++) {
if ((strcasecmp(caWords[i], caWords[j]) > 0)) { //swapping words
strcpy(caTemp, caWords[j]);
strcpy(caWords[j], caWords[i]);
strcpy(caWords[i], caTemp);
}
}
}
for (i = 0; i < iWCnt; i++) { //loop to skip duplicates
if ((strcasecmp(caWords[i], caWords[i + 1]) != 0)) { //if there is a duplicate , we willnot output it
printf("%s ", caWords[i]);
}
}
return 0;
}

Resources