Broken code(newbie code), Loop not working as intended - c

I am trying to write a program that prompts people to re-enter their name if they put numbers or special characters in them. (Working on numbers first then I will do special characters).
My for loop is not acting as I expected it to. I wanted my for loop to go over every char in name[256], and check if it is a ... z || A ... Z. However, I am running into problems. See output below the code.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int age;
int i = 0; //for the loop
float height, weight;
char name[256];
char reason[256];
printf("--------------------------------\n");
printf("WRITE YOUR INFORMATION\n");
printf("--------------------------------\n");
printf("NAME : ");
fgets(name, 256, stdin);
while (name[i] != '\0')
{
if (name[i] != (name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z'))
{
printf("Enter your name again, no numbers.\n");
i++;
printf("NAME : ");
fgets(name, 256, stdin);
}
break;
}
printf("AGE :");
return 0;
}
This is when my input for fgets function is br4ndon, sure it worked good, but when i typed in br4ndon again, it passed by... it wasn't supposed to.
--------------------------------
WRITE YOUR INFORMATION
--------------------------------
NAME : br4ndon
Enter your name again, no numbers.
NAME : br4ndon
AGE :
Now this is an input with brandon
--------------------------------
WRITE YOUR INFORMATION
--------------------------------
NAME : brandon
Enter your name again, no numbers.
NAME : brandon
AGE :
How can I make sure that it only prompts to re-enter name if the charachter contains anything but a ... z || A ... Z?

There are many issues in your code:
you mix up the loop for the input of name and the loop that checks if none of the chars of name is anything else than a letter.
you omit the removal of the trailing \n after fgets(read the fgets documentation)
the condition name[i] != (name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') makes no sense at all.
You want something like this:
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
int main()
{
int age;
float height, weight;
char name[256];
char reason[256];
printf("--------------------------------\n");
printf("WRITE YOUR INFORMATION\n");
printf("--------------------------------\n");
while (1)
{
printf("NAME : ");
int nameok = 1;
fgets(name, 256, stdin);
name[strcspn(name, "\n")] = 0; // remove the `\n` at the end of name
for (int i = 0; i < strlen(name); i++)
{
if (!(name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z'))
{
// character not included in A..Z or a..z
nameok = 0;
break;
}
}
if (nameok)
break; // name is OK, we end the while loop
// name not OK: ask again
printf("Enter your name again, no numbers.\n");
continue;
}
printf("AGE :");
return 0;
}
There is still room for improvement:
Examples:
you should use isalpha from ctype.h (which you include already) instead of the awkward !(name[i] >= 'a' && name[i] <= 'z') || (name[i] >= 'A' && name[i] <= 'Z') condition.
you should make a function that asks for the name
fgets(name, 256, stdin) should rather be fgets(name, sizeof(name), stdin), so if you change the size of the name array, you only need to change it in one place

Related

How to check a string contain a certain value in C

#include <stdio.h>
#include <string.h>
#define CHAR_SIZE 35
//Function to remove white space
char *remove_white_spaces(char *str)
{
int i = 0, j = 0;
while (str[i])
{
if (str[i] != ' ')
str[j++] = str[i];
i++;
}
str[j] = '\0';
return str;
}
void main()
{
int i = 0;
char str[CHAR_SIZE];
printf("\nKey in input: ");
fgetchar();
fgets(str , CHAR_SIZE, stdin);
//Remove white space
remove_white_spaces(str);
printf("%s",str);
//for (i = 0; str[i] != '\0'; ++i);
//printf("Length of the string: %d", i);
if (str[i] == '0' || str[i] == '1' )
{
printf("CORRECT");
}
else
{
printf("Wrong Input");
}
}
I want to check whether the user has type in the correct input. For example, I have key in 0 01111110 10100000000000000000000. After removing the white space, the str input became 00111111010100000000000000000000. From this str, I want to check that the user has only key in 0 and 1. The output of the result I got was correct which is shown below1.
Output of result
However, when the user key in another value including 0 and 1. The output I suppose to get is the wrong input. But I obtained Correct as the result which is shown below2.
Output of result
Additional question, How do I implement an if statement that the str has to only have 32 characters to continue otherwise it has to break and the user key has to key in 32 characters only. Can I do it in a while loop instead of an if statement so that the user would not need to run the code again?
You could use strtok to extract your characters. Also there's a flaw in your logic. it should be if (str[i] == '0' || str[i] == '1' to check if the value is '0' OR '1'. Here's a sample implementation you could refer to:-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define CHAR_SIZE 100
int main()
{
char str[CHAR_SIZE];
printf("\n Key in value: ");
getchar();
fgets(str, CHAR_SIZE, stdin);
char *tok;
tok = strtok(str, "\n");
int i = 0;
tok++; //skip the first character which is a space
while (*tok != 0x00)
{
if (*tok <= 0x31 && *tok >= 0x30)
tok++;
else
{
printf("Wrong number input ==> %c \n", *tok);
break;
}
}
}
initialize i:
putting the equivalent of C's
int i = 0;
in your prog lang before entering the while loop should do the job.
First of all, you are checking that str[i] should be equal to 0 and equal to 1 – and that doesn't make any sense, because an element in the array can be only one value, 0 or 1; so, you should test if (str[i] == '0' || str[i] == '1').
And, before that, you should initialize i: int i = 0.
Edit you must loop over elements of the string
int check = 0;
while (str[i] != '\0')
{
if (str[i] == '0' || str[i] == '1')
i++;
else {
check = 1;
break;
}
}
if (check == 0){
print("CORRECT");
}
else {
printf("WRONG INPUT");
}

Input Validation in C When Calculating Grades

I have a problem that needs to calculate the grade needed on a final exam in order to get the letter grade that they desire. I have the code correct for the calculations but I need to account for all invalid user input. I have accounted for negative grades and letter grades that don't exist but I can't figure out how to make sure the percentages they are inputting don't contain letters or other characters. For example if I ask for their current grade in the class they cannot input something like 95.6asi!. This is the code I have right now but there are many errors.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
void calcGradeNeededOnFinal() {
double percentWanted = 0.0;
double currentGrade, finalWeight;
char gradeWanted;
printf("Enter the grade you want in the class: ");
scanf("%c", &gradeWanted);
if (gradeWanted == 'A' || gradeWanted == 'a'){
percentWanted = 90.0;
}
else if (gradeWanted == 'B' || gradeWanted == 'b'){
percentWanted = 80.0;
}
else if (gradeWanted == 'C' || gradeWanted == 'c'){
percentWanted = 70.0;
}
else if (gradeWanted == 'D' || gradeWanted == 'd'){
percentWanted = 60.0;
}
else if (gradeWanted == 'F' || gradeWanted == 'f'){
percentWanted = 0.0;
}
else {
printf("Unknown Grade Received: %c. Ending Program.\n", gradeWanted);
exit(0);
}
printf("Enter your current percent in the class: ");
scanf("%lf", &currentGrade);
if(currentGrade < 0) {
printf("The number you last entered should have been positive. Ending program.\n");
exit(0);
}
char gradeString = (char)currentGrade;
for(int i=0; i < strlen(gradeString); ++i) {
if(!(isdigit(gradeString[i])) && (strcmp(gradeString[i], '.') != 0))) {
printf("Invalid formatting. Ending program.\n");
exit(0);
}
}
printf("Enter the weight of the final: ");
scanf("%lf", &finalWeight);
if(finalWeight < 0) {
printf("The number you last entered should have been positive. Ending program.\n");
exit(0);
}
char weightString = (char)finalWeight;
for(int i=0; i < strlen(weightString); ++i) {
if(!(isdigit(weightString[i])) && (strcmp(weightString[i], '.') != 0))) {
printf("Invalid formatting. Ending program.\n");
exit(0);
}
}
// this calculates the grade need on the final test to get the desired grade of the user
double gradeNeededOnFinal = (percentWanted - (currentGrade * (1.0 - finalWeight/100.0))) / (finalWeight/100.0);
printf("You need to get at least %.2lf%% on the final to get a %c in the class.\n", gradeNeededOnFinal, gradeWanted);
}
int main() {
calcGradeNeededOnFinal();
return 0;
}
For example if I ask for their current grade in the class they cannot input something like 95.6asi!.
You have declared grade as char so there is no possibility that it can store 95.6asi!
char gradeWanted;
What you need is : isalpha or isupper and islower function(s) from ctype.h
isalpha() checks for an alphabetic character; in the standard "C" locale, it is equivalent to (isupper(c) || islower(c)). In some locales, there may be additional characters for which isalpha() is true-letters which are neither upper case nor lower case.
Just check if your gradeWanted is an alphabet or not.
Using
if (isalpha( gradeWanted ))
or
if (isupper( gradeWanted ) || islower( gradeWanted ))
is enough.
All ctype functions takes an int and returns an int, you can declare char gradeWanted; as int gradeWanted;
you could read the characters entered and, using the ascii encoding, check (perhaps with a switch) which character is inserted and manage it.
This way you have full control of the entries.
you can get char to ascii conversion with:
int a_as_int = (int)'a';

Alphabet and code ascii

I am trying to create a program in c language that gets a number and a string, for example the number is 3 and the string is "Zig".
The output should be alphabet's codes + the number. If the character's number goes more than "Z" (90) it should start from "A" again. Similarily, for lower case characters, when going beyond "z" start again from "a".
input : "Zig"
number : 3
output : "Clj"
I have a problem with the part that it should start from A(for capitals) & a again.
this is my code now ! I have a problem with rotation part how to start from A or a again :)
char a[50];
int n,i;
printf("enter your number:\t");
scanf("%d",&n);
printf("enter your string:\t");
fflush(stdin);
gets(a);
while('A'<= a[i] <= 'Z'){
if(a[i]+n > 'Z'){
}
else{
a[i]=a[i]+n;
}
i++;
}
while('a' <= a[i] <= 'z'){
if(a[i]+n > 'z'){
}
else{
a[i]=a[i]+n;
}
i++;
}
printf("string:\n");
puts(a);
}
Fixed Bug
#include <stdio.h>
#include <strings.h>
int main(){
char str [80];
int number;
printf ("Enter your string: ");
scanf ("%79s",str);
printf ("Enter your number: ");
scanf ("%d",&number);
for(int i= 0; i < strlen(str);i++){
str[i]+=number;
while(str[i]>'Z' && str[i] < 'a'){
str[i] = 'A'+ str[i] - 'Z';
}
while(str[i]>'z'){
str[i] = 'a'+ str[i] - 'z';
}
}
printf("%s",str);
}
I have a problem with the part that it should start from A(for capitals) & a again
When you get to Z (decimal 90) you can easily subtract 25 (ASCII char "EM") to get back to A (decimal 65). Similarly you can repeat subtraction of 25 when you reach z and it will cycle back to

C language: there is a trailing character after the last character of my output

I am making a Caesar's Cipher for my lab sheet, and have made it able to encrypt 3 subtitution(Caesar's Cipher), which is the point of the exercise. But there has been one thing bugging me. First, there is a trailing character if i put it other than 3. For example, by typing "malware", and 2 for key.
This is my code :
#include<stdio.h>
#include<stdlib.h>
int main()
{
char text[100];
int key,i;
printf("Please enter a word/sentence (lowercaps) for encrypting :\n ");
fgets(text,100,stdin);
printf("Please enter the key that you desire : eg:14\n");
scanf("%d", &key);
for(i=0;i<strlen(text);i++)
{
if (key>=26)
{
key=key%26;
}
if (text[i]==' ')
{
continue;
}
if(text[i]+key>'z')
{
text[i]-=97;
text[i]+=26;
text[i]+=key;
text[i]%=26;
text[i]+=97;
}
else
{
text[i]=text[i]+key;
}
}
printf("this is your encrypted text : %s", text );
}
I hope I followed the correct indentation methods for coding. Got a lot of dislikes because of that
Code is 1) not properly detecting when a char is a lower case letter 2) encrypting non-letters including '\n' from fgets() which is causing OP's "trailing character after the last character of my output".
Instead:
if (text[i] >= 'a' && text[i]<= 'z') {
text[i] = (text[i] - 'a' + key)%26 + `a`;
}
else {
; // nothing
}
Alternatively
if (islower((unsigned char) text[i]) {
text[i] = (text[i] - 'a' + key)%26 + `a`;
}
Note: the above depends on char are encoded as ASCII.
A solution that does not depend on ASCII.
static const char lowercase[] = "abcdefghijklmnopqrstuvwxyz";
char *p = strchr(lowercase, text[i]);
if (p) {
int offset = (p - lowercase + key)%26;
text[i] = lowercase[offset];
}
I will simplify and correct this code to
#include <stdio.h>
int main() {
char text[100];
int key, i;
printf("Enter a word / sentence (lowercaps) for encrypting : ");
fgets(text, 100, stdin);
printf("Enter the key that you desire (eg. 14) : ");
scanf("%d", &key);
key %= 26; // Pull this out of the loop and remove the unnecessary if
for (i = 0; text[i]; ++i) { // Correct the loop condition
if (text[i] == ' ') continue;
if (text[i] + key > 'z')
text[i] = (text[i] - 97 + 26) % 26 + 97; // Simplify
else
text[i] += key;
}
printf("Encrypted text : %s\n", text);
return 0;
}
Input
Enter a word / sentence (lowercaps) for encrypting : malware
Enter the key that you desire (eg. 14) : 2
Output
Encrypted text : ocnyctg
As Blake_Lead said, this '\0' character was changed in your cypher
Indeed I was wrong about the length of the buffer as fgets() puts a '\0'
From the manual page:
A terminating null byte ('\0') is stored after the last character in the buffer.
So, you just need to change your test
if (text[i]==' ')
by something like:
if (text[i] < 'A' || text[i] > 'z' || (text[i] > 'Z' && text[i] < 'a') )

Using character for sentinel but receiving pointer error

I'm trying to program a loop that counts characters until it receives a certain sentinel value. The sentinel value is supposed to be a #, but I've also tried a 0 and a Z and had the same response.
When it compiles, I receive "warning: comparison between pointer and integer" for lines 16 (the line that calls the sentinel.)
If I don't define the sentinel, but instead rely on logical operators in the while statement, then I receive no error, but have an endless loop.
Thanks!
#include <stdio.h>
int main()
{
#define SENTINEL '#'
char ch;
int chcount;
printf("Enter your text, terminate with a #:");
scanf("%s", &ch);
chcount = 0;
while (ch != SENTINEL)
{
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount +1;
printf("You have entered %d characters", chcount);
}
}
return(0)
}
With the %s format specifier, scanf expects the address of a char buffer, where the string you type will be copied.
And you gave the address &ch of a single char, which is obviously not enough to contain a "word" from input with its terminating null character.
Moreover, your loop reads no input from the user. Thus the endless loop.
This is because the way you use scanf(), with %s format specifier you are writing to a char*, not the char ch (as you've declared). In order to write to a single char variable, you should use a %c format specifier.
To fix this you should either use f.e. getchar() instead of scanf() or use scanf() (and change ch to char* then) but iterate over scanned string to check whether there is #.
I would recommend the first solution.
The while loop never ends so I changed your while loop.
I tried to change your program to:
#include <stdio.h>
#define SENTINEL '#'
int main()
{
char ch;
int chcount;
printf("Enter your text, terminate with a #:");
chcount = 0;
while ((ch = getchar()) != SENTINEL)
{
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount + 1;
printf("You have entered %d characters\n", chcount);
}
}
return(0);
}
Some issues I found with your code:
scanf("%s", &ch);
It should be
scanf("%c", &ch);
Next, semicolon missing here: return(0);
However, since your aim is:
I'm trying to program a loop that counts characters until it receives a certain sentinel value. The sentinel value is supposed to be a #
I suggest moving your scanf() inside while loop:
#include <stdio.h>
int main()
{
#define SENTINEL '#'
char ch='0';
int chcount;
printf("Enter your text, terminate with a #:");
chcount = 0;
int i=0;
while (ch != SENTINEL)
{ scanf("%c", &ch);
if ((ch >= 'A') && (ch <= 'Z'))
{
chcount = chcount +1;
printf("You have entered %d characters", chcount);
i++;
}
}
return(0);
}
here is a working version of the posted code.
It contains numerous corrections.
Corrections include consistent/usable indentation and logic corrections
Note: not all implementations have the getline() function
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int sentinelFound = 0;
#define SENTINEL '#'
char* line = NULL;
size_t lineLen = 0;
printf("Enter your text, terminate with a #:");
int chcount;
getline(&line, &lineLen, stdin );
size_t i;
for( i=0; i<lineLen; i++)
{
if( SENTINEL == line[i] )
{
sentinelFound = 1;
break;
}
if ((line[i] >= 'A') && (line[i] <= 'Z')) // only count capital letters
{
chcount = chcount +1;
}
}
free( line );
if( !sentinelFound )
printf( "You did not enter the sentinel character!" );
else
printf("You have entered %d capital characters\n", chcount);
return(0);
} // end function: main

Resources