I have some simple user input function which reads what the user types, ignoring any enter's and taking the first character it comes across. I am using the cin.ignore statement because this is part of a menu, and I want to replay the menu if they enter none of the given options, but only once. Now I basically want to have an if-statement which is true iff the user entered only one character (he may enter multiple enter's before this character), so I wanted to use something like sizeof or length, but I couldn't quite get it to work. Can anybody help with this? It would be much appreciated. Also, if anything should be changed about the phrasing of the question, please let me know. Thanks in advance.
char Interface::leesin ( ) {
char invoer;
do {
invoer = cin.get();
} while (invoer == '\n');
cin.ignore(MAX,'\n');
return invoer;
}
the following is a code snippet whereby the user will be presented with a console menu and needs to input a character. The cin will read in only 1 char and then the program can do some processing with this char. The loop will terminate, when the user inputs the char '9'.
#include <iostream>
using namespace std;
int main() {
char ch;
do {
//print menu here
cin >> ch; // take in one char only
//perform action based on ch
} while (ch != '9');
return 0;
}
Related
I'm currently learning C programming, and wrote a script similar to one I've written in Python before. My goal is to learn how to pass input to an application and have it process the data I pass it.
The problem I'm having now is the feedback my application is giving me. I wrote a simple application to read keyboard input and give 1 of 3 responses based on what input I give it. The code is as follows:
/*Input test.*/
#include<stdio.h>
#include<stdlib.h>
char input;
const int option_a = 1;
const int option_b = 2;
int main()
{
printf("Lets get started! a for on or b for off?\n");
while(1)
{
input = getchar();
if(input == option_a)
{
printf("We're on.!\n");
}
else if(input == option_b)
{
printf("Off we go.\n");
}
else
{
printf("Excuse me, but I didn't get that.\n");
}
}
return 0;
}
Simply option_a is me pressing the 1 key on keyboard, and option_b is key 2. When I press these keys, or any key for that matter, the application will always go to the "else" portion of the decision tree. Saying that, it's clear to me that, and I'll say with a lack of a better term/expression, that my application isn't seeing my input as the decimal number 1 or 2.
From the terminal, what is the structure of the data I'm sending to my application, or simply put, what does my 1or 2 "look" like to my application?
When you are taking input with getchar() you are getting an char value. But you are comparing it with an integer. Instead of comparing with the integer, you can compare the input with corresponding characters. For example, use
const char option_a = '1';
const char option_b = '2';
I believe you want to find the American Standard Code for information interchange(ASCII) table. 0 = 48, 1 = 49, 2 = 50,...I had the same problem while working with arduino’s serial monitor, and it should all be covered by the same standard.
I'm new to Objective-C, and this is really my first program that is interactive. I've been learning for about 2 weeks now.
So, my question is: typically I've noticed when you have multiple scanf's in a row, they each wait for input - however in this situation, where I ask for account owner name, and balance - it fires both NSLog functions instead of waiting for the first input.
Here is my main:
int main(int argc, char* argV[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
bank *columbiaBank = [[bank alloc] init];
int iteration = 0;
while (true) {
int selection = 0;
NSLog(#"\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?:");
scanf("%i", &selection);
if (selection == 1) {
NSLog(#"\nEnter account owner:");
char accountOwner;
scanf("%c", &accountOwner);
NSLog(#"\nEnter opening balance:");
float openingBalance;
scanf("%f", &openingBalance);
// create and add new account
bankAccount *newAccount = [[bankAccount alloc] initWithProps:[NSString stringWithFormat:#"%c", accountOwner] :[NSString stringWithFormat:#"%i", iteration] :openingBalance];
[columbiaBank addAccount:newAccount];
[newAccount release];
NSLog(#"\nAccount successfully added!");
} else if (selection == 2) {
NSLog(#"\nEnter account id:");
int accountId;
scanf("%i", &accountId);
// remove account
[columbiaBank removeAccount:[NSString stringWithFormat:#"%i", accountId]];
NSLog(#"\nAccount successfully removed!");
} else if (selection == 3) {
NSLog(#"\nThe bank currently has %i accounts.", columbiaBank.totalAccounts);
NSLog(#"\nThe bank's current balance from all accounts is $%f", columbiaBank.totalBankBalance);
NSLog(#"\n-- Output of all account info --");
[columbiaBank printAccounts];
} else {
NSLog(#"You did not enter a valid action.");
}
iteration++;
}
[columbiaBank release];
[pool drain];
return false;
}
Other users already said everything about it. The scanf inserts a new line "\n" automatically in the buffer that is passed to the next scanf. This is because any unwritten data is written in the next stream.
I want to add that you can use fflush to clear the stream buffer, in this case you want to use
scanf("%i", &selection);
fflush(stdin)
to clear the buffer of stdin (the console input) after every scanf.
Edit: I didn't know that, but As #Peter Kowalski said the use of fflush(stdin), for input stream, should be avoided because it has an undefined behaviour for input streams.
Cprograming.com FAQ > Why fflush(stdin) is wrong.
But it seems that there is not a guaranteed method to flush the input stream in C.
Cprograming.com FAQ > Flush the input stream
I know that in C++ a standard way is to use cin.ignore() after cin >> selection but I don't know how this can be done in C. Maybe some more experienced user can give some insight on what is happening with fflush(stdin).
*[Note: If you are going to use Objective-C you might wish to use input conversion methods from Cocoa rather than mix Cocoa (NSLog) and stdio (scanf). But that doesn't answer your question...]
When parsing integers, floats and even strings scanf skips whitespace - e.g. spaces, tabs, end of line, etc. - and every input line ends with at least an end of line (which may be a carriage return, line feed, or both depending on the system). This means that after reading your first integer there is still, at least, an end of line in the input and the attempt to read a character will return it - hence no wait for input. To discard the remaining, unused, input you can use fpurge. E.g.:
#include <stdio.h>
int main(int argc, char* argV[])
{
int selection = 0;
fputs("\n1. Add Account \n2. Remove Account \n3. Modify Account \nWhat would you like to do?: ", stdout);
scanf("%i", &selection);
if (selection == 1)
{
fputs("\nEnter account owner: ", stdout);
fpurge(stdin); // skip any input left in the buffer as %c takes the very next character and does not skip whitespace
char accountOwner;
scanf("%c", &accountOwner);
fputs("\nEnter opening balance: ", stdout);
float openingBalance;
scanf("%f", &openingBalance);
printf("%c - %f\n", accountOwner, openingBalance);
}
}
Note that reading in character strings does skip whitespace, so if your account owner was a string you would not need the fpurge.
Presumably you want the account owner name to be more than a single character, but you're only reading a single character in that scanf. If you're trying to enter more than a single character there, the first scanf will read the first character, and since there's more in the input buffer, the next scanf will try to read immediately without waiting for your numeric input. If you are only using a single character for the owner name, then you'll need to consume the newline from the input buffer.
If you want to read a string as the account owner name, you'll need to allocate space for more than one character, and use %s rather than %c as your scanf format string. Also remember to check the return value for scanf. The function will return the number of items successfully scanned, or 0 if no items were scanned, typically due to invalid input, or return EOF.
char accountOwner[26];
// ...
// note that you can specify a width (max length) for a string using scanf
scanfReturn = scanf("%25s", accountOwner);
Hi all I am having a strange issue, when i use scanf to input data it repeats strings and saves them as one i am not sure why.
Please Help
/* Assment Label loop - Loops through the assment labels and inputs the percentage and the name for it. */
i = 0;
j = 0;
while (i < totalGradedItems)
{
scanf("%s%d", assLabel[i], &assPercent[i]);
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%s", assLabel[i]);
i++;
}
Input Data
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
Output Via Console
Prog1QuizQuizProg2MdtmMdtmFinal
Final diagnosis
You don't show your declarations...but you must be allocating just 5 characters for the strings:
When I adjust the enum MAX_ASSESSMENTLEN from 10 to 5 (see the code below) I get the output:
Prog1Quiz 20
Quiz 20
Prog2Mdtm 20
Mdtm 15
Final 25
You did not allow for the terminal null. And you didn't show us what was causing the bug! And the fact that you omitted newlines from the printout obscured the problem.
What's happening is that 'Prog1' is occupying all 5 bytes of the string you read in, and is writing a null at the 6th byte; then Quiz is being read in, starting at the sixth byte.
When printf() goes to read the string for 'Prog1', it stops at the first null, which is the one after the 'z' of 'Quiz', producing the output shown. Repeat for 'Prog2' and 'Mtdm'. If there was an entry after 'Final', it too would suffer. You are lucky that there are enough zero bytes around to prevent any monstrous overruns.
This is a basic buffer overflow (indeed, since the array is on the stack, it is a basic Stack Overflow); you are trying to squeeze 6 characters (Prog1 plus '\0') into a 5 byte space, and it simply does not work well.
Preliminary diagnosis
First, print newlines after your data.
Second, check that scanf() is not returning errors - it probably isn't, but neither you nor we can tell for sure.
Third, are you sure that the data file contains what you say? Plausibly, it contains a pair of 'Quiz' and a pair of 'Mtdm' lines.
Your variable j is unused, incidentally.
You would probably be better off having the input loop run until you are either out of space in the receiving arrays or you get a read failure. However, the code worked for me when dressed up slightly:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
char assLabel[10][10];
int assPercent[10];
int i = 0;
int totalGradedItems = 5;
while (i < totalGradedItems)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
{
fprintf(stderr, "Error reading\n");
exit(1);
}
i++;
}
/* Print Statement */
i = 0;
while (i < totalGradedItems)
{
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
i++;
}
return 0;
}
For the quoted input data, the output results are:
Prog1 20
Quiz 20
Prog2 20
Mdtm 15
Final 25
I prefer this version, though:
#include <stdio.h>
enum { MAX_GRADES = 10 };
enum { MAX_ASSESSMENTLEN = 10 };
int main(void)
{
char assLabel[MAX_GRADES][MAX_ASSESSMENTLEN];
int assPercent[MAX_GRADES];
int i = 0;
int totalGradedItems;
for (i = 0; i < MAX_GRADES; i++)
{
if (scanf("%9s%d", assLabel[i], &assPercent[i]) != 2)
break;
}
totalGradedItems = i;
for (i = 0; i < totalGradedItems; i++)
printf("%-9s %3d\n", assLabel[i], assPercent[i]);
return 0;
}
Of course, if I'd set up the scanf() format string 'properly' (meaning safely) so as to limit the length of the assessment names to fit into the space allocated, then the loop would stop reading on the second attempt:
...
char format[10];
...
snprintf(format, sizeof(format), "%%%ds%%d", MAX_ASSESSMENTLEN-1);
...
if (scanf(format, assLabel[i], &assPercent[i]) != 2)
With MAX_ASSESSMENTLEN at 5, the snprintf() generates the format string "%4s%d". The code compiled reads:
Prog 1
and stops. The '1' comes from the 5th character of 'Prog1'; the next assessment name is '20', and then the conversion of 'Quiz' into a number fails, causing the input loop to stop (because only one of two expected items was converted).
Despite the nuisance value, if you want to make your scanf() strings adjust to the size of the data variables it is reading into, you have to do something akin to what I did here - format the string using the correct size values.
i guess, you need to put a
scanf("%s%d", assLabel[i], &assPercent[i]);
space between %s and %d here.
And it is not saving as one. You need to put newline or atlease a space after %s on print to see difference.
add:
when i tried
#include <stdio.h>
int main (int argc, const char * argv[])
{
char a[1][2];
for(int i =0;i<3;i++)
scanf("%s",a[i]);
for(int i =0;i<3;i++)
printf("%s",a[i]);
return 0;
}
with inputs
123456
qwerty
sdfgh
output is:
12qwsdfghqwsdfghsdfgh
that proves that, the size of string array need to be bigger then decleared there.
Good afternoon,
I'm trying to accomplish a task that i know should be doable. however my attempts seem to fail every time. My endeavor is to learn to code in Objective -c and have been making good progress. what i would like to do is add a loop to my current application that asks at the end if i would like to run again or some thing to that regard, and reply with a yes or no. if no the program ends and if yes it jumps back to the top of the project to start all over. kinda like what i have below? forgive me please if its not quite perfect, im still getting used to programing and am finding it incredibly fun.
#include <stdio.h>
int main(void)
{
char loop = yes;
while (loop = yes)
{
.
.
.
}
printf ("would you like to continue (yes/no)/n");
scanf ("%s", loop);
}
The printf and scanf need to be moved up inside the curly braces of the while loop. Also, you want \n instead of /n in the printf. Finally, you're going to get a string back with that scanf() call, so you'll want to declare loop as a char array, and then in the while loop, check the first element of that array for a 'y' or 'n' or something like that. You might also want to look at getchar() instead of scanf() for that sort of thing.
Not compiled here, but should work:
#include <stdio.h>
int main(void)
{
char buffer[256];
do {
.
.
.
printf ("would you like to continue (yes/no)/n");
scanf ("%s", buffer);
} while (strcmp(buffer,"yes") != 0);
}
One wouldn't do anything like that in a real world application, but for demonstration purpose it should be ok.
I made your variable an array, because strings are arrays of characters in C. Length is set to 256 bytes (255 characters + 0-byte as delimiter). I changed the loop to do-while to make it run at least once. For string comparison you need to call a function. strcmp returns 0 for identical strings. Finally, the question belongs in the loop.
It is plain C though, using nothing of Objective-C.
int main() {
char A = 'n';
char B = 'y';
char Answer;
printf("Does the subject have a glazed over look? (y/n): \n");
scanf("%c",&Answer);
if (Answer=='N'||Answer=='y'|| Answer=='N'||Answer=='Y')
printf("Good\n");
else
printf("Please enter 'y' or 'n' \n ");
return 0;
}
#include <stdio.h>
int main(void)
{
avi;
char loop[10];
while (loop = yes)
{
.
.
.
}
printf ("would you like to continue (yes/no)/n");
scanf ("%s", loop);
if(strcpm(loop,"YES")==0) goto avi:
}
I'm trying to allow users to simply hit Enter without typing anything, and use this to mean accepting a default value. scanf isn't doing what I want and the app still 'blocks': the next line of code doesn't run.
The only way is to actually type something THEN press Enter.
I tried using NSFileHandle and fileHandleWithStandardInput; however, it seems that the user is now forced to hit Ctrl-D to indicate EOF.
Someone suggested using fgets, but I cannot work out what to pass as 3rd parameter (of FILE* type). Tried stdin but it doesn't 'block'.
How do I accept input from a user, using Objective-C, and at the same time allow the user to simply hit Enter without being forced to type anything? How do I read a single line, even if that line is blank?
Assuming the code doesn't block and the next line runs immediately (as you seemed to indicate early in the question and in a comment), you have a common problem when mixing non-line-based and line-based input.
What happens is you have a newline left in the buffer, and fgets sees that, reads it, and returns, instead of doing what you really want: ignoring it, and then reading a line.
The solution is to simply do the ignoring part yourself, and then call fgets:
#include <stdio.h>
#include <string.h>
FILE* ignoreline(FILE* stream) {
for (int c; (c = fgetc(stream)) != EOF;) {
if (c == '\n') break;
}
return stream;
}
void example_use() {
char buf[1000];
ignoreline(stdin);
fgets(buf, sizeof buf, stdin);
// or, since it returns the stream, can be more compact:
fgets(buf, sizeof buf, ignoreline(stdin));
}
int main() { // error handling omitted
int n;
printf("Enter a number: ");
scanf("%d", &n);
char buf[1000];
printf("Enter a line: ");
ignoreline(stdin); // comment this line and compare the difference
fgets(buf, sizeof buf, stdin);
*strchr(buf, '\n') = '\0';
printf("You entered '%s'.\n", buf);
return 0;
}
Note that it is also common and encouraged to "pair" the ignoreline with the scanf (or other non-line-based input) to turn that into line-based input. You may want to modify it, in that case, so you can tell the difference between input of "42 abc" and "42" (in the "Enter a number" case). Some people just use fgets everywhere, then parse that line with sscanf, and while that works, it's not necessary.
I use getch(); in library conio.h
simply the program waits for any key to be pressed
If you're using Windows, you can use the ReadConsoleInput function (see MSDN for more on this) :
INPUT_RECORD keyin;
DWORD r;
while (ReadConsoleInput(GetStdHandle(STD_INPUT_HANDLE),&keyin,1,&r)) {
if (keyin.EventType!=KEY_EVENT) continue;
if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_SPACE) break; ///use these VK codes to get any key's input
if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_F1)
{
printf("You pressed F1\n");
}
if (keyin.Event.KeyEvent.wVirtualKeyCode==VK_F2)
{
printf("You pressed F2\n",);
}
}//end while loop
You don't need to hit enter after each key then.This works like a dream for me...
use getchar() to take input without using scanf function...