gets(); function not waiting for input on second loop in C - c

I'm writing a program that simulates purchasing cars. The program works well the first go around, but after the purchase is made and the prompt asks for a name, gets() does not search for input. Here is my code.
#include <stdio.h>
int i;
int j=1;
int prices[5] = { 24000,28000,25000,20000,120000 };
int invent[5] = { 5,2,3,8,2 };
int purchased[5] = { 0, 0, 0, 0, 0 };
int main()
{
char name[50];
printf("Welcome to Buy-a-Car!\nPlease enter your name:\n");
gets(name);
printf("Welcome, %s. Here is our available inventory.\n", name);
sale();
return 0;
}
void sale()
{
while (i>0, j != 0) {
printf("1. Toyota Camry %d %d\n2. Honda CRV %d %d\n3. Honda Accord %d %d\n4. Hyundai Elantra %d %d\n5. Audi R8 %d %d", invent[0], prices[0], invent[1], prices[1], invent[2], prices[2], invent[3], prices[3], invent[4], prices[4]);
printf("\nWhich car would you like to purchase?\n");
scanf("%d", &i);
i = i - 1;
printf("How many would you like to purchase?\n(Note: To checkout, please press 0.)\n");
scanf("%d", &j);
if (j > invent[i])
printf("I'm sorry, that number is insufficient. Please try again.\n");
else
invent[i] = invent[i] - j;
purchased[i] = j;
}
checkout();
}
void checkout()
{
printf("Review of transaction:\n1. Toyota Camry %d %d\n2. Honda CRV %d %d\n3. Honda Accord %d %d\n4. Hyundai Elantra %d %d\n5. Audi R8 %d %d", purchased[0], prices[0], purchased[1], prices[1], purchased[2], prices[2], purchased[3], prices[3], purchased[4], prices[4]);
int total;
for (i = 0; i < 5; i++)
{
total = total + (purchased[i] * prices[i]);
}
printf("\n\nTotal: %d\n\n\n", total);
j = 1;
int purchased[5] = { 0, 0, 0, 0, 0 };
main();
}

It's because the '\n' char in buffer after use scanf, use scanf("%d%*c",&var); %*c prevents '\n' to skip line when gets is used
gets is not safe, use fgets(&str,sizeof(str),stdin);

After running scanf(), the Enter (and anything before) is still in the input buffer. You can clear it like this:
scanf("%*[\n]%*c");
or
while( getchar() != '\n' );
Now gets() won't return an empty string. But anyway, it's extremely discouraged to use it. Use fgets or scanf("%[^\n]") instead.
fgets(name, sizeof(name), stdin);
// or
scanf("%[^\n]", name);
Besides, don't call main() from anywhere in your program. Its behavior is undefined. You can wrap the whole stuff up in another function, and use a loop. An endless recursion call will surely end up blowing up the stack.

Related

Unwanted output on second pass using strcpy

I'm reading a book called "C programming Absolute Beginners Guide."
The following program uses some if loops and strcpy to store some character arrays provided by the user. The first pass of strcpy works fine. The second produces garbage. I understand the array needs a \0 to end. According to the book, strcpy does this automatically. What am I missing?
#include <stdio.h>
#include <string.h>
main()
{
int ctr, numMovies, rating, favRating, leastRating;
char movieName[40], favorite[40], least[40];
favRating = 0;
leastRating = 0;
do {
printf("How many movies have you seen this year? ");
scanf(" %d", &numMovies);
if (numMovies < 1)
{
printf("No movies! How can you rank them?\nTry again\n\n");
}
} while (numMovies < 1 );
for (ctr = 1; ctr <= numMovies; ctr++)
{
printf("\nWhat's the name of the movie? ");
printf("(1-word titles only!) ");
scanf(" %s", movieName);
printf("On a scale of 1 to 10, what would ");
printf("you rate it? ");
scanf(" %d", &rating);
if (rating > favRating)
{
strcpy(favorite, movieName);
favRating = rating;
}
printf("%s", movieName);
if (rating < leastRating)
{
strcpy(least, movieName);
leastRating = rating;
}
}
printf("\nYour Favorite Movie was %s.\n", favorite);
printf("\nYour Least-favorite movie was %s.\n", least);
return 0;
}
Because you initialize leastRating to zero you won't have a least favorite unless the rating is negative. Not sure that's what you want.
The best suggestion is from #xing, add a include
#include <limits.h>
and initialize you best and worst like this;
favRating = INT_MIN;
leastRating = INT_MAX;

Read 2 data string

I have faced a problem with my program and I don't understand why. I read 2 data string and the program just skips the first read and jumps on the second one. I can't place the program here because is pretty big and I don't think anyone wants to waste time reading and understanding it.For example:
struct agenda {
char nume[20];
char prenume[20];
} vector[50];
void adaugare (){
printf("x=");
gets_s(vector[0].nume);
printf("y=");
gets_s(vector[0].prenume);
}
And when I build and run it, it only reads the second string.Edit:
struct agenda {
char nume[20];
char prenume[20];
}vector[50];
void adaugare();
void main() {
adaugare();
_getch();
}
void adaugare() {
int numar;
system("cls");
printf("\n\tCate contacte doriti sa adaugati? ");
scanf_s("%d", &numar);
for (int i = 0; i < numar; i++) {
printf("\nIntroduceti contactul %d\n", i);
printf("\tIntroduceti numele contactului %d: ", i);
gets_s(vector[i].nume);
printf("\tIntroduceti prenumele contactului %d: ", i);
gets_s(vector[i].prenume);
}
}
So in this case if you build and run it, it only reads the second string.
First thing you should elaborate what is gets_s() ? Is it your implementation of gets() or typo ? Instead of gets_s use fgets() to avoid buffering problem as mentioned in comments by #user3121023
// gets_s(vector[0].nume);
fgets(vector[0].nume,sizeof(vector[0].nume),stdin);
printf("y=");
// gets_s(vector[0].prenume);
fgets(vector[0].prenume,sizeof(vector[0].prenume),stdin);
EDIT(for visual c++) :
void adaugare() {
int numar;
system("cls");
printf("\n\tCate contacte doriti sa adaugati? ");
scanf_s("%d", &numar);
fflush(stdin);
for (int i = 0; i < numar; i++) {
printf("\nIntroduceti contactul %d\n", i);
printf("\tIntroduceti numele contactului %d: \n", i);
fflush(stdin);
gets_s(vector[i].nume);
printf("\tIntroduceti prenumele contactului %d: \n", i);
fflush(stdin);
gets_s(vector[i].prenume);
}
}
Because You must flush the input buffer(stdin) before using gets_s().
I hope it help's.

Double usage of scanf() depends on call order

I wrote a program in C which takes as an input a value and an ordered Array of integers and performs a ternary search to find the value(if it exists) inside the Array.
I have seen all the possible problems with the usage of scanf and the related topics here in Stackoverflow.
I have noticed that there is a difference if I call the 2 scanf functions in reverse order.
If I use the code as it is below. First read the value and after the array from the user, the program and scanf functions as expected.
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
Although if I use the scanf inputs in the reverse order the second scanf never stops to get user input and read values left in the buffer.
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
I cannot understand what is the difference in the calling order.
I have tried the solutions mentioned in the other threads but none worked.
Just as a reference here is the whole code(working as expected):
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int ternarySearch(int A[], int l, int r, int k){
int i;
int first,second;
if(l>r){
return -1;
}
i= (r - l)/3;
if(i==0){
i++;
}
first = i+l-1;
second = i*2+l-1;
if(A[first]==k){
return first;
}
else if(A[first]>k){
ternarySearch(A, l, first-1, k);
}
else
{
if(A[second]==k)
return second;
else
if(A[second]>k)
ternarySearch(A, first+1,second-1, k);
else
ternarySearch(A, second+1,r, k);
}
}
int main(){
const int maxarraylen = 1000;
int i;
int n;
int A[maxarraylen];
char string[250];
printf("Enter the value to be searched in the Array: ");
int k;
scanf(" %d", &k);
printf("Type elements of A(sorted) separated by spaces (type 'end' to stop): ");
i = 0;
while(scanf("%d", &A[i]) == 1) {
i++;
}//while
n=i-1;
//We assume the array is sorted otherwise we can use any sorting algorithm e.g. code from task1
scanf(" %d", &k);
int result;
result=ternarySearch(A, 0, n, k);
if(result==-1){
printf("The value was not found in the Array.\n");
}
else{
printf("The value was found in position no. %d.\n", result);
}
return 0;
}
Your problem is that you are not 'stepping over' your end input.
We can see this by doing an experiment using the following program:
#include <stdio.h>
#include <stdlib.h>
void main(void) {
FILE *f;
long f_pos;
int ret;
int i;
int data[5];
int data_last;
int search;
f = fopen("./input.txt", "r");
if (f == NULL) {
perror("fopen()");
return;
}
/* read in the values for the array */
data_last = -1;
for (i = 0; i < 5; i++) {
ret = fscanf(f, "%d", &(data[i]));
printf("fscanf(data[%d]): ret: %d\n", i, ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
if (ret != 1) {
break;
}
data_last = i;
}
/* check that we read in at least one value */
if (data_last == -1) {
printf("no input data!\n");
return;
}
/* insert 'fix' here */
/* pre-load the 'search' with known garbage */
search = 987;
/* now read in the search value */
ret = fscanf(f, "%d", &search);
printf("fscanf(search): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);
/* print out our info */
for (i = 0; i <= data_last; i++) {
printf("data[%d]: %d\n", i, data[i]);
}
printf("search for: %d\n", search);
return;
}
With the following data in input.txt:
123
456
end
456
The output is as follows:
fscanf(data[0]): ret: 1
ftell(): 3
fscanf(data[1]): ret: 1
ftell(): 7
fscanf(data[2]): ret: 0
ftell(): 8
fscanf(search): ret: 0
ftell(): 8
data[0]: 123
data[1]: 456
search for: 987
ftell() tells us where the file's cursor is, and in this case we can see that it is at byte 8... the e of the input line end.
It doesn't get past it, and thus the next attempt to read a number (%d) will fail too!
It's also a good idea to check the return values! We can see that the fscanf(&search) call has failed to read a number!
The solution is to insert this snippet just after we check that we recieved array values:
/* this is the 'fix' */
ret = fscanf(f, "end");
printf("fscanf(end): ret: %d\n", ret);
f_pos = ftell(f);
printf("ftell(): %ld\n", f_pos);

Why do I get random garbage values in this simple program?

I want to read some number from the terminal and print them afterwards.
However, they all seem to be some kind of random value instead of the one I supplied.
Why doesn't my input get saved correctly?
int main (void)
{
int i = 0 , numeros[21] , cont = 1, z = 0;
puts("\n === Bienvenido ===\n");
puts("\n === Vamos a procesadar un numero de serie de 20 digitos [Numericos] ===\n");
puts("\n === Dime los numeros ===\n");
while (cont != 20 )
{
fflush(stdin);
scanf("%d", &numeros[i]);
printf("\n === Dime otro numero. Numeros: %d ===\n", cont);
cont++;
}
for (z = 0; z < 20; z++)
{
printf("\nLos numeros son: %d\n", numeros[z]);
}
system("pause");
}
Ok, a couple of issues:
numeros is declared as an array of 21 ints, but you're using it as if it were numeros[20]
Undefined behaviour because you're calling fflush on stdin
scanf("%d", &numeros[i]), though unsafe, is all fine and dandy, but i is never incremented
Check return values of functions... always: scanf returns the number of values it scanned, if it returns 0, no %d was scanned, and numeros[i] needs to be reassigned.
Here's an example of how I'd write your program:
#include <stdio.h>
#include <stdlib.h>
int main ( void )
{
int c,i=0,
numbers[20],
count=0;
//puts adds new line
puts("enter 20 numbers");
while(count < 20)
{
c = scanf(" %d", &numbers[i]);//note the format: "<space>%d"
if (c)
{//c is 1 if a number was read
++i;//increment i,
++count;//and increment count
}
//clear stdin, any trailing chars should be ignored
while ((c = getc(stdin)) != '\n' && c != EOF)
;
}
for (i=0;i<count;++i)
printf("Number %d: %d\n", i+1, numbers[i]);
return 0;
}
You are not incrementing i in the first loop.
You are incrementing cont, but using numeros[i] to store your input. As i never changes, you only write to the first array element. Change the i to cont, as in
scanf("%d", &numeros[cont]);
What exactly do you want to achieve? I see that you're putting into i=0 index of your numeros array number from stdin. Then you're iterating trough this array, but you've just entered one number! You should propbably change the subsctript of your numeros array to cont like that:
scanf("%d", &numeros[cont]);
scanf("%d", &numeros[i]);
should be replaced with
scanf("%d", &numeros[cont]);
AS you are incrementing cont not i

Can't nail the problems with this code

Ok so I got this thing going here.
I keep getting a few errors.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <cstdio>
//functions called
int get_lmt();
int get_total_trash();
void print_output(int, int);
//why is it void?
int main(void)
{
char hauler[100];
int t_trash=0, lmt=0;
printf("Hello \n What is your name: ");
fflush(stdin);
scanf("%s", &hauler);
t_trash = get_total_trash();
lmt = get_lmt();
printf("Name: %s\n", &hauler);
print_output(lmt, t_trash);
system("pause");
return 0;
}
int get_total_trash()
{
char yn = 'y';
int t_trash = 0, trash=0;
while (yn != 'n')
{
printf("What is your trash: ");
fflush(stdin);
scanf("%i", &trash);
t_trash = trash + t_trash;
printf("Do you have more trash tons? (y or n): ");
fflush(stdin);
scanf("%c", &yn);
}
return t_trash;
}
int get_lmt()
{
int lmt = 0;
printf("What was last months trash: ");
fflush(stdin);
scanf("%i", &lmt);
return lmt;
}
void print_output(int lmt, int t_trash)
{
float rate = 350.00, charge;
int sum=0, total=0;
if (lmt > t_trash)
{
printf("Total trash tons: %i\n", &t_trash);
printf("Last month's trash: %i\n", &lmt);
printf("Rate: $ %.2f\n", &rate);
}
else
{
printf("What is your tonnage rate: ");
fflush(stdin);
scanf("%.2f\n", &charge);
sum = t_trash - lmt;
total = sum * charge;
rate = rate + total;
printf("Total trash tons: %i\n", &t_trash);
printf("Last month's trash: %i\n", &lmt);
printf("Rate: $ %.2f\n", &rate);
}
}
Now what it should be doing is, The main should be calling the functions on screen as needed.
Now i did all of this with cout cin and it works fine no problems. But when I run this (this is modified to the printf and scanf) it says:
OK UPDATE: Got a ton of it to work. Just one more thing and I should be good. The outcome will not go as expected.
Instead of an output of
last months trash: 100 (asked at the end of the loop)
trash tonnage: 50 (accumulated in the loop)
rate: 350.00 (float variable)
(this is if last month trash was > this month.)
I get just bad numbers all around. It makes no mathematical sense.
Other then that it works fine.
Does the code the the last function look wrong to you guys?
Lots of problems with this code. Lots of them.
1) print_output defintiion takes in a char[100] (char*), print_output declatation takes a char
2) When you pass hauler into print_output, you are passing in hauler[100] (a char, and one pass the end of the array to boot)
3) printf("Name: %s\n", &hauler); hauler is of type char[100] (char*), so &hauler is char**.
there is probably more.

Resources