skipping over scanf loops in c - c

I don't know why, when I run this, it skips the "how many pages in the book" scanf and goes straight onto the second loop "who is the author".
I'm sure this is something to do with whitespace, but I thought I accounted for this with the getchar at the bottom of the for loop.
header:
struct bookInfo{
char title[40];
char author[25];
float price;
int pages;
};
.c file:
int main()
{
int ctr;
struct bookInfo books[3];
for (ctr = 0; ctr < 3; ctr++)
{
printf("what is the name of the book #%d?\n", (ctr+1));
gets(books[ctr].title);
puts("who is the author?");
gets(books[ctr].author);
puts("how much did the books cost");
scanf(" $%f", &books[ctr].price);
puts("how many pages in the book");
scanf(" %d", &books[ctr].pages);
getchar();
}
printf("here is the collection of books: \n");
for (ctr = 0; ctr <3; ctr++)
{
printf("book #%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
printf("\nit is %d pages and costs $%.2f", books[ctr].pages, books[ctr].price);
}
return 0;
}

Change this:
puts("how much did the books cost");
scanf(" $%f", &books[ctr].price);
to this:
printf("how much did the books cost: $");
fflush( stdout );
scanf("%f", &books[ctr].price);
Unless you intend for your user to type a $ before the price, which would be annoying. You don't need the leading blank in the format string, since %f tells scanf to skip over leading whitespace.
Secondly, NEVER NEVER NEVER NEVER NEVER NEVER NEVER NEVER use gets. Ever. In any way, shape, or form. It will (not might, will) introduce a point of failure / major security hole in your program. It was deprecated in the 1999 standard, and has been removed from the standard library as of the 2011 standard. It is the programming equivalent of splicing live wires while standing in a shower.
Use fgets (which, unlike gets, will attempt to store the newline character in the target buffer if there's room) or scanf (with an appropriate precision in the conversion specifier) instead.

That is because gets() reads the line of text present in the current buffer. and since the current buffer contains "What is name of author ?" it reads it.
If you display the contents of the struct members you can clearly observe this.
So I Suggest this
Use
char *temp;
fgets(STDIN,temp);
before Loop begins.
This helps you

Related

After getting user inputs the last printf() is not printing at all

Struggling on my homework assignment.
After I give inputs it stops rather than doing the random array and last print if anyone can help I would appreciate it
#include <stdio.h>
#include <stdlib.h>
int main() {
char name, color;
int age;
int *poer = &age;
char *p = &name;
char *ptr = &color;
printf("What is your name?\n");
scanf(" %s", &name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", &color);
char *story[5] = {"old volkswagen beetle", "singlet", "quater", "left sock",
"blackberry bold ninek"};
srand(time(0));
printf("My pal right here %s is %d years old I feel like we have been coding"
" together for a hundred years now I always wonder where the time has gone"
" One thing I have wanted to know is why they love "
"their %s %s so much I guess I might never know\n",
name, age, color, story[rand() % 5]);
return 0;
}
Plenty of errors can be caught by enabling the compiler warnings.
Here is the list of all problems with their proper solutions:
For this line:
srand(time(0));
You need to include the time.h library, otherwise, you will get an implicit definition of time() error message. Passing NULL to time() is a good practice.
As people figured out:
char name, color;
A single char-type cannot hold more than a single ASCII character. Thus, you need to formulate a sequence of characters, called character array. In C99, variable-length arrays are supported. Still, using a macro constant for defining string lengths during compile-time makes the code good. Replace it:
#define MAX_LENGTH 128 // Prefer your length
...
char name[MAX_LENGTH], color[MAX_LENGTH];
In the similar lines:
printf("What is your name?\n");
scanf(" %s", &name);
scanf() function stops reading further input after whitespace. For example, if you input: John Doe, the name will only store John, Doe becomes truncated. Also, never put an ampersand sign for a char-array in scanf().
fgets() is considered safer than this, since it accepts a limited number of characters defined in its second argument. Replace the scanf():
// ... , sizeof name, ... --- is also applicable here
if (fgets(name, MAX_LENGTH, stdin) == NULL) {
// Do something when input's invalid
}
// Input is okay
Note: The fgets() leaves a trailing newline character as soon as it stops receiving user input. To discard this, use this after its usage:
name[strcspn(name, "\n")] = 0;
After applying all these changes, you will not get any further problems.
the following code will be fine
char name[256];
char color[256];
int age;
printf("What is your name?\n");
scanf(" %s", name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", color);
in your code, a char was casted to char* the variable will hold data larger than it could. the the stack was ruined
You used char for string which is wrong. You need a char array to store the strings.
Try this:
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define STR_MAX 300
int main()
{
char name[STR_MAX];
char color[STR_MAX];
int age;
printf("What is your name?\n");
scanf(" %s", name);
printf("How old are you??\n");
scanf(" %d", &age);
printf("What is your favorite color?\n");
scanf(" %s", color);
char *story[5] = {"old volkswagen beetle","singlet","quater","left sock","blackberry bold ninek"};
srand(time(0));
printf("My pal right here %s is %d years old I feel like we have been coding together for a hundred years now I always wonder where the time has gone One thing I have wanted to know is why they love their %s %s so much I guess I might never know\n",name, age, color, story[rand()%5]);
return 0;
}
your program terminated abnormally because stack was ruined.
char name; //has only 1 byte space
char color; //has only 1 byte space
but these two variables was used to hold data larger than they can. then data was written to some place else which will cause the stack overflow.
code like this will be ok
char name[256];
char color[256];

User Input being skipped

still making my way through C Programming Absolute Beginner's Guide.
I am at the example about Structures and I cannot figure out what is going wrong. When I compile and run the code, the first two questions run fine, but after it prompts for "How much did the book cost?", when I enter the input for this one, the next two questions get posted together. I have no idea why. I think I have the code written as shown in the book. I have read online that gets is not code but I am not sure why at this point. Any guidance would once again be greatly appreciated!
//This header file defines a structure for information about a book
struct bookInfo {
char title[40];
char author[25];
float price;
int pages;
};
/*This program gets the bookInfo structure by including structurePractice.h
and asks the user to fill in three structures and then prints them*/
//First, include the header file
#include "structurePractice.h"
#include <stdio.h>
int main()
{
int ctr;
struct bookInfo books[3]; //Array of 3 structure variables
//Get information about each book from the user
for (ctr = 0; ctr < 3; ctr++)
{
printf("What is the name of the book #%d?\n", (ctr+1));
gets(books[ctr].title);
puts("Who's is the author? ");
gets(books[ctr].author);
puts("How much did the book cost? ");
scanf(" $%f", &books[ctr].price);
puts("How many pages are in the book? ");
scanf(" %d", &books[ctr].pages);
getchar(); //Clears last newline for next loop
}
//Print a header line and then loop through and print the info
printf("\n\nHere is the collection of books: \n");
for (ctr = 0; ctr < 3; ctr++)
{
printf("#%d: %s by %s", (ctr+1), books[ctr].title, books[ctr].author);
printf("\nIt is %d pages and costs $%.2f", books[ctr].pages, books[ctr].price);
printf("\n\n");
}
return (0);
}
You have a typo in your scanf.
scanf(" $%f", &books[ctr].price);
^
|
here
That says you want a $ followed by a decimal number. If the user does not input a dollar sign, scanf will read nothing. The input will remain on the input buffer. It will be read by the next scanf.
This is one of the many problems with scanf. Because scanf mixes up reading input with parsing input, if the input does not match the expected format it will remain in the input buffer. Instead, read and parse separately with fgets (not gets) and sscanf. It's also important to check that the input was read else books[ctr].price will contain garbage.
// Declare a buffer once outside the loop. Reuse it for each fgets call.
// BUFSIZ is a constant for the natural I/O buffer size of your platform.
char buf[BUFSIZ];
puts("How much did the book cost? ");
// Read only as much as the buffer can handle. This is what makes fgets safe,
// and gets unsafe.
fgets(buf, sizeof(buf), stdin);
// sscanf returns the number of items matched. Check if they all matched.
if( sscanf(buf, " %f", &books[ctr].price) != 1) {
printf("Sorry, '%s' doesn't look like a price.", buf);
// Set it to something or else it will be garbage.
books[ctr].price = 0;
}
A real program would loop until it gets valid input. The important thing is to read the buffer, then parse it, and check if the parsing worked. Later on you might write a little function to package up this prompting code.

How to get rid of a white space line in C?

I'm a beginner and just learning structures in C, but I encountered a small problem. This is the code:
struct Phone{
char name[50];
double screensize;
int memory;
int camera;
};
int main(){
struct Phone phone1;
printf("What model do you have? ");
fgets(phone1.name,50, stdin);
printf("How many MP does the camera have? ");
scanf(" %d", &phone1.camera);
printf("How much memory does you phone have? ");
scanf(" %d", &phone1.memory);
printf("You entered you have: \n");
printf("Model: %s \nCamera: %d \nMemory: %d", phone1.name, phone1.camera, phone1.memory);
}
It doesn't have any errors but, when I run it and input my stuff, the last printf from the code will display the model name, a line of white space, and then the camera and memory on consecutive rows. I want to get rid of that line of white space. I tried to leave a white space in scanf before all %d in order to discard that line, but it doesn't work (I've read that scanf reads the newline when you input something first and, to prevent that, we just need to add a space to flush the buffer first).
Here you input a line from console:
printf("What model do you have? ");
fgets(phone1.name,50, stdin);
it captures also a '\n' character, and then you print:
printf("Model: %s \nCamera: %d \nMemory: %d", phone1.name, phone1.camera, phone1.memory);
// ^ ^ there you print that '\n' in phone1.name and second hardcoded

Using scanf to store string in a structure

I've written a function that stores information on books to a struct Book and everything is working fine except for when the book title has any white spaces. So something like Dracula will be stored and displayed just fine, but something like Lord of the Rings will just skip scanning for the rest of the book's information and proceed to close the program. Is there any way to use scanf to register the string with the white spaces? Here's my code:
void addBook(struct Book book[], int *size)
{
if(*size== MAX_BOOKS) {
printf("the inventory is full.\n");
}
else {
printf("ISBN\n");
scanf("%d", &book[*size]._isbn);
printf("Title\n");
scanf("%s", book[*size]._title);
printf("Price\n");
scanf("%f", &book[*size]._price);
printf("Year\n");
scanf("%d", &book[*size]._year);
printf("Qty\n");
scanf("%d", &book[*size]._qty);
printf("Book successfully added to inventory\n");
(*size)++;
}
}
I can update with the full code if necessary.
No problem. That's because %s stops at the first space. Use %[^\n] so it reads until he find the enter.

How to use int in array?

i create a really simple coding and it got no errors but when it run, i cant put input in the 'age' side.
#include <stdio.h>
#include <conio.h>
struct baby
{
char name[2][30];
char sex[2][7];
char birthday[2][12];
};
struct parents
{
char nama[2][30];
int age[2];
};
struct momdad
{
struct parents father;
struct parents mother;
};
struct momdad info;
struct baby newborn;
int main()
{
int i;
for(i=0;i<2;i++)
{
printf("\nEnter baby's name %d: ",i+1);
gets(newborn.name[i]);
printf("Enter baby's sex %d (Female/Male): ",i+1);
gets(newborn.sex[i]);
printf("Enter baby's birthday %d (dd/mm/yyyy): ",i+1);
gets(newborn.birthday[i]);
printf("Enter father's name %d: ",i+1);
gets(info.father.nama[i]);
printf("Enter father's age %d: ",i+1);
gets(info.father.age[i]);
printf("Enter mother's name %d: ",i+1);
gets(info.mother.nama[i]);
printf("Enter mother's age %d: ",i+1);
gets(info.mother.age[i]);
}
printf("\n\n\tNEW BORN BABY IN KUANTAN HOSPITAL");
printf("\n\n===============================================");
for(i=0;i<2;i++)
{
printf("\n\nBaby name: %s",newborn.name[i]);
printf("\nSex: %s",newborn.sex[i]);
printf("\nBirthday: %s",newborn.birthday[i]);
printf("\n\nFather name: %s",info.father.nama[i]);
printf("\nFather age: %s",info.father.age[i]);
printf("\n\nMother name: %s",info.mother.nama[i]);
printf("\nMother age: %s",info.mother.age[i]);
printf("\n\n----------------------------------------------");
}
getch();
}
this is my declaration that i think is wrong but i dont know how.
int age[2];
and the input will be putting in here
printf("Enter father's age %d: ",i+1);
gets(info.father.age[i]);
n in here
printf("Enter mother's age %d: ",i+1);
gets(info.mother.age[i]);
i'm still new in programming sorry for asking this simple question
Never use gets(). It cannot be used safely, and as of 2011 it's been removed from the language.
In a comment, you mention calling fflush(stdin);. The behavior of fflush is undefined for input streams. Some implementations define the behavior, but depending on that will make your program non-portable -- and you don't need it anyway.
The simplest way to read input data is to use scanf(), but that has some of its own problems. For example, if you use scanf("%d", &n); and type 123, it will consume the 123 and leave anything following it (such as a newline) waiting to be read.
A better way to read input is to use fgets to read a line of text, then sscanf to parse the data from the input line. It re
Here's an example:
#define MAX_LEN 200
char line[MAX_LEN];
int num;
printf("Enter an integer: ");
fflush(stdout);
if (fgets(line, MAX_LEN, stdin) == NULL) {
fprintf(stderr, "Error reading line\n");
exit(EXIT_FAILURE);
}
if (sscanf(line, "%d", &num) != 1) {
fprintf(stderr, "Error parsing integer from line\n");
exit(EXIT_FAILURE);
}
printf("The number is %d\n", num);
I call fflush(stdout) after the first printf to ensure that the prompt actually appears. stdout can be line-buffered, meaning that output won't appear until you've printed an entire line. The fflush isn't always necessary, but it's a good idea.
The fgets call reads a full line of input or MAX_LEN characters if the line is longer than that. (gets has no way to specify the maximum input size, so no matter how big your target array is, it can always read more and clobber random memory.) fgets returns a null pointer if there was a problem, and I check for that.
sscanf is similar to scanf, but it reads data from a string in memory, not from standard input. (There's also fscanf, which reads from a specified file.) It returns the number of items that it successfully scanned, so a value other than 1 would indicate an error.
I suggest reading the documentation for all these functions; I haven't covered everything they do. In fact, you should read the documentation for any standard library function you use.

Resources