How to take command argument in Go? - go

I just start to learn Go, and I wrote a prime test program using the ProbablyPrime library.
package main
import (
"fmt"
"math/big"
"math"
"os"
"strconv"
)
func prime_test(n int64, certainty int)(bool,float64){
var probobility float64
i := big.NewInt(n)
isPrime := i.ProbablyPrime(certainty)
probobility = 1 - 1/math.Pow(4,10)
return isPrime, probobility
}
func why_not_prime(n int64)(int64){
var i int64
for i=2 ; i<n/2; i++ {
if n%i == 0 {return i}
}
return i
}
func main() {
var n int64
var certainty int
var isPrime bool
var probobility float64
if len(os.Args) > 1 {
n,_ = strconv.ParseInt(os.Args[1],64,64)
certainty,_ = strconv.Atoi(os.Args[2])
}
isPrime, probobility = prime_test(n,certainty)
if isPrime {
fmt.Printf("%d is probably %0.8f%% a prime.", n, probobility*100)
} else {
var i int64
i = why_not_prime(n)
fmt.Printf("%d is a composite because it can be divided by %d", n, i)
}
}
The code could be successfully compiled. When I run it, it always return 0 is a composite because it can be divided by 2.
I guess there's something wrong with the command line argument parsing. How to fix it?

The problem is with this line:
n,_ = strconv.ParseInt(os.Args[1],64,64)
The documentation of ParseInt(s string, base int, bitSize int) (i int64, err error) states:
ParseInt interprets a string s in the given base (2 to 36) and returns the corresponding value i.
The base can be 36 at the most and you pass 64. In this case an error will be returned (which you discard by using the blank identifier _), and n will have the zero value which is 0 hence you see the output as
0 is a composite because it can be divided by 2
Solution:
Change the line in question to this:
n, _ = strconv.ParseInt(os.Args[1], 10, 64)
and it should work. Also you should not discard errors because you will run into cases like this. Instead handle them properly like this:
var err error
n, err = strconv.ParseInt(os.Args[1], 10, 64)
if err != nil {
log.Fatal(err)
}
Note:
Also note that the first argument (os.Args[0] is the name of the executable), and since you expect and work with 2 extra arguments, you should check if the length of os.Args is greater than 2 not 1:
if len(os.Args) > 2 {
// os.Args[1] and os.Args[2] is valid
}

Related

How to read inputs recursively in golang

In the following code after one recursion the inputs are not read(from stdin). Output is incorrect if N is greater than 1.
X is read as 0 after one recursive call and hence the array is not read after that.
Program is supposed to print sum of squares of positive numbers in the array. P.S has to done only using recursion
package main
// Imports
import (
"fmt"
"bufio"
"os"
"strings"
"strconv"
)
// Global Variables
var N int = 0;
var X int = 0;
var err error;
var out int = 0;
var T string = "0"; // All set to 0 just in case there is no input, so we don't crash with nil values.
func main() {
// Let's grab our input.
fmt.Print("Enter N: ")
fmt.Scanln(&N)
// Make our own recursion.
loop()
}
func loop() {
if N == 0 {return}
// Grab our array length.
fmt.Scanln(&X)
tNum := make([]string, X)
// Grab our values and put them into an array.
in := bufio.NewReader(os.Stdin)
T, err = in.ReadString('\n')
tNum = strings.Fields(T)
// Parse the numbers, square, and add.
add(tNum)
// Output and reset.
fmt.Print(out)
out = 0;
N--
loop()
}
// Another loop, until X is 0.
func add(tNum []string) {
if X == 0 {return}
// Parse a string to an integer.
i, err := strconv.Atoi(tNum[X-1])
if err != nil {}
// If a number is negative, make it 0, so when we add its' square, it does nothing.
if (i < 0) {
i = 0;
}
// Add to our total!
out = out + i*i
X--
add(tNum)
}
Input:
2
4
2 4 6 8
3
1 3 9
Output:
1200
Expected output:
120
91
bufio.Reader, like the name suggests, use a buffer to store what is in the reader (os.Stdin here), which means, each time you create a bufio.Reader and read it once, there are more than what is read stored into the buffer, and thus the next time you read from the reader (os.Stdin), you do not read from where you left.
You should only have one bufio.Reader for os.Stdin. Make it global (if that is a requirement) or make it an argument. In fact, bufio package has a Scanner type that can splits spaces and new lines so you don't need to call strings.Fields.
I think you should practise doing this yourself, but here is a playground link: https://play.golang.org/p/7zBDYwqWEZ0
Here is an example that illustrates the general principles.
// Print the sum of the squares of positive numbers in the input.
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
)
func sumOfSquares(sum int, s *bufio.Scanner, err error) (int, *bufio.Scanner, error) {
if err != nil {
return sum, s, err
}
if !s.Scan() {
err = s.Err()
if err == nil {
err = io.EOF
}
return sum, s, err
}
for _, f := range strings.Fields(s.Text()) {
i, err := strconv.Atoi(f)
if err != nil || i <= 0 {
continue
}
sum += i * i
}
return sumOfSquares(sum, s, nil)
}
func main() {
sum := 0
s := bufio.NewScanner(os.Stdin)
sum, s, err := sumOfSquares(sum, s, nil)
if err != nil && err != io.EOF {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println(sum)
}
Input:
2
4
2 4 6 8
3
1 3 9
Output:
240

How to fill a slice with scan values

I'm brand new to Go and having trouble getting fmt.scan() to fill a slice. The number of input values is dynamic and I can't use a for loop. My initial thought was to try this:
package main
import "fmt"
func main() {
var x []int
fmt.Println("Enter input")
fmt.Scanf("%v", append(x))
fmt.Println(x)
}
Which obviously doesn't work. Can someone point me in the right direction?
[Get] fmt.Scan() to fill a slice. The number of input values is dynamic and I can't use a for loop.
Perhaps, something like this:
package main
import "fmt"
func input(x []int, err error) []int {
if err != nil {
return x
}
var d int
n, err := fmt.Scanf("%d", &d)
if n == 1 {
x = append(x, d)
}
return input(x, err)
}
func main() {
fmt.Println("Enter input:")
x := input([]int{}, nil)
fmt.Println("Input:", x)
}
Output:
Enter input:
1
2 3
4
5 6 7
Input: [1 2 3 4 5 6 7]
ADDENDUM:
When storage is allocated for a variable or a new value is created, and no explicit initialization is provided, the variable or value is given a default value, the zero value for its type: nil for slices. Conversions are expressions of the form T(x) where T is a type and x is an expression that can be converted to type T. []int(nil) is a conversion to the zero value for the slice value []int.
x := input([]int(nil), nil)
is equivalent to
x := input([]int{}, nil)
or
var x []int
x = input(x, nil)
I have revised my answer to use:
x := input([]int{}, nil)
I'm new to Go, so this are my 2cents as a newbie.
func main(){
var numsToInput int
fmt.Println("Welcome user!")
fmt.Println("How many numbers would you like to scale today?")
fmt.Scan(&numsToInput)
fmt.Println("Type please the ", num, " numbers: ")
var values []float32 // Empty slice
for i := 0; i < num; i++{
var val float32
fmt.Scanln(&val)
values = append(values, val)
}
fmt.Println(values)
}
It's not a very elaborate program, but certainly it's simple.
I hope it was useful.
Using simple packages and more logic, you could try this,
package main
import "fmt"
func main() {
var ele rune
var size int
var sli = make([]int,0,1)
size = cap(sli)
for i:=0; i<=size; i++{
if i>=len(sli){
size=size+1
}
ele = 0
fmt.Println("Enter a number to add: ")
fmt.Scan(&ele)
if ele==0 {
fmt.Println("Stopping!")
break
}
sli = append(sli, int(ele))
}
fmt.Println(sli)
}
The code would stop and print the slice when you enter anything other than an integer.

Read n integers / float / string from standard input

Algorithm competition have questions that provide the input in multiple lines, with the first line specifying the count of the inputs. Example -
3
78
42
99
The first line tells that there will be 3 integers followed by the three integers.
Currently, I have the following code to read them -
package main
import "fmt"
func main() {
var num []int
var input int
var count int
fmt.Scanf("%d", &count)
for {
if (count == 0) {
break
}
fmt.Scanf("%d", &input)
num = append(num, input)
count--
}
}
Is there a better way to carry this out? The above approach feels clumsy for some reason.
This code pushes everything into the loop header, as well as puts input into the most local scope possible. You should be checking the error returned by Scanf too:
package main
import "fmt"
func main() {
var num []int
var count int
var err error
for _, err = fmt.Scanf("%d\n", &count); err == nil && count > 0; count-- {
var input int
_, err = fmt.Scanf("%d\n", &input)
num = append(num, input)
}
if err != nil {
panic(err)
}
}
There are about a million ways to write equivalent code, this seemed the best to me. An argument could be made for putting the error check in the loop before the append, but since encountering an error presumably invalidates the list, I thought it looked prettier this way.
package main
import (
"bufio"
"os"
"fmt"
)
func main() {
reader := bufio.NewReader(os.Stdin)
a:= read(reader,100000)
fmt.Println(a)
}
func read (reader *bufio.Reader, n int)([]uint32) {
a := make([]uint32, n)
for i:=0; i<n; i++ {
fmt.Fscan(reader, &a[i])
}
return a
}

Reading an integer from standard input

How do I use the fmt.Scanf function in Go to get an integer input from the standard input?
If this can't be done using fmt.Scanf, what's the best way to read a single integer?
http://golang.org/pkg/fmt/#Scanf
All the included libraries in Go are well documented.
That being said, I believe
func main() {
var i int
_, err := fmt.Scanf("%d", &i)
}
does the trick
An alternative that can be a bit more concise is to just use fmt.Scan:
package main
import "fmt"
func main() {
var i int
fmt.Scan(&i)
fmt.Println("read number", i, "from stdin")
}
This uses reflection on the type of the argument to discover how the input should be parsed.
http://golang.org/pkg/fmt/#Scan
Here is my "Fast IO" method for reading positive integers. It could be improved with bitshifts and laying out memory in advance.
package main
import (
"io/ioutil"
"bufio"
"os"
"strconv"
)
func main() {
out := bufio.NewWriter(os.Stdout)
ints := getInts()
var T int64
T, ints = ints[0], ints[1:]
..
out.WriteString(strconv.Itoa(my_num) + "\n")
out.Flush()
}
}
func getInts() []int64 {
//assumes POSITIVE INTEGERS. Check v for '-' if you have negative.
var buf []byte
buf, _ = ioutil.ReadAll(os.Stdin)
var ints []int64
num := int64(0)
found := false
for _, v := range buf {
if '0' <= v && v <= '9' {
num = 10*num + int64(v - '0') //could use bitshifting here.
found = true
} else if found {
ints = append(ints, num)
found = false
num = 0
}
}
if found {
ints = append(ints, num)
found = false
num = 0
}
return ints
}
Golang fmt.Scan is simpler than Golang fmt.Scanf (which is simpler than Clang scanf)
If fmt.Scan errors i.e. if not nil, log & return
1 Read single variable:
import (
"fmt"
"log"
)
var i int
if _, err := fmt.Scan(&i); err != nil {
log.Print(" Scan for i failed, due to ", err)
return
}
fmt.Println(i)
2 Read multiple variables:
import (
"fmt"
"log"
)
var i, j, k int
if _, err := fmt.Scan(&i, &j, &k); err != nil {
log.Print(" Scan for i, j & k failed, due to ", err)
return
}
fmt.Println(i, j, k)
Best of luck
Example from: http://www.sortedinf.com/?q=golang-in-1-hour
You can use fmt.Scanf with a format specifier. The format specifier for the integer is %d. So you can use standard input like below.
func main() {
var someVar int
fmt.Scanf("%d", &someVar)
}
or else you can use fmt.Scan or fmt.Scanln as below.
func main() {
var someVar int
fmt.Scanln(&someVar)
}
You could also use bufio.NewReader to read an integer from the standard input.
The below program:
Prompts for an integer input
Creates a bufio.Reader to read from standard input
Reads input till it encounters a newline character '\n' (Note that this will only read a single integer. Space separated values will not work)
Removes the newline character
Converts string to int
package main
import (
"fmt"
"bufio"
"os"
"strconv"
"strings"
)
func getInt() error {
fmt.Println("Enter an integer")
userInput := bufio.NewReader(os.Stdin)
userVal, err := userInput.ReadString('\n')
if err != nil {
return err
}
input := strings.TrimSpace(userVal)
intVal, err := strconv.Atoi(input)
if err != nil {
return err
}
fmt.Printf("You entered: %d\n", intVal)
return nil
}
func main() {
getInt()
}
Why can't we just use a scanf? just like we use in C? it's working though.
package main
import "fmt"
func main() {
var i int
fmt.Scanf("%d", &i)
fmt.Println(i)
}

Looking for Go equivalent of scanf

I'm looking for the Go equivalent of scanf().
I tried with following code:
1 package main
2
3 import (
4 "scanner"
5 "os"
6 "fmt"
7 )
8
9 func main() {
10 var s scanner.Scanner
11 s.Init(os.Stdin)
12 s.Mode = scanner.ScanInts
13 tok := s.Scan()
14 for tok != scanner.EOF {
15 fmt.Printf("%d ", tok)
16 tok = s.Scan()
17 }
18 fmt.Println()
19 }
I run it with input from a text with a line of integers.
But it always output -3 -3 ...
And how to scan a line composed of a string and some integers?
Changing the mode whenever encounter a new data type?
The Package documentation:
Package scanner
A general-purpose scanner for UTF-8
encoded text.
But it seems that the scanner is not for general use.
Updated code:
func main() {
n := scanf()
fmt.Println(n)
fmt.Println(len(n))
}
func scanf() []int {
nums := new(vector.IntVector)
reader := bufio.NewReader(os.Stdin)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
i, _ := strconv.Atoi(f)
nums.Push(i)
}
str, err = reader.ReadString('\n')
}
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
}
Improved version:
package main
import (
"bufio"
"os"
"io"
"fmt"
"strings"
"strconv"
"container/vector"
)
func main() {
n := fscanf(os.Stdin)
fmt.Println(len(n), n)
}
func fscanf(in io.Reader) []int {
var nums vector.IntVector
reader := bufio.NewReader(in)
str, err := reader.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = reader.ReadString('\n')
}
return nums
}
Your updated code was much easier to compile without the line numbers, but it was missing the package and import statements.
Looking at your code, I noticed a few things. Here's my revised version of your code.
package main
import (
"bufio"
"fmt"
"io"
"os"
"strconv"
"strings"
"container/vector"
)
func main() {
n := scanf(os.Stdin)
fmt.Println()
fmt.Println(len(n), n)
}
func scanf(in io.Reader) []int {
var nums vector.IntVector
rd := bufio.NewReader(os.Stdin)
str, err := rd.ReadString('\n')
for err != os.EOF {
fields := strings.Fields(str)
for _, f := range fields {
if i, err := strconv.Atoi(f); err == nil {
nums.Push(i)
}
}
str, err = rd.ReadString('\n')
}
return nums
}
I might want to use any input file for scanf(), not just Stdin; scanf() takes an io.Reader as a parameter.
You wrote: nums := new(vector.IntVector), where type IntVector []int. This allocates an integer slice reference named nums and initializes it to zero, then the new() function allocates an integer slice reference and initializes it to zero, and then assigns it to nums. I wrote: var nums vector.IntVector, which avoids the redundancy by simply allocating an integer slice reference named nums and initializing it to zero.
You didn't check the err value for strconv.Atoi(), which meant invalid input was converted to a zero value; I skip it.
To copy from the vector to a new slice and return the slice, you wrote:
r := make([]int, nums.Len())
for i := 0; i < nums.Len(); i++ {
r[i] = nums.At(i)
}
return r
First, I simply replaced that with an equivalent, the IntVector.Data() method: return nums.Data(). Then, I took advantage of the fact that type IntVector []int and avoided the allocation and copy by replacing that by: return nums.
Although it can be used for other things, the scanner package is designed to scan Go program text. Ints (-123), Chars('c'), Strings("str"), etc. are Go language token types.
package main
import (
"fmt"
"os"
"scanner"
"strconv"
)
func main() {
var s scanner.Scanner
s.Init(os.Stdin)
s.Error = func(s *scanner.Scanner, msg string) { fmt.Println("scan error", msg) }
s.Mode = scanner.ScanInts | scanner.ScanStrings | scanner.ScanRawStrings
for tok := s.Scan(); tok != scanner.EOF; tok = s.Scan() {
txt := s.TokenText()
fmt.Print("token:", tok, "text:", txt)
switch tok {
case scanner.Int:
si, err := strconv.Atoi64(txt)
if err == nil {
fmt.Print(" integer: ", si)
}
case scanner.String, scanner.RawString:
fmt.Print(" string: ", txt)
default:
if tok >= 0 {
fmt.Print(" unicode: ", "rune = ", tok)
} else {
fmt.Print(" ERROR")
}
}
fmt.Println()
}
}
This example always reads in a line at a time and returns the entire line as a string. If you want to parse out specific values from it you could.
package main
import (
"fmt"
"bufio"
"os"
"strings"
)
func main() {
value := Input("Please enter a value: ")
trimmed := strings.TrimSpace(value)
fmt.Printf("Hello %s!\n", trimmed)
}
func Input(str string) string {
print(str)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return input
}
In a comment to one of my answers, you said:
From the Language Specification: "When
memory is allocated to store a value,
either through a declaration or make()
or new() call, and no explicit
initialization is provided, the memory
is given a default initialization".
Then what's the point of new()?
If we run:
package main
import ("fmt")
func main() {
var i int
var j *int
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j)
j = new(int)
fmt.Println("i (a value) = ", i, "; j (a pointer) = ", j, "; *j (a value) = ", *j)
}
The declaration var i int allocates memory to store an integer value and initializes the value to zero. The declaration var j *int allocates memory to store a pointer to an integer value and initializes the pointer to zero (a nil pointer); no memory is allocated to store an integer value. We see program output similar to:
i (a value) = 0 ; j (a pointer) = <nil>
The built-in function new takes a type T and returns a value of type *T. The memory is initialized to zero values. The statement j = new(int) allocates memory to store an integer value and initializes the value to zero, then it stores a pointer to this integer value in j. We see program output similar to:
i (a value) = 0 ; j (a pointer) = 0x7fcf913a90f0 ; *j (a value) = 0
The latest release of Go (2010-05-27) has added two functions to the fmt package: Scan() and Scanln(). They don't take any pattern string. like in C, but checks the type of the arguments instead.
package main
import (
"fmt"
"os"
"container/vector"
)
func main() {
numbers := new(vector.IntVector)
var number int
n, err := fmt.Scan(os.Stdin, &number)
for n == 1 && err == nil {
numbers.Push(number)
n, err = fmt.Scan(os.Stdin, &number)
}
fmt.Printf("%v\n", numbers.Data())
}

Resources