dsjpqpdm620596
2017-02-18 10:53
浏览 71
已采纳

从重定向的.txt文件获取输入时,Go-Scanf和ReadString与换行符冲突

I really want to understand whether there are conflicts regarding Go's ReadString and Scanf functions when reading from a redirected standard input. FYI, developement is done on Ubuntu.

I currently have a recursive function that runs recursively, where in each iteration it asks the user to input the number of integers that will be tested, for then to have a testing session be done within a newly created 'testcase' object. So here's the following code for the function:

func (T *Test) Testing() {

if I == T.N {
    return
} else {
    //ask for number of integers per testcase
    var input string
    x:=0

    _,err = fmt.Scanf("%v
", &x)


    //check for correct user input first
    if err != nil {
        fmt.Println("Error: ", err, "LOL")
        ProgramExit()
    }


    //receive string as input (to accomodate the itegers that are going to be put in a line, with space-seperated integers), terminate at newline
    input,err = in.ReadString('
')

    input = strings.Trim(input, "
")

    //check for correct user input first
    if err != nil {
        fmt.Println("Error: ", err, "Errorororo")
        ProgramExit()
    }

    //split any spaces in the input
    input_array := strings.Split(input, " ") 

    if l := len(input_array); l!=x {
        fmt.Printf("inconsistent length of input! Inputted number of integers is %v, being ", l)
        fmt.Println(input_array)
        os.Exit(1)
    } 

    //make new TestCase object, with its sum and i zeroed first
    T.Tst[I] = &TestCase{x,make([]int,x),0,0} 

    //fill TestCase object
    T.Tst[I].Fill(input_array) 

    //increase I
    I++ 

//this is where println could be added to check for iterations

    //iterate by doing recursion back to method, instead of doing a for loop
    T.Testing() 
}

For clarification, ProgramExit() is just a function to exit the entire program when error occurs. While Fill() is a function to fill up T object using input_array's data.

Now my problem is that when I run the program with the mentioned loop, it can successfully read the inputs that I manually typed into the command line below:

(format of input is:

num of testcases

num of integers for testcase 1

num of input integers for testcase 1

num of integers for testcase 2

num of input integers for testcase 2

...

)

2
4
3 -1 1 14
5
9 6 -53 32 16

However when I put the same inputs into a .txt file and redirect that as the input for my program, it gets an EOF error, that seems to happen during the 2nd iteration of the function (i.e. when it tries to read in for 2nd testcase object). Here is the output that I got in the CLI:

$ main < data.txt
0
Error:  EOF LOL
Incorrect input! needs to be an integer input!

And this is the output when I put a println function for every successful iteration to print out value of I (I'th iteration)

$ main < data.txt
1
0
Error:  EOF LOL
Incorrect input! needs to be an integer input!

So it does seem that my function is iterating properly however unfortunately after reading the an entire line with ReadString, Scanf would read the next line as a newline (or EOF), instead of reading the next line properly. (Which does not happen when I inputted the integers manually).

Could anyone please help point out whether there is a problem with my function that does this, or is there an alternative way to do this properly? (please note that I am developing this for a challenge, and in this challenge, for loop is not allowed lol)

Thanks in advance!

  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • doufeiqiong3515 2017-02-18 14:31
    已采纳

    My guess is that Scanf is treating the you leave at the end after 1st iteration as the EOF.

    It's hard to guess where you are getting that error, looking at your code. But maybe try;

    _,err = fmt.Scanf("%v%c", &x)
    

    instead of

    _,err = fmt.Scanf("%v
    ", &x)
    

    And make sure your text file is formatted (beware of the newlines) as expected. Or use a more forgiving scanner(see below),

    Scanf scans text read from standard input, storing successive space-separated values into successive arguments as determined by the format. It returns the number of items successfully scanned. If that is less than the number of arguments, err will report why. Newlines in the input must match newlines in the format. The one exception: the verb %c always scans the next rune in the input, even if it is a space (or tab etc.) or newline.

    See ReadString doc;

    ReadString reads until the first occurrence of delim in the input, returning a string containing the data up to and including the delimiter. If ReadString encounters an error before finding a delimiter, it returns the data read before the error and the error itself (often io.EOF). ReadString returns err != nil if and only if the returned data does not end in delim. For simple uses, a Scanner may be more convenient.

    You may be getting the EOF from ReadString as well, again, hard to say looking at your output as it has neither of your debug logs (LOL etc.)

    Could be helpful if you print what it actually reads. And i'd consider using Scanner instead.

    已采纳该答案
    打赏 评论
  • dongmanni6916 2017-02-18 19:13

    Thanks for those who tried to help! I found the more proper way to input in a line of integers after googling around again. Apparently there is a method already discussed here: Read a set of integers separated by space in Golang.

    I basically replaced my strings input method and instead do an iteration of fmt.Scan() in each iteration of the testcase values to input the integers properly. Once again many thanks for those who tried to help, and apologies that I didn't find the google answer sooner hehe!

    打赏 评论

相关推荐 更多相似问题