fgets() not behaving as intended , kind of "spills" into a following fgets() - c

this program lets the user enter a string and then asks what to do ( have deleted the parts that actually do stuff to make everything lighter and the problem easier to spot). The problem is that whenever a string longer than 256 characters is entered, it kinda "spills" into the following fgets(), which in turn prints "insert a valid input".
here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>
#include <string.h>
int main(void) {
printf("your string:\n");
char stringa[257];
fgets(stringa, 257, stdin);
for (int i = 0; stringa[i]; i++) {
stringa[i] = tolower(stringa[i]);
}
char stringakek[257];
int j= 0;
for (int i = 0; stringa[i]; i++) {
if (stringa[i] >= 'a' && stringa[i] <= 'z' && stringa[i] != '\0') {
stringakek[j] = stringa[i];
j++;
}
}
printf("this is your string all in lowercase and containing only letters: %s\n", stringakek);
printf("what do you want to do?\n");
printf("press 1 for case 1\n");
printf("press 2 for case 2\n");
printf("press 3 for case 3\n");
int controllo = 0;
char a[300000];
while (controllo == 0) {
fgets(a, 300000, stdin);
switch(a[0]) {
case '1':
printf("case 1\n");
controllo = 1;
break;
case '2':
printf("case 2\n");
controllo = 1;
break;
case '3':
printf("case 3\n");
controllo = 1;
break;
default:
printf("insert a valid input\n");
break;
}
}
}
For example if something like
*R3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-re*
was input the expected output would be:
*your string:
R3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-re
this is your string all in lowercase and containing only letters: rhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhq
what do you want to do?
press 1 for case 1
press 2 for case 2
press 3 for case 3*
but it actually outputs this:
*your string:
R3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-reR3HQ53BAQ5I4GAERÈ+ÒÈGA43IOHAUNVKANE124RÈ+fioureahjkgaeu+-re
this is your string all in lowercase and containing only letters: rhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhqbaqigaergaiohaunvkanerfioureahjkgaeurerhq
what do you want to do?
press 1 for case 1
press 2 for case 2
press 3 for case 3
**insert a valid input***
Why is this? How can I fix this?

Related

Trying to find duplicates in a Struct Array in C

I've attempted to find if the user has inputted a product id value that's a duplicate and if so, it just tells them that it's a duplicate value and then returns to the menu in my switch statement.
The actual result i get, is that after "productsfilled == 0", it won't utilise the For Loops to check for the duplicates and productsfilled will remain at 1. I've looked online and this way of finding duplicates tends to work and i have used it previously in my code, so I don't think that could be the issue.
Here's my code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <conio.h>
int productsfilled;
struct ProductData{
int product_id;
char product_name[120];
int price;
};
int quiz_5(){
char ch;
int size, input = 0;
struct ProductData products[20];
while(1){
printf("\nWelcome To The Super Mall's Product List. Please Select An Option:\n1. Add Product\n2. Display Product\n3. Delete Product\n");
fflush(stdin);
switch(getchar()){
case '1':
printf("\nPlease Enter Product ID:");
scanf("%d",&products[productsfilled].product_id);
printf("\nPlease Enter Product Name:");
scanf("%s",&products[productsfilled].product_name);
printf("\nPlease Enter Product Price:");
scanf("%d",&products[productsfilled].price);
printf("Productsfilled: %d",productsfilled);
if(productsfilled == 0){
productsfilled = 1;
break;
}
for(int i = 0; i < productsfilled;i++){
for (int j = i + 1; j < productsfilled;j++){
if(products[i].product_id == products[j].product_id){
printf("\nPlease Use Different Product ID");
break;
}else{
printf("test");
productsfilled += 1;
break;
}
}
}
break;
case '2':
while(1){
for(int i = 0;i < productsfilled;i++){
printf("Product ID: %d Product Name: %s Product Price: %d\n",products[i].product_id,products[i].product_name,products[i].price);
}
printf("Please Press Enter To Continue");
fflush(stdin);
if(getchar() == '\n'){
break;
}
}
case '3':
break;
case '\n':
break;
default:
printf("Please Select An Option:\n1. Add Product\n2. Display Product\n3. Delete Product: ");
}
}
}
int main() {
int input = 1;
printf("Welcome to my assignment. Which quiz do you want to run (please input the number of the quiz e.g. for quiz 1, type 1): \n-Quiz 1\n-Quiz 2\n-Quiz 3\n-Quiz 4\n-Quiz 5\n-Quiz 6\n-Quiz 7\n");
while(input == 1){
fflush(stdin);
switch(getchar()){
case '5':
quiz_5();
break;
case '\n':
printf("Welcome to my assignment. Which quiz do you want to run (please input the number of the quiz e.g. for quiz 1, type 1): \n-Quiz 1\n-Quiz 2\n-Quiz 3\n-Quiz 4\n-Quiz 5\n-Quiz 6\n-Quiz 7\n");
getchar();
default:
printf("Invalid Input\n");
} }
return 0;
}
The problem is that you don't increment productsfilled before you enter the loop...therefore, productsfilled is always 1 less than the actual length of your array which means that you don't compare all elements in the array.
Try your program on 2 inputs, both with the same ID. You'll see that you don't compare anything.
You are wrong when using scanf for string input:
scanf("%s",&products[productsfilled].product_name);
You should not use &, you should use as below:
scanf("%119s",products[productsfilled].product_name);
OT, in main function:
switch(getchar()){
case '5':
...
Because getchar() will return int value, so if you want to access to quiz_5, you have to type 35 (ANSCI code) instead of type 5 when you run your program.
char a = '5';
similar to:
int a = 35;

Find a char that equals an input

In the code below I take the input from the user and then I find the digit that was introduced by comparing it to every other digit.
This my code:
#include <stdio.h>
#include <stdlib.h>
int main(){
int i = 0;
int input;
printf("Input a digit: \n");
scanf("%d", &input);
for(; i < 10; i++)
{
if(i == input)
{
printf("Your input is %d\n", i);
break;
}
}
return 0;
}
How do I check for a letter instead? Say the user inputs letter G, and I take that in a loop to compare it to every other character until I find the one it equals to?
You can use pretty much the same code you already have, just scan for a char:
char input;
scanf("%c", &input);
To check the input, use what fits your expectations best. A switch is probably a solid choice:
switch (input) {
case 'G':
printf("G was received\n");
break;
default:
printf("Uninteresting character %c was received\n", input);
}

Double while loop for flushing data before a switch statement

I need to write a script for the user to enter a score between 0 and 10, flush the bad input out, if user inputs it and then using a switch statement, tell a user what grade did he/she got.
Here is my script:
...
int main()
{
int input; // input from user
printf("Enter the number between 0 and 10 and I will tell you your grade!");
while ((input=scanf("Your input:", &input) != EOF))
{
if (input < 0 || input > 10) //input is invalid
{
printf("Sorry, invalid character data.");
while (getchar() !='\n')
{
printf("Your input must be from 0 to 10.", input);
scanf("%d", &input); //This part looks very bad for me
}
}
else
switch (input)
{
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Your grade is F. \n");
break;
case 6:
printf("Your grade is D. \n");
break;
...
I got this far with my homework, and here are some "leftover" problems I can't fight with.
1) Whenever user submits anything after enter, it goes into infinite loop and prints Your grade is F., even when case = 6 for example.
2) I used break; at the end of each case. It looks like they don't work(?)
3) It looks like the problem in the second line in the second loop
scanf("%d", &input); //This part looks very bad for me
but then I guess the scripts accepts it as true since the else statements that includes switch begins to work, because otherwise it wouldn't print Your grade is F.
Try the following code. Have a look at what flush_stream is doing when we have invalid data...
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
void flush_stream();
void flush_stream() {
char c;
do {
c = getchar();
}
while (!isdigit(c) && c != '\n');
ungetc(c, stdin);
}
int main(void) {
const char *prompt = "Input please: ";
int input; // input from user
printf("Enter the number between 0 and 10 and I will tell you your grade!\n");
while(1) {
printf("%s", prompt);
int ret = scanf("%d", &input);
if(ret == 0) {
printf("Sorry, invalid character data, your input must be from 0 to 10.\n");
flush_stream();
continue;
}
if(ret > 0) {
if (input < 0 || input > 10) {
printf("Sorry, invalid character data, your input must be from 0 to 10.\n");
flush_stream();
continue;
}
switch (input) {
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
printf("Your grade is F. \n");
break;
case 6:
printf("Your grade is D. \n");
break;
}
}
}
}
It seems you are using scanf and printf wrong.
To input a number:
scanf("%d", &input);
To output a number:
printf("%d\n", input);
And in you while loop, when the input is illegal, why not just continue to the next loop?
while (true) {
printf("input your grade here: ");
if (scanf("%d", &input) == EOF) {
break;
}
if (input < 0 || input > 10) {
printf("your input is illegal.\n");
continue;
}
switch (input) {
...
}
}

Can't execute Switch statement inside For Loop more than 10 times - C

i'm currently learning C, and i have an exercise, request for 20 characters and show the amount of ('a','e','i','o','u').
I coded this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
char letter;
int a = 0, e = 0, i = 0, o = 0, u = 0, x;
for(x = 0; x < 20; x++)
{
printf("\nEnter a character: ");
letter = getchar();
letter = tolower(letter);
switch(letter)
{
case 'a':
a += 1;
break;
case 'e':
e += 1;
break;
case 'i':
i += 1;
break;
case 'o':
o += 1;
break;
case 'u':
u += 1;
break;
default:
continue;
}
system("cls");
}
printf("\nAmount of 'a': %d", a);
printf("\nAmount of 'e': %d", e);
printf("\nAmount of 'i': %d", i);
printf("\nAmount of 'o': %d", o);
printf("\nAmount of 'u': %d\n", u);
system("pause");
return 0;
}
But this only can be executed 10 times. Why this happens?
PD. Sorry for my poor english.
As mentioned in the comments, you are processing 20 characters, but half of them are newlines. If you take out your line system("cls") this becomes apparent:
% ./ctest
Enter a character: a
Enter a character:
Enter a character: b
Enter a character:
Enter a character: c
At the first prompt, I typed a<RET> and the first loop iteration (x=0) processed the a but there is still a <RET> waiting in the input buffer. The second loop iteration (x=1) gets the next available character, <RET> and processes it, the the third loop iteration (x=2) prints its prompt and waits for new input.
You can further see how this works by getting it to process 20 characters you are counting. For example, if I provide the input aaaaaeeeeeiiiiiooooo<RET>, which is 21 characters, you can see that the first 20 are processed:
% ./ctest
Enter a character: aaaaaeeeeeiiiiiooooo
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Enter a character:
Amount of 'a': 5
Amount of 'e': 5
Amount of 'i': 5
Amount of 'o': 5
Amount of 'u': 0
To fix this problem you should either read and discard the newline character or use a different method of reading that can ignore the newlines.
You need to ignore newline chars.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main()
{
char letter;
int a = 0, e = 0, i = 0, o = 0, u = 0, x;
for (x = 0; x < 20; x++)
{
printf("\nEnter a character: ");
letter = getchar();
letter = tolower(letter);
if (letter == '\n')
{
x--;
system("cls");
continue;
}
if (letter)
{
switch (letter)
{
case 'a':
a += 1;
break;
case 'e':
e += 1;
break;
case 'i':
i += 1;
break;
case 'o':
o += 1;
break;
case 'u':
u += 1;
break;
default:
break;
}
}
system("cls");
}
printf("\nAmount of 'a': %d", a);
printf("\nAmount of 'e': %d", e);
printf("\nAmount of 'i': %d", i);
printf("\nAmount of 'o': %d", o);
printf("\nAmount of 'u': %d\n", u);
system("pause");
return 0;
}
You can use scanf instead of getchar, it will also solve it.

how to perfect hangman looping issue in the end C language?

the hang man has a problem please identify it??
the letters when typed the code shows 'not found'and the same letter has to be typed twice to get it accepted? and the chances to guess the letter decreases how to fix it?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <ctype.h>
#define WORD_COUNT 3
#define MAX_LENGTH 10
typedef char string[MAX_LENGTH];
void main(void) {
string words[WORD_COUNT] = { "bird","fish","lion","ants","bear","deer","fowl" };
char answer[MAX_LENGTH];
char guess;
int count = -0, index, i, found, choice = -7;
char mysteryWord[MAX_LENGTH];
printf("Welcome to Hangman!\n");
printf("\n\nChoose an option\n"
"1) Easy\n"
"2) Moderate\n"
"3) Hard\n"
"Your choice: ");
scanf("%i", &choice); a biref menu case
switch (choice) {
case 1:
count = 5;
break;
case 2:
count = 2;
break;
case 3:
count = 1;
}
srand(time(NULL));
index = rand() % WORD_COUNT;
strcpy(mysteryWord, words[index]);/*actual comparing */
for (i = 0; i < strlen(mysteryWord); i = i + 1)
{
answer[i] = '-';
}
answer[i] = '\0';
printf("%s \n", answer);
while (1 > 0) {
printf("\n %i guess(es) left\n", count);
printf("Guess a letter:");
scanf("%c\n", &guess);
guess = tolower(guess);
found = 0;
for (i = 0; i < strlen(mysteryWord); i++)
{
if (mysteryWord[i] == guess) {
answer[i] = guess;
found = 1;
}
}
if (found == 0) {
printf("Not found!\n");
--count;
}
if (count == 0) {
printf("Game over\n");
printf("The answer is %s.", mysteryWord);
break;
}
else {
what should be here instead of if(answer==mysteryWord) ?
if (strcmp(answer, mysteryWord) == 0)
{
printf("Yes, it's a %s\n", answer);
break; /* or return */
} else
printf("%s", answer);
}
} end of while loop ?
} end of main ?
Change
scanf("%c\n", &guess);
To
scanf(" %c", &guess);
Note the space before %c. The space discards all blanks like newlines and spaces and the %c will then scan the next non-whitespace character.
In your case,when you input data for any scanf,you enter the data and press the enter key.scanf reads the data entered and leaves the \n(newline character) in the stdin. When you scan a character using %c , scanf reads the \n left out by the previous scanf and thus,does not wait for input.
scanf(" %c", &guess);
Please make sure your scanf() is like above with a space before %c
The purpose of space is it gobbles whitespace and special characters

Resources