While loop quitting only when q is entered twice - c

How do I terminate the while loop without needing the user to enter q twice?
I think I have an input buffer somewhere, but I am not sure where my problem is.
#include <stdio.h>
#include <string.h>
int main(void)
{
int Length, fLength, iLength;
char sObject [25];
printf("Enter object and object length in inches (q to quit); \n");
while (scanf("%24s %d", sObject, &Length) > 1) {
fLength = Length / 12;
iLength = Length % 12;
printf("The length of %s is %d foot %d inches\n", sObject, fLength, iLength);
printf("Enter object and object length in inches (q to quit); \n");
}
return 0;
}
Here is an example of my output.
Enter object and object length in inches (q to quit);
bat 100
The length of bat is 8 foot 4 inches
Enter object and object length in inches (q to quit);
q
q

The first q matches the %24s conversion specification, the second q causes the %d to fail, hence scanf() returns 1 and the loop is exited.
You should read a full line of input at a time, test for the exit command and attempt to convert with sscanf() otherwise
Also note that the split into feet and inches is incorrect: you should compute inches before dividing fLength. Using 2 extra variables is more readable and less error prone.
Here is a corrected version:
#include <stdio.h>
#include <string.h>
int main(void) {
char buf[100];
char object[25];
int length;
for (;;) {
printf("Enter object and object length in inches (q to quit):\n");
if (!fgets(buf, sizeof buf, stdin)) {
/* end of file or read error */
break;
}
if (!strcmp(buf, "q\n")) {
/* user typed q enter */
break;
}
if (sscanf(buf, "%24s %d", object, &length) == 2) {
int feet = length / 12;
int inches = length % 12;
printf("The length of %s is %d foot %d inches\n",
object, feet, inches);
} else {
printf("invalid input: %s\n", buf);
}
}
return 0;
}

If I have understood correctly then rewrite the while statement for example the following way
while (scanf("%24s", sObject) == 1 && strcmp(sObject, "q") != 0 && scanf("%d", &Length) == 1) {

Related

(Visual Studio)Calculation _using for sentence

Want to elicit average of entered real value,until negative value is entered.
My problem is
My calculation don't quit when negative value is entered
It keep asks printf sentence for 3 time.
What did I do wrong?
#include <stdio.h>
int main(void)
{
double total = 0.0;
double input=0.0;
int num = 0;
for (; input >= 0.0;)
{
total += input;
printf("real number(minus to quit):");
scanf_s("%1f", &input);
num++;
}
printf("average:%f \n", total / (num - 1));
return 0;
}
you have many problems with your code :
it's not %1f in the line scanf_s("%1f", &total); as %1f will give you undefined behavior , it's %lfas you are scanning a double , there is a big difference between number one and lower case L
the function called scanf returns an integer indicating how many elements could be assigned to the input that the user entered , so , you should do if(scanf_s("%lf", &input) == 1) to check if the assignment done successfully, that will help you in detecting if - is entered instead of the number
if the user entered a lonely - then sacnf will fail to convert and you have to take another approach
when you are printing the average in this line : printf("average:%f \n", total / (num - 1)); , you actually prints a double , so it's %lf instead of %f
the condition of the for loop is incorrect , you are saying for (; input >= 0.0;) but this will prevent you from entering any negative values as when entering a negative value , the for loop will break , so you could use while(1) instead of the for loop and only break when a - is entered alone
so here is my edited version of yours , I introduced a dummy string to read the buffer and check whether the input was a lonely - or not , and if not then I try to convert it to double and here is my edited solution :
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char dummy[30];
double total = 0.0;
int num = 0;
double DecimalConverted = 0;
while(1)
{
printf("real number(minus to quit):");
fgets(dummy, 30, stdin); // gets the input into the buffer
if(dummy[0] == '-' && dummy[1] == '\n') // break from the loop on condition that '-' only entered
break;
// convert the string to decimal
DecimalConverted = strtod(dummy ,NULL);
if(DecimalConverted == 0)
printf("not a number\n");
else{
total += DecimalConverted;
num++;
}
}
printf("average:%lf \n", total / (num - 1));
return 0;
}
and here is the output :
real number(minus to quit):12
real number(minus to quit):-51
real number(minus to quit):-
average:-39.000000

While loop loops infinitely when checking if variable is a digit

I'm pretty new to programming so answer to this one might be simple but i can't find it. When checking wether the variable is over 1000 or under 1 the program works but whenever i input a letter the program just loops infinitely. Anyways here's the code and thanks for your help:
printf("Player 1 enter A number between 1 and 1000: ");
scanf("%d", &num);
while(num<1 || num>1000 || !isdigit(num)){
printf("please enter different number: ");
scanf("%d", &num);
}
scanf is a poor choice for reading input from the user.
You probably want this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
// Get a number from the user
// number: pointer to the number
// return value: 1 if the user has typed a number
// 0 if the user ha not typed a number
int GetNumber(int *number)
{
char inputbuffer[20];
fgets(inputbuffer, sizeof inputbuffer, stdin); // read raw line from user
if (!isdigit(inputbuffer[0])) // if first char isn't a digit
return 0; // it's not a number, return 0
*number = strtol(inputbuffer, NULL, 10); // convert to number
return 1;
}
int main()
{
int num;
printf("Player 1 enter A number between 1 and 1000: ");
while (!GetNumber(&num) || num < 1 || num > 1000) {
printf("please enter different number: ");
}
printf("number = %d\n", num);
return 0;
}
Alternative version of GetNumber:
int GetNumber(int *number)
{
char inputbuffer[20];
fgets(inputbuffer, sizeof inputbuffer, stdin);
char *endptr;
*number = strtol(inputbuffer, &endptr, 10);
if (*endptr != '\n') // if user input ends with somethign else than
return 0; // \n it's not a number (e.g: "123a")
return 1;
}

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

Getting an Array from user? C programming

My console keeps on crashing after entering a few numbers. I am trying to get an array of 10 numbers from the user thru the console and then taking count of positives, negatives, evens, and odds. What am I doing wrong?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int pos, neg, even, odd;
int nums[10];
printf("Give me 10 numbers: ");
pos = neg = even = odd = 0;
for(int i = 0; i < 10; i++){
scanf(" %d", nums[i]);
if(nums[i] > 0){
pos++;
if(nums[i] % 2 == 0){
even++;
}
else{
odd++;
}
}
else{
neg++;
}
}
printf("Positives: %d, Negatives: %d, Evens: %d, Odds: %d\n", pos, neg, even, odd);
return 0;
}
In your code,
scanf(" %d", nums[i]);
should be
scanf(" %d", &(nums[i]));
or,
scanf(" %d", nums+i);
as you need to pass the pointer to variable as the format specifier's argument in scanf() .
To elaborate, %d expects a pointer to int and what you're supplying is an int variable. it invokes undefined behavior.
That said,
Always check the return value of scanf() to ensure proper scanning.
int main() should be int main(void) to conform to the standard.
Modify scanf like scanf(" %d", &nums[i]);
scanf(" %d", nums[i]);
Scanf expects a pointer to a location to write to, and you're not giving it one.
Change your scanf to:
scanf(" %d", &(nums[i]));
to make your program work.
With this change I tested your program with stdin of
20 10 9 1 39 1 2 2 31 1
And recieved output:
Give me 10 numbers: Positives: 10, Negatives: 0, Evens: 4, Odds: 6
ideone of the thing for your testing purposes.
Change scanf(" %d", nums[i]); to scanf(" %d", &nums[i]);, because scanf() needs addresses. The parentheses around nums[i] isn't necessary, and may effect readability.
Also note that 0 is even, but not negative.
When scanf is usedto convert numbers, it expects a pointer to the corresponding type as argument, in your case int *:
scanf(" %d", &nums[i]);
This should get rid of your crash. scanf has a return value, namely the number of conversions made or the special value EOF to indicate the end of input. Please check it, otherwise you can't be sure that you have read a valid number.
When you look at your code, you'll notice that you don't need an array. Afterreading the number, you don't do aything with the array. You just keep a tally of odd, even and so on numbers. That means you just need a single integer to store the current number. That also extends your program nicely to inputs of any length.
Here's a variant that reads numbers until the end of input is reached (by pressing Ctrl-D or Ctrl-Z) or until a non-number is entered, e.g. "stop":
#include <stdlib.h>
#include <stdio.h>
int main()
{
int count = 0;
int pos = 0;
int neg = 0;
int even = 0;
int odd = 0;
int num;
while (scanf("%d", &num) == 1) {
count++;
if (num > 0) pos++;
if (num < 0) neg++;
if (num % 2 == 0) even++;
if (num % 2 != 0) odd++;
}
printf("%d numbers, of which:\n", count);
printf(" %d positive\n", pos);
printf(" %d negative\n", neg);
printf(" %d even\n", even);
printf(" %d odd\n", odd);
return 0;
}
Change scanf statement after for loop to
scanf(" %d", &nums[i]);

Detection of data type through scanf + usage of it in further functions

So I'm relatively new to C and am trying out some beginner programs. One of which is a program that reads user input from stdin (through usage of scanf).
I'm gonna explain everything step by step for sake of easier comprehension of my intentions (although this part of code is functional/operational and does not require any specific help. So if you wish, you may skip straight to the question below)
So we have a program that reads input from scanf() and decides if it's number or string.
#include <stdio.h>
int isNumber(const char *input){
/* while not end of string */
while (*input != '\0'){
/* if we do not detect a number, return 0 */
if (*input < '0' || '9' < *input)
return 0;
input++;
}
return 1;
}
int main(void){
char uInput[30];
/*Ask user for input */
printf("Please enter number or word \n");
scanf("%29s", uInput);
if (isNumber(uInput)){
printf("We found a number %s \n", uInput);
}
else {
printf("We found a word %s \n", uInput);
}
return 0;
}
So yeah, in the program so works so far. Hopefully everything's clear. Now I know this is not the optimal way of the detection, but that's currently not of concern.
Question begins from here:
Now I've decided to spice things up a little, by adding another function.
To be more specific, it's concerning about prime numbers.
So I've began with the function of
int prime(int number){
int divider;
for (divider = 2; divider <= number - 1; divider++){
if (number%divider == 0)
return 0;
else if (number == divider)
return 1;
}
}
Under presumption everything in my function is correct, I decided to initialize the function in my main() function.
Basically what I want to do:
if the user input is a word - print out the word
if the user input is a number - check if the number is prime and then print out the number and whether it's prime.
So here's how I change up the code:
int main (void){
char uInput[30];
int result;
/*User input goes here*/
printf("Please enter a number or a word \n");
scanf("%29s", uInput);
/* if it contains any numbers do */
if(isNumber(uInput)){
result = prime(uInput);
/* now I've created another if condition, if it is a prime number */
if(result == 1){
printf("It is a prime number: %d \n", uInput);
} else {
printf("It is a number: %d \n", uInput);
}
else {
printf("It is a word %s \n", uInput);
}
return 0;
}
Suspicion: Now I'm 99% sure there is an error in this code (and not just a syntax one). I probably even know where it lies, but due to my lack of knowledge I'm not really sure how to fix it.
So as I was doing the function for the prime number, I wasn't certain if I should make it as a result of string or an integer. Issue is, my program runs through the word as a string and even if it is a number, technically it remains a string under 'illusion that it's a number'.
Issue was, I'm not really sure how would I compare a prime number, that's not an integer but a string. So I've changed %s to %d on my printf. I assume there must be some form of conversion, that I'm not aware of.
But was of no succes. Currently, the word detection works, but when I input for example 2, my output results in
"I input 2 into scanf() through console"
It is a number 2686752
Desired result would be
It is a prime number: 2
(Which also means by deduction, it doesn't even use the first if and skips to else, because if it would have been a prime number the printf for it is different. So there may be something wrong with my "prime" function as well.
So issue is, I can't use scanf(%d, uInput) because otherwise the string detection wouldn't work and clearly my solution is not correct either.
Any suggestions?
First there is a problem in your prime function. Check for (number == divider) is incorrect. You can simply remove the else if part as below.
int prime(int number){
int divider;
for (divider = 2; divider <= number - 1; divider++){
if (number%divider == 0)
return 0;
}
return 1;
}
Next issue is in the way you get a number from uInput. You can use atoi for this as below
if(isNumber(uInput)){
result = prime(atoi(uInput));
/* now I've created another if condition, if it is a prime number */
if(result == 1){
printf("It is a prime number: %s \n", uInput);
} else {
printf("It is a number: %s \n", uInput);
}
else {
printf("It is a word %s \n", uInput);
}
Complete code is as below
#include <stdio.h>
#include <stdlib.h>
int isNumber(const char *input){
/* while not end of string */
while (*input != '\0'){
/* if we do not detect a number, return 0 */
if (*input < '0' || '9' < *input)
return 0;
input++;
}
return 1;
}
int prime(int number){
int divider;
for (divider = 2; divider <= number - 1; divider++){
if (number%divider == 0)
return 0;
}
return 1;
}
int main (void){
char uInput[30];
int result;
/*User input goes here*/
printf("Please enter a number or a word \n");
scanf("%29s", uInput);
/* if it contains any numbers do */
if(isNumber(uInput)){
result = prime(atoi(uInput));
/* now I've created another if condition, if it is a prime number */
if(result == 1){
printf("It is a prime number: %s \n", uInput);
} else {
printf("It is a number: %s \n", uInput);
}
}
else {
printf("It is a word %s \n", uInput);
}
return 0;
}
You can convert a string to a number with atoi or strtol.
In your main, after determining the input is a number, convert it to an int and pass that to prime:
...
/* if it contains any numbers do */
if(isNumber(uInput)){
int iInput = atoi(uInput);
result = prime(iInput);
/* now I've created another if condition, if it is a prime number */
...
Then you can either print the number with %d:
printf("It is a prime number: %d \n", iInput); /* note: iInput */
or with %s:
printf("It is a prime number: %s \n", uInput); /* note: uInput */
You will need to first get the line with fgets, and then scan it with sscanf:
char line[80], word[32];
int num;
if (fgets(line, 79, stdin)) {
if (sscanf(line, "%31s", word) == 1)
printf("%s\n", word); // it's a string
else if (sscanf(line, "%d", &num) == 1) // it's a number
printf("%d: %s\n", num, (isprime(num)) ? "Prime" : "Not Prime");
}
char *isprime(int n)
{
int i;
for (i = 2; i < n - 1; ++i)
if (n % i == 0)
return 0;
return 1;
}

Resources