【问题标题】:Getting User Data From Console从控制台获取用户数据
【发布时间】:2012-11-14 23:03:38
【问题描述】:

昨天刚开始用 Java 背景用 Objective-C 编程,我迷路了。我有一个可以运行的程序,它的目的是从控制台获取一个人的姓名、年龄和体重,然后将这些值输出给用户。我的问题是当我在控制台中输入数据时,它只会显示我输入的第一个字母。然后它不会显示我的字符串的任何其他字符。所以这里有一些示例控制台数据来证明我的观点。

控制台:

2012-11-14 17:56:05.673 Tutorial[1757:403] Please Enter In Your Name
warning: this program uses gets(), which is unsafe.
C
2012-11-14 17:56:09.494 Tutorial[1757:403] Please Enter Your Age
1
2012-11-14 17:56:11.239 Tutorial[1757:403] Please Enter Your Weight
2
2012-11-14 17:56:13.205 Tutorial[1757:403] 
Name: Chris 
Age: 18 
Weight: 200

如您所见,它只会显示我输入的第一个字母,但它实际上使用输入字符串。为什么会发生这种情况?

函数声明:

#import "Person.h"

Person * readPersonData (Person * object);
void writePersonInformation(Person * object);

主要方法:

int main (int argc, const char * argv[])
{
    @autoreleasepool
    {
        Person * p1 = [[Person alloc] init];
        p1 = readPersonData(p1);
        writePersonInformation(p1);
    }
}

函数实现:

Person * readPersonData (Person * object)
{
    char nameCharacters[100];
    NSString * objectName;
    int objectAge, objectWeight;

    NSLog(@"Please Enter In Your Name");
    gets(nameCharacters);
    objectName = [[NSString alloc] initWithUTF8String:nameCharacters];
    [object setName : objectName];

    NSLog(@"Please Enter Your Age");
    scanf("%i", &objectAge);
    [object setAge : objectAge];

    NSLog(@"Please Enter Your Weight");
    scanf("%i", &objectWeight);
    [object setWeight : objectWeight];

    return object;
}
void writePersonInformation(Person  * object)
{
    NSLog(@"\nName: %@ \nAge: %i \nWeight: %i", object.getName, object.getAge, object.getWeight);
}

【问题讨论】:

  • Java 程序员也在这里,但我用 Objective-c 玩得够多了,猜到问题是你混合了 c 和 Objective-c。例如,您的 char 数组必须针对 NSObject 子类进行更改。但这只是一个猜测。等待专业人士
  • @BrunoVieira 我认为这也可能与我的字符数组有关,所以我将整个部分注释掉,只提示了年龄和体重的两个提示,但结果是一样的。这种语言对我来说看起来很陌生,只是想掌握这一切!
  • 我完全理解你。幸运的是,我们有 stackoverflow!
  • @BrunoVieira Objective-C 是一个 C 超集,所以没关系。这可能只是因为 Apple 添加了一些愚蠢的警告来阻止使用gets。尝试使用其他 C 方法之一来读取命令行输入。

标签: objective-c


【解决方案1】:

我认为这个问题与 Xcode 4.5 的问题有关(请参阅 this)。

您没有在问题中说明您是从调试器控制台还是从命令行运行,但是当您从命令行尝试时会发生什么?

不过,您应该使用 fgets(),如果只是为了停止运行时警告消息。

【讨论】:

    【解决方案2】:

    gets() 已知由于缓冲区溢出的可能性而存在安全问题,因此相当长一段时间以来的建议是改用 fgets()。

    【讨论】:

    • 这就是它不回显所有输入的原因吗?
    • 我对此表示怀疑,但无论如何摆脱该消息不会有什么坏处。至于问题,请尝试使用不同的转换。 initWithCString 可能会这样做,但您也可能会收到不推荐使用的警告。另请参阅:stackoverflow.com/questions/7884388/…
    • 看起来你的答案是评论。
    • 我认为这是一个答案,因为其中一个问题是编译器警告。
    • 不是根据 OP 它不是。这对你来说可能是个问题(实际上这对我来说也是个问题——我永远不会发布那样的代码),但这并不能解决他遇到的问题。
    【解决方案3】:

    使用fgets 传递文件的标准输入,而不是gets,大多数编译器通常将其标记为不安全。这至少会消除可能导致输入不显示的警告。这是一篇关于如何使用fgets的帖子

    Safe Alternative to gets

    或者,您可以尝试抑制警告,可能有一些编译器指令可以做到这一点(我知道在 VS 中有)。我曾经对很多“不安全”的函数进行自己的边界检查,发现这样可以减少编译器的一些烦恼。

    【讨论】:

    • 问题是“我的问题是当我在控制台中输入数据时,它只会显示我输入的第一个字母”。这能回答问题吗?
    • @trojanfoe 它没有回答为什么会这样,但我敢打赌它解决了他描述的问题。
    • @evanmcdonnal 删除 gets() 就像注释掉所有提示到阅读的内容对我的问题没有任何帮助。
    • @gmustudent 我没有说停止提示用户。我说使用fgets 而不是getsfgets 具有边界检查,被认为是安全的,并且不会产生该警告。当警告消失时,您的问题可能会随之而来。
    • @evanmcdonnal 照你说的做了,还是有问题。与gets()无关
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-30
    • 1970-01-01
    • 2019-02-12
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    相关资源
    最近更新 更多