1

我是 Objective-C 的新手,这确实是我的第一个交互式程序。我已经学习了大约2周了。

所以,我的问题是:通常我注意到当您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;
}
4

3 回答 3

2

其他用户已经说了一切。scanf 会在缓冲区中自动插入一个新行“\n”,然后传递给下一个 scanf。这是因为任何未写入的数据都会写入下一个流中。

我想补充一点,您可以使用它fflush来清除流缓冲区,在这种情况下您要使用

scanf("%i", &selection);
fflush(stdin)

stdin在每个scanf.

编辑:我不知道,但正如@Peter Kowalski 所说,应避免将 fflush(stdin) 用于输入流,因为它对输入流具有未定义的行为。

Cprograming.com FAQ > 为什么 fflush(stdin) 是错误的。

但似乎没有保证在 C 中刷新输入流的方法。

Cprograming.com FAQ > 刷新输入流

我知道在 C++ 中,标准方法是使用cin.ignore()aftercin >> selection但我不知道如何在 C 中做到这一点。也许一些更有经验的用户可以对fflush(stdin).

于 2012-08-19T06:30:27.913 回答
0

大概您希望帐户所有者名称不只是一个字符,但您只读取其中的一个字符scanf。如果您尝试在此处输入多个字符,第scanf一个字符将读取第一个字符,并且由于输入缓冲区中有更多字符,因此下一个scanf将尝试立即读取而不等待您的数字输入。如果您使用单个字符作为所有者名称,那么您需要使用输入缓冲区中的换行符。

如果您想读取字符串作为帐户所有者名称,则需要为多个字符分配空间,并使用%s而不是%c作为scanf格式字符串。还记得检查返回值scanf。该函数将返回成功扫描的项目数,如果没有扫描任何项目,则返回 0,通常是由于输入无效,或者 return EOF

char accountOwner[26];

// ...

// note that you can specify a width (max length) for a string using scanf
scanfReturn = scanf("%25s", accountOwner);
于 2012-08-19T05:48:59.683 回答
0

*[注意:如果您打算使用 Objective-C,您可能希望使用来自 Cocoa 的输入转换方法,而不是混合使用 Cocoa ( NSLog) 和 stdio ( scanf)。但这并不能回答您的问题...]

在解析整数、浮点数甚至字符串时,会scanf跳过空格 - 例如空格、制表符、行尾等 - 并且每个输入行都至少以行尾结束(可能是回车、换行或两者都取决于系统)。这意味着在读取您的第一个整数之后,至少在输入中仍然存在行尾,并且尝试读取字符将返回它 - 因此无需等待输入。要丢弃剩余的、未使用的输入,您可以使用fpurge. 例如:

#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.

于 2012-08-19T18:55:07.710 回答