How to Avoid User String Inputs in Objective-C - objective-c

My program asks for an integer input and I want to make sure (error trap) that the program would print "invalid" if the user inputs a string or any other character.
I'm new to Objective-C, hope you'll understand.
NSLog(#"1. Apple 2. Orange 3. Mango 4. Banana");
NSLog(#"Choose fruit:");
scanf("%d", &fruit);
**if(fruit>4 || fruit<1){
//If the user inputs any number other than the choices.
NSLog(#"Invalid.");
}
else if(...){
//if the user inputs a string or character
}**
I expecting the program would print "Invalid" if it would input a character or string or anything besides the choices.

Im not sure if you still require an answer . Im also fairly new so anyone feel free to add . Im not sure if this is meets your exact requirements but it does what you want it to . Instead of tryign to check for each and every data type what i suggest is check if the entered value is an integer or not . If it is do something else return the error message .Take a look at the below code .
int main(int argc, const char * argv[]) {
char str[50] = {0}; // init all to 0
NSLog(#"1. Apple 2. Orange 3. Mango 4. Banana");
NSLog(#"Choose fruit:"); // print buffer
scanf("%s",str);
// you can create an NS foundation NSString object from the str buffer
NSString *valueEntered = [NSString stringWithUTF8String:str];
if([valueEntered integerValue]){
printf("do somethinng here\n");
}
else{
printf("Not an integer\n");
}
}
First take the user's input as a NSString , so we can transfer it to a Integer value later onwards. The reason i have initialised it as a character is because Scanf wont allow to pass a String from what i read . So get the user's input as a character set change it to a String and check if it includes a Integer or not . IntegerValue returns the integer that the string holds if there is one , else it returns 0 .
Another method you can try is using ScanInt method in NSScanner. Issue with that is it will check if it includes a integer and return true . So something like "abc32" will also be true in that manner so probably wont be usefull for you .
Please let me know if this is what you expect as i also learnt a few things trying to solve this :)

Check the return value of scanf.
Having said that, using scanf for interactive input is often a recipe for confusion, so it might be a better idea to read input into a string with something like fgets and then analyze the string (possibly, but not necessarily, with sscanf).

Related

Trying to check size of some cin statement

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

Convert a string into a int

I need some help here, I am currently making a game, but I got stuck somewhere. So, what I want is, if a Labels text is higher then the other labels text, then something will happen, I typed If Label26.Text > Label24.Text Then Label33.Visible = True which seems not to work, please, I need some help here, thanks. And yes, the labels text is NUMBERS.
The Text property of a label is a string. As far as computers go, you can't do math (using comparison operators like > will not return the result you are expecting) with strings because they are just a sequence of characters.
Even if the string only contains a number, the computer still sees it as a sequence of characters and not a number ("5" is a string literal with the character 5 in it, while 5 is an integer that can be used in a mathematic expression).
As some of the other commenters mentioned, you need to cast the Text property to an Integer or Double (or some other numeric data type). To do so, you'd want to use Int32.Parse to change the strings to integers.
If Int32.Parse(Label26.Text) > Int32.Parse(Label24.Text) Then Label33.Visible = True
You can use the int.tryParse to check if the content of the variable is a number or not. The output of the TryParse is a boolean, see the example below:
int num1 = 0;
bool num1_ = false;
num1_ = int.TryParse(txt1.Text.ToString(), out num1);
if (num1_)
{
// Is a number/integer
//Do something
}
else
{
//Is a string
//Do something else
}

Strtol and Glib Buffers causing appcrash

I'm trying to take data read from a TCP socket with the g_io_channel_read_chars method and convert it into a long integer. I've tried using strtol, atoi, not casting ScanLine as a gchar pointer, accessing the first variable of ScanLine with ScanLine[0], declaring FilterAmount in different ways and despite that, my app still crashes on that line. Any ideas?
static gchar ScanLine[9640];
long int FilterAmount;
g_io_channel_read_chars (source, (gchar *) ScanLine,1,&BytesRead,&GlibError);
if (BytesRead != 1){
return TRUE;
}
printf("This is my string: %s\n", ScanLine);
FilterAmount = strtol(ScanLine, NULL, 10);
The output of the printf statement is "2"
strtol() takes a C string argument: this means the character array must be NULL-terminated. Yours is quite probably not. You must either add a terminator after the last byte you read or parse the digits yourself (since you know when to stop parsing).

scanf is not waiting for input within my loop?

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

loop on prompt with a yes or no?

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:
}