I am playing around with Go. I want to make it so when someone enters 'hi' it prints hiii
Here is my code
package main
import (
"fmt"
"bufio"
"os"
)
func main(){
reader := bufio.NewReader(os.Stdin)
fmt.Println("Simple Shell")
fmt.Println("---------------------")
for {
fmt.Print("-> ")
text, _ := reader.ReadString('\n')
if (text == "hi") {
fmt.Println("hiii")
}
}
}
There is a trick to that: When using ReadString and ReadBytes function with a delimiter, the returned string (and bytes) contains the delimiter. That's why the condition is not true, your actual string is "hi\n" and not "hi".
In order to read from stdin, you can use the ReadLine function, or manually trim the end line characters with packages strings and bytes.
Also, you can use a Scanner, it reads lines by default. Here are some examples which all do the same job:
package main
import (
"bufio"
"bytes"
"fmt"
"os"
"strings"
)
func main() {
reader := bufio.NewReader(os.Stdin)
fmt.Print("-> ")
text, _, _ := reader.ReadLine()
if string(text) == "hi" {
fmt.Println("hii")
}
fmt.Print("-> ")
stext, _ := reader.ReadString('\n') // stext ends with '\n', it reads the delimiter
stext = strings.TrimRight(stext, "\n")
if stext == "hi" {
fmt.Println("hii")
}
fmt.Print("-> ")
text, _ = reader.ReadBytes('\n')
text = bytes.TrimRight(text, "\n")
if string(text) == "hi" {
fmt.Println("hii")
}
fmt.Print("-> ")
scanner := bufio.NewScanner(os.Stdin)
scanner.Scan()
stext = scanner.Text()
if stext == "hi" {
fmt.Println("hii")
}
fmt.Print("−> ")
scanner.Scan()
text = scanner.Bytes()
if string(text) == "hi" {
fmt.Println("hii")
}
}
Just add \n such that
if text == "hi\n" {
fmt.Println("hiii")
}
Related
Morning All
I am trying to put together an ASCII art generator which accepts a word as a command line argument and prints out in ASCII art. This is working so far however, instead of interpreting "\n" as a new line it is printing these characters as ASCII art as well. Any ideas on how I can print a new line instead?
I have tried splitting the argument using code below but doesn't seem to do anything:
split := strings.Split(wordArg[1], "\n")
fmt.Println(split)
This just prints out [hello\n].
I am printing using printf if there is anything I can add there to help interpret the \n as new line instead of as being part of the string.
I have added the whole code if it helps make sense of what I'm doing:
package main
import (
"bufio"
"fmt"
//"strings"
//"io/ioutil"
"log"
"os"
"strings"
)
func main() {
wordArg := os.Args
split := strings.Split(wordArg[1], "\n")
fmt.Println(split)
wordRune := []rune(wordArg[1])
f, err := os.Open("standard.txt")
if err != nil {
fmt.Println(err)
}
defer f.Close()
scanner := bufio.NewScanner(f)
var lines []string
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
log.Fatal(err)
}
for i := 0; i < 8; i++ {
for j := 0; j < len(wordRune); j++ {
if lines[int(wordRune[j])*9-287+i] == " " {
fmt.Printf(" ")
} else {
fmt.Printf(lines[int(wordRune[j])*9-287+i])
}
}
fmt.Print("\n")
}
}
Any help would be much appreciated.
Thanks
strings.ReplaceAll
func ReplaceAll(str, oldstr, newstr string) string
The Replace All function does as the name suggests, and replaces all occurrences of oldstr with newstr within str.
strings.ReplaceAll(os.Args[1], "\\n", "\n")
This will return a string containing the first argument from the command line, with newlines in place of a literal backslash and letter n.
I'm struglling to remove the "\ n" as a string delimiter when teh string is read from the keyboard. The objective is to identify the last letter of the string received by the keyboard input.
But it turns out that he does not identify "n" as the last letter. I think that he is save the "\n" as the last input.
Test: Try to write "ian" and it will result in "not found".
Note: I already tried use the "TrimSuffix" function, but don't solved the issue.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
str := bufio.NewReader(os.Stdin)
fmt.Println("Please enter a string:")
strReciv, _ := str.ReadString('\n')
//---------------------------------------------
s1 := strings.HasPrefix(strReciv, "i")
s2 := strings.Contains(strReciv, "a")
s3 := strings.HasSuffix(strReciv, "n")
if s1 && s2 && s3 {
fmt.Println("Found!")
} else {
fmt.Println("Not Found")
}
}
strings.Trim works for me, as this shows
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
str := bufio.NewReader(os.Stdin)
fmt.Println("Please enter a string:")
sin, _ := str.ReadString('\n')
strReciv := strings.Trim(sin, "\n")
//---------------------------------------------
s1 := strings.HasPrefix(strReciv, "i")
s2 := strings.Contains(strReciv, "a")
s3 := strings.HasSuffix(strReciv, "n")
if s1 && s2 && s3 {
fmt.Println("Found!")
} else {
fmt.Println("Not Found")
}
}
After a lot of investigation, finally worked :)
I need to remove the \r too.
package main
import (
"bufio"
"fmt"
"os"
"strings"
)
func main() {
str := bufio.NewReader(os.Stdin)
fmt.Println("Please enter a string:")
strIn, _ := str.ReadString('\n')
strReciv := strings.Replace(strIn, "\r\n", "", -1)
//---------------------------------------------
s1 := strings.HasPrefix(strReciv, "i")
s2 := strings.Contains(strReciv, "a")
s3 := strings.HasSuffix(strReciv, "n")
if s1 && s2 && s3 {
fmt.Println("Found!")
} else {
fmt.Println("Not Found")
}
}
Carriage Return
The term CRLF refers to Carriage Return (ASCII 13, \r ) Line Feed (ASCII 10, \n ). They're used to note the termination of a line, however, dealt with differently in today's popular Operating Systems.
In my code below I've set up a ReadString which reads user input and passes it along in a exec.Command.
This works just fine, but when I try to compare the string with a hardcoded string in vbscript (in this case I'm comparing it to "hello") it always fails even when the user input is "hello" as well.
If I just run the vbscript through the command line like this however...
cscript.exe script.vbs hello
...then the StrComp works as intended so I suspect that it's either a data type issue or there's some extra character that's passed along in the golang app.
Here's the main.go:
package main
import (
"fmt"
"os/exec"
"bufio"
"os"
)
func main() {
buf := bufio.NewReader(os.Stdin)
fmt.Print("Type something: ")
text, err := buf.ReadString('\n')
if err != nil {
fmt.Println(err)
} else {
args := []string{"./script.vbs", string(text)}
exec.Command("cscript.exe", args...).Run()
}
}
And here's the script.vbs
MsgBox(WScript.Arguments(0))
If StrComp(WScript.Arguments(0), "hello") = 0 Then
MsgBox("it's the same")
Else
MsgBox("It's not the same...")
End If
When working with windows, line endings are "\r\n". I don't know whether ReadString() should remove the delimiter, but even then text will contain an invisible \r. Use strings.TrimSpace to be on the save side:
package main
import (
"fmt"
"os/exec"
"bufio"
"os"
"strings"
)
func main() {
buf := bufio.NewReader(os.Stdin)
fmt.Print("Type something: ")
text, err := buf.ReadString('\n')
fmt.Printf("0 got: %T %v %q\r\n", text, text, text)
text = strings.TrimSpace(text)
fmt.Printf("1 got: %T %v %q", text, text, text)
if err != nil {
fmt.Println(err)
} else {
args := []string{"./script.vbs", string(text)}
exec.Command("cscript.exe", args...).Run()
}
}
output (of main; use your imagination for the VBScript MsgBoxes):
main
Type something: hello
0 got: string hello
"hello\r\n"
1 got: string hello "hello"
I'm trying to write a Go script that takes in as many lines of comma-separated coordinates as the user wishes, split and convert the string of coordinates to float64, store each line as a slice, and then append each slice in a slice of slices for later usage.
Example inputs are:
1.1,2.2,3.3
3.14,0,5.16
Example outputs are:
[[1.1 2.2 3.3],[3.14 0 5.16]]
The equivalent in Python is
def get_input():
print("Please enter comma separated coordinates:")
lines = []
while True:
line = input()
if line:
line = [float(x) for x in line.replace(" ", "").split(",")]
lines.append(line)
else:
break
return lines
But what I wrote in Go seems way too long (pasted below), and I'm creating a lot of variables without the ability to change variable type as in Python. Since I literally just started writing Golang to learn it, I fear my script is long as I'm trying to convert Python thinking into Go. Therefore, I would like to ask for some advice as to how to write this script shorter and more concise in Go style? Thank you.
package main
import (
"fmt"
"os"
"bufio"
"strings"
"strconv"
)
func main() {
inputs := get_input()
fmt.Println(inputs)
}
func get_input() [][]float64 {
fmt.Println("Please enter comma separated coordinates: ")
var inputs [][]float64
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if len(scanner.Text()) > 0 {
raw_input := strings.Replace(scanner.Text(), " ", "", -1)
input := strings.Split(raw_input, ",")
converted_input := str2float(input)
inputs = append(inputs, converted_input)
} else {
break
}
}
return inputs
}
func str2float(records []string) []float64 {
var float_slice []float64
for _, v := range records {
if s, err := strconv.ParseFloat(v, 64); err == nil {
float_slice = append(float_slice, s)
}
}
return float_slice
}
Using only string functions:
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
func main() {
scanner := bufio.NewScanner(os.Stdin)
var result [][]float64
var txt string
for scanner.Scan() {
txt = scanner.Text()
if len(txt) > 0 {
values := strings.Split(txt, ",")
var row []float64
for _, v := range values {
fl, err := strconv.ParseFloat(strings.Trim(v, " "), 64)
if err != nil {
panic(fmt.Sprintf("Incorrect value for float64 '%v'", v))
}
row = append(row, fl)
}
result = append(result, row)
}
}
fmt.Printf("Result: %v\n", result)
}
Run:
$ printf "1.1,2.2,3.3
3.14,0,5.16
2,45,76.0, 45 , 69" | go run experiment2.go
Result: [[1.1 2.2 3.3] [3.14 0 5.16] [2 45 76 45 69]]
With given input, you can concatenate them to make a JSON string and then unmarshal (deserialize) that:
func main() {
var lines []string
for {
var line string
fmt.Scanln(&line)
if line == "" {
break
}
lines = append(lines, "["+line+"]")
}
all := "[" + strings.Join(lines, ",") + "]"
inputs := [][]float64{}
if err := json.Unmarshal([]byte(all), &inputs); err != nil {
fmt.Println(err)
return
}
fmt.Println(inputs)
}
I am new in GoLang and I am encountering a problem with this condition:
Even if the input of the user is "1", it doesn't enter in the if statement.
package main
import (
"bufio"
"fmt"
"os"
"strconv"
"math"
"strings"
)
func prompt(toprint string) string{
if(toprint == ""){
toprint = "Enter text :";
}
reader := bufio.NewReader(os.Stdin);
fmt.Println(toprint);
text, _ := reader.ReadString('\n');
return text;
}
func main() {
choice := prompt("Please enter '1'");
if(strings.Compare("1",choice)==0||choice=="1"){
// D'ONT ENTER HERE EVEN WHEN choice=="1"
}else{
// Always go here
}
}
Thank you for your help.
This is because reader.ReadString returns all the text including the delimiter, so the string returned will be 1\n not just 1. From the documentation (my emphasis):
func (*Reader) ReadString
func (b *Reader) ReadString(delim byte) (string, error)
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.
Perhaps you want to do
return strings.TrimSpace(text)
at the end of prompt().
Thank you !
Here's the "prompt()" code which returns the correct input :
func prompt(toprint string) string{
if(toprint == ""){
toprint = "Enter text :";
}
reader := bufio.NewReader(os.Stdin);
fmt.Println(toprint);
text, _ := reader.ReadString('\n');
return text[0:len(text)-2];
}