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

从重定向的.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.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 c程序不知道为什么得不到结果
  • ¥40 复杂的限制性的商函数处理
  • ¥15 程序不包含适用于入口点的静态Main方法
  • ¥15 素材场景中光线烘焙后灯光失效
  • ¥15 请教一下各位,为什么我这个没有实现模拟点击
  • ¥15 执行 virtuoso 命令后,界面没有,cadence 启动不起来
  • ¥50 comfyui下连接animatediff节点生成视频质量非常差的原因
  • ¥20 有关区间dp的问题求解
  • ¥15 多电路系统共用电源的串扰问题
  • ¥15 slam rangenet++配置