Flush stdin using fgets - objective-c

Trying to make a registration page through the console.
I need several inputs for it, and I'm using fgets, so I need to flush stdin.
Lots of similar questions on Stack Overflow redirected here: http://c-faq.com/stdio/stdinflush2.html.
I got the code below using that link. However, this doesn't actually work. It says Username:, and then when I type in a username, and press enter, it just goes to a new, empty line in console where I can type in more.
Why is this happening?
How can I fix it?
EDIT: Added code
NSLog(#"Do you have an account already?(1 for Yes, 0 for no)");
fgets(cnumb1, 2, stdin);
int c;
while((c = getchar()) != '\n' && c != EOF);
size_t length = strlen(cnumb1);
if (cnumb1 [length-1] == '\n'){ // In case that the input string has 1 character plus '\n'
cnumb1 [length-1] = '\0';} // Plus '\0', the '\n' isn't added and the if condition is false.
NSString* string = [NSString stringWithUTF8String: cnumb1];
if (string == 0) {
while(numb4 == 1) {
numb3 = 1;
while( numb3 == 1){
NSLog(#"Username:");
fgets(usercheck1, 13, stdin);
int c2;
while((c2 = getchar()) != '\n' && c2 != EOF);
size_t length1 = strlen(usercheck1);
if (usercheck1 [length1-1] == '\n'){ // In case that the input string has 12 characters plus '\n'
usercheck1 [length1-1] = '\0';} // Plus '\0', the '\n' isn't added and the if condition is false.

Completely rewrote my answer, looks like I didn't understand the problem well enough.
The line that is supposed to empty the input buffer will not get anything until the user presses return again - unless the user enters more characters than the input buffer can hold.
You should first check the length of string read by fgets and if the last character (before the \0) is a \n, don't try to read more characters. Otherwise empty the input buffer like you did.

Related

conversion of subject name into x509_name format

I have subject name of CA certificate in CN=CA1, O=DEVANG.
I want to convert into X509_NAME format.
Is there any APIs to help me convert it ?
How can I compare ?
There do not seem to be any helper functions available in OpenSSL to do this. It looks like the only way to achieve what you want is by parsing the string and building up the X509_NAME_ENTRY elements one by one. You could use strsep for that, resulting in something like this code (which does not do any error checking and is error prone with regard to variations in the name format):
#define TEST_NAME "CN=CA1, O=DEVANG"
X509_NAME *x509name = X509_NAME_new();
char *x509nameString = strdup(TEST_NAME);
char *toFree = x509nameString;
char *x509nameEntryString = strsep(&x509nameString, ",");
char *x509nameEntryTypeString;
char *x509nameEntryValueString;
while (NULL != x509nameEntryString) {
x509nameEntryValueString = x509nameEntryString;
x509nameEntryTypeString = strsep(&x509nameEntryValueString, "=");
X509_NAME_add_entry_by_txt(x509name, x509nameEntryTypeString,
MBSTRING_ASC, x509nameEntryValueString, -1, -1, 0);
/* Need to skip spaces */
while ((NULL != x509nameString) &&
(' ' == *x509nameString)) {
x509nameString = &x509nameString[1];
}
x509nameEntryString = strsep(&x509nameString, ",");
}
/* See the result, just FYI */
X509_NAME_print_ex_fp(stdout, x509name, 0, XN_FLAG_ONELINE);
free(toFree);
For comparing two X509_NAME instances, the function X509_NAME_cmp() is available.
I do hope somebody has a better answer...

EXC_BAD_ACCESS when reading 9 characters, but works with less than 9

I'm developing a console app in Objective-C. I've got it working, but when manually testing edge cases, I found a strange behavior that I can't explain.
Basically, I've set up scanf() in a loop, and when the user types invalid info, it prints an "invalid option" message. Then, if the input is less than 9 characters long, it goes through the loop again as intended. But, if the input is 9 characters or longer, it gives a EXC_BAD_ACCESS error on a certain line.(This error doesn't happen if I comment out said line.)I can't figure out any reason why 8 vs 9 characters being read would cause this error. Any ideas?
Below are the two methods that I figure are relevant, with a comment on the line throwing the error. If you think other referenced code may be causing this, let me know and I'll add that code.
-(void)startMenu {
printf("\nGAME OPTIONS\n| WinningScore = %d (w) | Name = %s (n) | Back (b) |\n",
_options.winningScore, [_options.name UTF8String]);
}
-(void)start {
char selectedOption;
char w = 'w';
char n = 'n';
char b = 'b';
while(YES) {
[self startMenu]; // This line gets the EXC_BAD_ACCESS error
// if the user puts in 9 or more characters.
// If it is commented out, then no error is thrown.
scanf("%s", &selectedOption);
if(selectedOption == w) {
[self setWinningScore];
} else if(selectedOption == n) {
[self setName];
} else if(selectedOption == b) {
break;
} else {
printf("'%s' is not a valid option.\n", &selectedOption);
}
}
}
It this was C (and the post is tagged C) I'd suggest:
char selectedOption;
....
scanf(" %c", &selectedOption);
...
printf("'%c' is not a valid option.\n", selectedOption);
The failure showing up after a 9 charterer input is serendipity. scanf("%s", &selectedOption); is certainly wrong for reading a single character. Any input starts causing problems. Use the matching format specifier and variable.
[Edit]
A C-like solution.
If more than 1 char is desire for input, use the idea put forth by #Devolus. Example:
char selectedOption[10];
if (fgets(selectedOption, sizeof selectedOption, stdin) == NULL)
Handle_EOForIOerror();
// Get rid of potential trailing \n if desired.
size_t len = strlen(selectedOption);
if (len > 0 && selectedOption[len-1] == '\n') selectedOption[--len] = '\0';
You should use fgets instead of scanf here, as you can limit the number of characters in the buffer.
scanf is potentially unsafe because the buffer can be exceeded.

Why does my program keeps repeating the line even if a valid input is enter?

int main(int argc, const char * argv[])
{
#autoreleasepool {
int userInput= 6 ;
char userChar='\0';
//creating new instances
Dice *a = [[Dice alloc] init];
//creating new objects
Die *d1 = [[Die alloc] initWithSides:&userInput];
Die *d2 = [[Die alloc] initWithSides:&userInput];
//adding dices
[a addDice:d1];
[a addDice:d2];
while(1)
{
printf("Press R to roll dices and Q to exit \n> ");
scanf("%c",&userChar);
if (userChar == 'r' | userChar =='R')
{
for (int i=0; i<10; i++)
{
[a rollDice];
printf("Dice 1 =%d\n",d1.returns);
printf("Dice 2 =%d\n",d2.returns);
printf("The total values of both dice is %d\n",a.totalValue);
printf("Does the dices have same value? Y(1) N(0) => %d\n\n",a.allSame);
}
}
else if (userChar == 'q' | userChar == 'Q')
{
return 0;
}
else
{
printf("Enter a valid command!\n");
}
}
}
}
I tried to create a loop that repeats itself and when r is pressed, do the roll dice and q when user wants to quit the program. otherwise, keep repeating itself until either proper input is enter. but i don't get it why if i enter an input, it will repeat the phase that are in else? Like this,
Press R to roll dices and Q to exit
>l
Enter a valid command!
Press R to roll dices and Q to exit
>Enter a valid command! //Why does it repeats itself here??
Press R to roll dices and Q to exit
>
hey try to use following code it must work.
scanf(" %c",&userChar);
If you enter
l<RETURN>
in your console then there are two characters in the input buffer: the "l" and
a newline.
The first scanf() reads the "l" and the second scanf() reads the newline.
While this can be solved by modifying the scan format, a much better solution to read
an entire line from user input is to use fgets(), e.g.
char buf[100];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
userChar = buf[0];
// ...
}
And note that the logical "or" operator is ||, not |!

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

printf(), fprintf(), wprintf() and NSlog() won't print on XCode

I'm doing a small app for evaluating and analyzing transfer functions. As boring as the subject might seem to some, I want it to at least look extra cool and pro and awesome etc... So:
Step 1: Gimme teh coefficients! [A bunch of numbers]
Step 2: I'll write the polynomial with its superscripts. [The bunch of numbers in a string]
So, I write a little C parser to just print the polynomial with a decent format, for that I require a wchar_t string that I concatenate on the fly. After the string is complete I quickly try printing it on the console to check everything is ok and keep going. Easy right? Welp, I ain't that lucky...
wchar_t *polynomial_description( double *polyArray, char size, char var ){
wchar_t *descriptionString, temp[100];
int len, counter = 0;
SUPERSCRIPT superscript;
descriptionString = (wchar_t *) malloc(sizeof(wchar_t) * 2);
descriptionString[0] = '\0';
while( counter < size ){
superscript = polynomial_utilities_superscript( size - counter );
len = swprintf(temp, 100, L"%2.2f%c%c +", polyArray[counter], var, superscript);
printf("temp size: %d\n", len);
descriptionString = (wchar_t *) realloc(descriptionString, sizeof(wchar_t) * (wcslen(descriptionString) + len + 1) );
wcscat(descriptionString, temp);
counter++;
}
//fflush(stdout); //Already tried this
len = wprintf(L"%ls\n", descriptionString);
len = printf("%ls**\n", descriptionString);
len = fprintf(stdout, "%ls*\n", descriptionString);
len = printf("FFS!! Print something!");
return descriptionString;
}
During the run we can see temp size: 8 printed the expected number of times ONLY WHILE DEBUGGING, if I run the program I get an arbitrary number of prints each run. But after that, as the title states, wprintf, printf and fprintf don't print anything, yet len does change its size after each call.
In the caller function, (application:(UIApplication *)application didFinishLaunchingWithOptions:, while testing) I put an NSLog to print the return string, and I dont get ANYTHING not even the Log part.
What's happening? I'm at a complete loss.
Im on XCode 4.2 by the way.
What's the return value from printf/wprintf in the case where you think it's not printing anything? It should be returning either -1 in the case of a failure or 1 or more, since if successful, it should always print at least the newline character after the description string.
If it's returning 1 or more, is the newline getting printed? Have you tried piping the output of your program to a hex dumper such as hexdump -C or xxd(1)?
If it's returning -1, what is the value of errno?
If it turns out that printf is failing with the error EILSEQ, then what's quite likely happening is that your string contains some non-ASCII characters in it, since those cause wcstombs(3) to fail in the default C locale. In that case, the solution is to use setlocale(3) to switch into a UTF-8 locale when your program starts up:
int main(int argc, char **argv)
{
// Run "locale -a" in the Terminal to get a list of all valid locales
setlocale(LC_ALL, "en_US.UTF-8");
...
}