0

In order to get more familiar with Swift I put together the start of a class designed to represent the needs and wants of a human game character. Right now it keeps track of a water and food variable. These variables are changed by functions that accept NSStrings (or Strings, I have tried both) and run that parameter through a switch statement.

import Foundation

class human {

var food:Int = 0
var water:Int = 0

func setFood(str:NSString) {
    var generic:String = "The \(str) filled your Food Hole with "

    switch str {
    case "chicken":
        food += 10
        println(generic + "10 points.")
    case "bread":
        food += 5
        println(generic + "5 points")
    case "beans":
        food += 10
        println(generic + "10 points")
    default:
        if food < 30 {
            food += 2
            println("That wasn't really food...Here's two pity points")

        } else {
            println("Stop eating garbage")
        }
    }
}

func setWater(str:NSString) {
    var generic:String = "The \(str) filled your Water Hole with "

    switch str {
    case "water":
        water += 30
        println(generic + "30 points.")
    case "mud water":
        water += 10
        println(generic + "10 points. And you're gross.")
    case "radioactive coolant":
        water += 5
        println("Okay so that technically worked but wasn't a good idea")
    default:
        println("Don't put that in your mouth")
    }
}
}

Here is the code for getting input from the console:

var hu = human()

hu.setFood("bread")
println(hu.food)    //this works fine

let keyboard = NSFileHandle.fileHandleWithStandardInput()

while (keyboard) {
println("What do you eat or drink?")

var input = NSString(data: keyboard.availableData, encoding: NSUTF8StringEncoding)
hu.setFood(input)

println(input) //check input to confirm it even holds a string
}

The first setFood function with the hardcoded string works fine. The correct case is matched, the variable is updated correctly, the text prints, etc. I have a println statement at the end there so that I can see what the input variable actually holds and it does seem to hold some kind of String.

The specific problem is that the switch statement always selects the default case when matching against input from the console. Inputting a valid string like chicken into the console will not match the chicken case of the switch statement.

Is this an encoding issue? I've tried NSString, String, I've tried casting input to a String, using a lowercase method to see if that "cleans" things up. I've looked through the library reference in Xcode for anything that might give me what I want without any luck. I am a beginner at Swift obviously and I've never written any Objective-C. I hope I'm not missing something obvious. Thanks.

acochetti
  • 3
  • 2
  • Check for a newline at the end of your input. – pjs Jun 10 '14 at 16:45
  • Wow, I can't believe it was that simple. I didn't realize the strings would include a newline. Is my way of getting console input non-standard or is accounting for newlines just something that has to be done manually? – acochetti Jun 10 '14 at 17:00
  • At this point I think you have to do it manually. I'm hoping that the final release of Swift will have easy input functions the equivalent of, say, Ruby's `gets`. – pjs Jun 10 '14 at 17:03

2 Answers2

2

The console input includes the newline that was inserted by pressing "enter". If you change the last println(input) to println("<\(input)>") you will see it prints

<chicken
>

One quick solution is to add

input = input.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet())

before passing it to setFood()

Jayson
  • 1,689
  • 14
  • 26
  • This may trim more than you want, in which case you should explicitly only remove the newline from the end – Jayson Jun 10 '14 at 17:01
  • The trimming method worked perfectly. I will keep your warning in mind about over-trimming but as I have it set up right now there aren't any problems. Thank you! – acochetti Jun 10 '14 at 17:06
0

I implemented a gets function to handle my string input and trim the newlines:

func gets() -> String {
    return NSString(data: NSFileHandle.fileHandleWithStandardInput().availableData,
    encoding:NSUTF8StringEncoding).stringByTrimmingCharactersInSet(NSCharacterSet.newlineCharacterSet())
}

let response = gets()
pjs
  • 18,696
  • 4
  • 27
  • 56