fgets wants input twice - c

I'm still quite new to C and do have problems with how to indent code, so I apologise for this in advance. I am trying to get the programme to input strings and output readability score. I have the code all written out, however, whenever input a phase and press enter the programme doesn't execute the rest of the code, instead I have to input something else before moving on. I have no idea why! Please could someone help?
#include <string.h>
#include <stdlib.h>
#include <math.h>
int main(void)
{
char str[500]; // think of this like an array
int alphabet =0 , i =0, word=0, special_characters =0, vowels = 0;
printf("Input the string:\n");
fgets(str,500,stdin); // <== issue here where I have to input string twice for while loop to occur!
/* Checks each character of string*/
while(str[i] !='\0')// while there is a character and not empty space
{
if(str[i] == 'a' || str[i] == 'e' || str[i] == 'i' ||
str[i] == 'o' || str[i] == 'u' || str[i] == 'A' ||
str[i] == 'E' || str[i] == 'I' || str[i] == 'O' ||
str[i] == 'U')
{
++vowels;
}
else if((str[i] ==' ' || str[i]=='\n' || str[i]=='\t'))
{ // if there is not space, tab or enter, then logically there is a word
word++; // after not finding a space it is told to look for next one
}
else if((str[i] =='?' || str[i]=='!' || str[i]=='.')) // looks for sentance enders
{
special_characters++; // keeps going until text ends
}
else if((str[i]>='a' && str[i]<='z') || (str[i]>='A' && str[i]<='Z'))
{
// only i is just a counter of each letter in
// this case. alphabet is told to increase
alphabet++; // made this a loop that goes onto next letter
}
i++; // tells i to scan over ALL if loops by being INSDIE the while loop but not
// part of the IF statements!
}
//L = Letters ÷ Words × 100 = 639 ÷ 119 × 100 ? 537
//S = Sentences ÷ Words × 100 = 5 ÷ 119 × 100 ? 4.20
double letters = vowels + alphabet;
double w = word;
double d = 100.0;
double L = (letters/w)*d;
double e = special_characters; // sentances
double S= (e/w)*100;
scanf("%lf",&S);
double index = (0.0588 * L) -(0.296 * S)- 15.8;
scanf("%lf",&index);
double round(double index);
if(index <=1)
{
printf("Below Grade 1\n");
}
else if(index >=3 && index <4)
{
printf(" Grade 3\n");
}
else if(index >=5 && index <6)
{
printf(" Grade 5\n");
}
else if(index >=7 && index <8)
{
printf(" Grade 7\n");
}
else if(index >=8 && index <9)
{
printf(" Grade 8\n");
}
else if(index >=9 && index <10)
{
printf(" Grade 9\n");
}
else if(index >=10 && index <11)
{
printf(" Grade 9\n");
}
else if(index >=16)
{
printf(" Grade 16+\n");
}
}

Your problem is likely further down on the scanf()
Try
// ...
double S= (e/w)*100;
printf("Enter value for S:\n"); // suggestion for feedback
if (scanf("%lf", &S) != 1) {
//scanf failed
fprintf(stderr, "scanf failed.\n");
exit(EXIT_FAILURE);
}
//...

Related

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';

String character check

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.

Problem with inputing only a number from 1 to 1000

Working on Ubuntu
I have a problem with my code and i dont know how to fix. Maybe there is a function that will help me with that.
I want to input a string and then my program need to check if it is a number from 1 to 1000. If there is a letter or a symbol
Here is my code:
char tab[200]="";
int i;
scanf("%199[^\n]s",tab);
for(i=0;i<200;i++)
{
if(tab[i] >= 'A' && tab[i]<='Z')
{
printf("Big letters\n");
}
else if(tab[i] >= 'a' && tab[i]<='z')
{
printf("Small letters\n");
}
}
if(strlen(tab) == 4 && tab[3] > 0 && tab[2] > 0 && tab[1] > 0 && tab[0] > 1)
{
printf("Bigger then 1k\n");
}
else if(strlen(tab) > 4)
{
printf("Longer then 4 chars\n");
}
It's not working properly and it also doesnt include symbols...
I've found code like this but im not sure how to make my number less then 1001
char input[MAXINPUT] = "";
int length,i;
int number;
printf(" id: \n");
fgets(input, MAXINPUT, stdin);
number = atoi(input);
length = strlen (input);
for (i=0;i<length; i++)
if (!isdigit(input[i]))
{
printf ("Entered input is not a number\n");
exit(1);
} else if (number < 1001)
printf ("Given input is a number\n");
Not sure if i am using fgets properly here.
Before u will send me to here
, please read my question
Use This.. Maybe This Help. You can Modify it on your Choice.
#include<string.h> // header file for strlen()
void method()
{
char tab[200]="";
int i;
scanf("%199[^\n]s",tab);
for(i=0;i<strlen(tab);i++) // Loops only to the lenght of total vlaues in array
{
if(tab[i] >= 65 && tab[i]<=90) // Ascii Value of Capital Ltrs
{
printf("Big letter\n");
}
else if(tab[i] >= 97 && tab[i]<=122) // Ascii Value of Small Ltrs
{
printf("Small letter\n");
}
else if(tab[i] >= 48 && tab[i]<=57) // Ascii Value of Numbers
{
printf("Number\n");
}else // of else other numebrs are all Symbols but can be
{
printf("Symbols\n");
}
}
}
Please note that you're compareing characters with integers (numbers). The character '1' in ascii is 49, as an example, while you have been using the numeric value 1 in the comaprisons. Test to add single quotation marks similar to those around your letter comparisons and see if you don't get a different result.
Best regards
Esbjörn

Count and compute: from files; I;m kinda lost on how to get going (Noobie here)

Im going an assignment on trying to count the number of certain keywords in a source code. I for the life of me just don't know how to do it.
For example, my code is suppose to do this
number of total lines
number and percentage of blank lines
number and percentage of comments (start with // or /*)
number and percentages of ints, longs, floats, doubles, char
number and percentages of if's
number and percentage of else's
number and percentage of for's
number and percentage of switch
number and percentage of semicolons
number and percentage of structs
number and percentage of arrays (contains [ or ], divide count by 2)
number of blocks (contains { or }, divide count by 2)
This is the little I done so far
int main()
{
FILE * bsfile;
bsfile = fopen("bship.txt", "r");
char singleLine[150];
while (!feof(bsfile)) {
fgets(singleLine, 150, bsfile);
puts(singleLine);
}
fclose(bsfile);
return 0;
}
It pretty much writes the whole file into the console, than shuts off. If anyone can help me by explaining to me how to find for examples the number of ifs, it would really help me a lot and get me started. I tried google and such, no luck on how I can get this to work. I know I'm suppose to use a counter with the for()?
What you are doing is reading one line from file and putting it in string. Now fgets() is used in loop with a same string which will keep overwriting previous lines. This is not the safe way of copying file data into string. This is unnoticed by you because you are printing everyline after getting it into string. If you had used puts after the while loop you will realize the problem.
You should use double pointer to character and dynamically allocate 2D array for every lines and keep getting lines by using fgets for every 1D array or use single pointer and copy whole data into single string which is dynamically allocated using fgetc()
After getting data into string, use strstr() with your search strings to count repeatitions of particular keywords and your work is done. Only thing you have to do then is compute percentage for every keyword which is not a tough job.
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *bk;
bk = fopen("brick.c", "r");
char singleLine[1000];
int a= 0;
int totalLines = 0;
int numberofifs = 0;
int blankLine = 0;
int comLines = 0;
int intLines = 0;
int longLines = 0;
int floatLines = 0;
int doubleLines = 0;
int charLines = 0;
int ifLines = 0;
int elseLines = 0;
int forLines = 0;
int switchLines = 0;
int semiLines = 0;
int structLines = 0;
int arrayLines = 0;
int blockLines = 0;
float percentofbl;
float percentofcl;
float percentofint;
float percentoflong;
float percentoffloat;
float percentofdouble;
float percentofchar;
float percentofif;
float percentofelse;
float percentoffor;
float percentofswitch;
float percentofsemi;
float percentofstruct;
float percentofarray;
float percentofblock;
while (!feof(bk)) {
fgets(singleLine, 1000, bk);
totalLines++;
for( a =0; singleLine[a] != '\0'; a++){ // Loops to scan the whole source code//
// scanning blank lines //
if (a == 0 && singleLine[a] == '\n' && singleLine[a+1] == '\0')
blankLine++;
// scanning comment lines //
if ( singleLine[a] == '/' && ( singleLine[a+1] == '/' || singleLine[a+1] == '*'))
comLines++;
// scanning int line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'i' && singleLine[a+2] == 'n' && singleLine[a+3] == 't')
intLines++;
// scanning longs line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'l' && singleLine[a+2] == 'o' && singleLine[a+3] == 'n'
&& singleLine[a+4] == 'g')
longLines++;
// scanning floats line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'f' && singleLine[a+2] == 'l' && singleLine[a+3] == 'o'
&& singleLine[a+4] == 'a' && singleLine[a+5] == 't')
floatLines++;
// scanning doubles line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'd' && singleLine[a+2] == 'o' && singleLine[a+3] == 'u'
&& singleLine[a+4] == 'b' && singleLine[a+5] == 'l' && singleLine[a+5] == 'e')
doubleLines++;
// scanning chars line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'c' && singleLine[a+2] == 'h' && singleLine[a+3] == 'a'
&& singleLine[a+4] == 'r')
charLines++;
// scanning if's line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'i' && singleLine[a+2] == 'f')
ifLines++;
// scanning else's line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'e' && singleLine[a+2] == 'l' && singleLine[a+3] == 's'
&& singleLine[a+4] == 'e')
elseLines++;
// scanning for line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 'f' && singleLine[a+2] == 'o' && singleLine[a+3] == 'r')
forLines++;
// scanning switch line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 's' && singleLine[a+2] == 'w' && singleLine[a+3] == 'i'
&& singleLine[a+4] == 't' && singleLine[a+5] == 'c' && singleLine[a+5] == 'h')
switchLines++;
// scanning semicolons line //
if (singleLine[a] == ';')
semiLines++;
// scanning structs line //
if ((singleLine[a] == ' ' || singleLine[a] == '\t') && singleLine[a+1] == 's' && singleLine[a+2] == 't' && singleLine[a+3] == 'r'
&& singleLine[a+4] == 'u' && singleLine[a+5] == 'c' && singleLine[a+5] == 't')
structLines++;
// scanning arrays [ line //
if (singleLine[a] == '[')
arrayLines++;
// scanning blocks { line //
if (singleLine[a] == '{')
blockLines++;
percentofbl = (float)blankLine/totalLines * 100;
percentofcl = (float)comLines/totalLines * 100;
percentofint = (float)intLines/totalLines * 100;
percentoflong = (float)longLines/totalLines * 100;
percentoffloat = (float)floatLines/totalLines * 100;
percentofdouble = (float)doubleLines/totalLines * 100;
percentofchar = (float)charLines/totalLines * 100;
percentofif = (float)ifLines/totalLines * 100;
percentofelse = (float)elseLines/totalLines * 100;
percentoffor = (float)forLines/totalLines * 100;
percentofswitch = (float)switchLines/totalLines * 100;
percentofsemi = (float)semiLines/totalLines * 100;
percentofstruct = (float)structLines/totalLines * 100;
percentofarray = (float)arrayLines/totalLines * 100;
percentofblock = (float)blockLines/totalLines * 100;
}
}
printf("The total number of lines is %i\n",totalLines);
printf("The total number of blank lines is %i and percentage is %lf \n",blankLine, percentofbl );
printf("The total number of comment lines is %i and percentage is %lf \n", comLines, percentofcl);
printf("The total number of int lines is %i and percentage is %lf \n", intLines, percentofint);
printf("The total number of long lines is %i and percentage is %lf \n", longLines, percentoflong);
printf("The total number of float lines is %i and percentage is %lf \n", floatLines, percentoffloat);
printf("The total number of double lines is %i and percentage is %lf \n", doubleLines, percentofdouble);
printf("The total number of char lines is %i and percentage is %lf \n", charLines, percentofchar);
printf("The total number of if lines is %i and percentage is %lf \n", ifLines, percentofif);
printf("The total number of else lines is %i and percentage is %lf \n", elseLines, percentofelse);
printf("The total number of for lines is %i and percentage is %lf \n", forLines, percentoffor);
printf("The total number of switch lines is %i and percentage is %lf \n", switchLines, percentofswitch);
printf("The total number of semicolon lines is %i and percentage is %lf \n", semiLines, percentofsemi);
printf("The total number of structs lines is %i and percentage is %lf \n", structLines, percentofstruct);
printf("The total number of arrays lines is %i and percentage is %lf \n", arrayLines, percentofarray);
printf("The total number of blocks lines is %i and percentage is %lf \n", blockLines, percentofblock);
fclose(bk);
return 0;
}

How do I find the length of the input string even though i set the size of array

How do I find how many numbers the user inputs if I already set the size to 20
strlen would only get me 20 still
and how would I put it in the else if that's in the for loop
this is a program to check if the 10 digits the user puts in is valid or not
#include<stdio.h>
int validateString(char *inStr);
int main()
{
char stringInput[20];
printf("Please enter a 10 digit phone number: ");
scanf("%s",stringInput);
if (validateString(stringInput)== 1)
{
printf("%s is a valid phone number.\n",stringInput);
}
else if (validateString(stringInput)== 0)
{
printf("%s is not a valid phone number.\n",stringInput);
}
int validateString(char *inStr)
{
int i;
for (i=0;i<length;i++)
{
if(!(inStr[i] == '0' ||
inStr[i] == '1' ||
inStr[i] == '2' ||
inStr[i] == '3' ||
inStr[i] == '4' ||
inStr[i] == '5' ||
inStr[i] == '6' ||
inStr[i] == '7' ||
inStr[i] == '8' ||
inStr[i] == '9' ||
inStr[i] == ' ' ))
{
return 0;
}
else if ( //the input string is longer than 10 or less than 10)
{
return 0;
}
else
{
return 1;
}
}
}
strlen should work fine to get the length (number of digits), you just need to make sure the end of the line is terminated with 0. If the input appends a carriage return or line feed on the end, then just replace those values with 0.
int main ()
{
char x[20];
x[0] = '1';
x[1] = '2';
x[2] = '\n';
x[3] = 0;
printf("%d\n", strlen(x));
}
The above code displays 3.
If I were to replace index 2 with 0, then I would get the correct count of 2.
strlen doesn't give you the total length of an array, it gives you the length of a string terminated with 0.
You also don't need to check for each character, you could do this:
if(!(inStr[i] >= '0' && inStr[i] <= '9') || inStr[1] != ' ')
{
return 0;
}
I would also split out the funcationality a bit:
int validDigits(char *inStr)
{
for (int i=0;i<strlen(inStr);i++)
{
if(!(inStr[i] >= '0' && inStr[i] <= '9') || inStr[1] != ' ')
{
return 0;
}
}
return 1;
}
int validateString(char *inStr)
{
return (validDigits(inStr) && strlen(inStr) == 10);
}
But, remember to replace any carriage return and line feeds (10 and 13) to zero, otherwise strlen will return a higher number than expected.

Resources