我是Objective-C的新手,这是我的第一个交互式程序。我现在已经学习了大约两个星期。
所以,我的问题是:通常我注意到当你连续多个scanf
时,他们每个人都在等待输入 - 但是在这种情况下,我要求帐户所有者名称和余额 - 它会触发NSLog
个函数,而不是等待第一次输入。
这是我的主要内容:
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;
}
答案 0 :(得分:2)
其他用户已经说了一切。 scanf在传递给下一个scanf的缓冲区中自动插入一个新行“\ n”。这是因为任何未写入的数据都写在下一个流中。
我想补充一点,您可以使用fflush
清除流缓冲区,在这种情况下您要使用
scanf("%i", &selection);
fflush(stdin)
在每stdin
之后清除scanf
(控制台输入)的缓冲区。
编辑:我不知道,但正如@Peter Kowalski所说,应该避免使用fflush(stdin)作为输入流,因为它对输入流有一个未定义的行为。
Cprograming.com FAQ > Why fflush(stdin) is wrong.
但似乎没有一种保证方法可以在C中刷新输入流。
Cprograming.com FAQ > Flush the input stream
我知道在C ++中,标准方法是在cin.ignore()
之后使用cin >> selection
,但我不知道如何在C中完成此操作。也许一些更有经验的用户可以对某些内容有所了解发生在fflush(stdin)
。
答案 1 :(得分:0)
据推测,您希望帐户所有者名称不只是一个字符,但您只需阅读scanf
中的单个字符。如果您尝试在那里输入多个字符,则第一个scanf
将读取第一个字符,并且由于输入缓冲区中有更多字符,下一个scanf
将立即尝试读取而无需等待为您的数字输入。如果 仅使用单个字符作为所有者名称,那么您将需要使用输入缓冲区中的换行符。
如果您想要读取字符串作为帐户所有者名称,则需要为多个字符分配空间,并使用%s
而不是%c
作为scanf
格式字符串。另请记得检查scanf
的返回值。该函数将返回成功扫描的项目数,如果没有扫描项目则返回0,通常是由于输入无效,或返回EOF
。
char accountOwner[26];
// ...
// note that you can specify a width (max length) for a string using scanf
scanfReturn = scanf("%25s", accountOwner);
答案 2 :(得分:0)
* [注意:如果您打算使用Objective-C,您可能希望使用Cocoa的输入转换方法而不是混合Cocoa(NSLog
)和stdio(scanf
)。但这不能回答你的问题...]
解析整数时,浮点数甚至字符串scanf
都会跳过空格 - 例如空格,制表符,行尾等 - 并且每个输入行至少以行尾结束(可以是回车符,换行符或两者,具体取决于系统)。这意味着在读完第一个整数后,输入中至少仍有一行结束,并且尝试读取一个字符将返回它 - 因此无需等待输入。要丢弃剩余的未使用的输入,您可以使用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);
}
}
请注意,读取字符串确实会跳过空格,因此如果您的帐户所有者是字符串,则不需要fpurge
。