How to get single keypress in D with getc()? - shell

I need to get user input (y/n) keypress in console.
How I can do it? I know that I can use readln, but is there any other way? I am trying to use getc()
import std.stdio;
import std.string;
import std.stream;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
but I am getting error:
source\app.d(6): Error: function core.stdc.stdio.getc (shared(_iobuf)* stream) is not callable using argument types (File)
next attempt:
char [] checkYesNo() #property
{
char [] key;
while(readln(key) != 'y')
{
}
return key;
}
This code compile, but failure at execution time with strange error "Error executing command run"

One library that does the single press is my terminal.d
https://github.com/adamdruppe/arsd/blob/master/terminal.d
It looks more complex than it is. Here's an example to get a single key:
import terminal;
void main() {
auto terminal = Terminal(ConsoleOutputType.linear);
auto input = RealTimeConsoleInput(&terminal, ConsoleInputFlags.raw);
terminal.writeln("Press any key to exit");
auto ch = input.getch();
terminal.writeln("Bye!");
}
To build, put terminal.d in your folder and then compile them together: dmd yourfile.d terminal.d.
First, you construct a terminal. The two types are linear or cellular. Linear outputs one line at a time, cellular goes "full screen" in the console.
Then, you make an input struct based on that terminal. The ConsoleInputFlags says what you want: do you want echo? Mouse input? etc. raw is the simplest one: it will send you plain keyboard input as they happen with relatively little else.
Then you can write to the terminal and get characters from the input. The input.getch() line fetches a single character, returning immediately when something is available without buffering. Other functions available on input include kbhit, which returns true if a key was hit so input is available, false if it isn't - useful for a real time game, being checked on a timer, or nextEvent, which gives full input support, including mouse events. The Demo in the terminal.d source code shows something with full support:
https://github.com/adamdruppe/arsd/blob/master/terminal.d#L2265
Another useful convenience function on terminal itself btw is getline, which grabs a full line at a time, but also lets the user edit it and offers history and autocomplete. terminal also offers a function called color to do colored output, and moveTo, useful in cellular mode, to move the cursor around the screen. Browse the code to learn more, if you're interested.

The error is because phobos is conflicting with the runtime.
std.stdio publicly imports core.stdc.stdio, and they both define stdin, but as different types. getc() really just calls fgetc( stdin ), so when the runtime tries calling getc(), it passes in the stdin from std.stdio instead of the correct one from core.stdc.stdio, resulting in the error.
The best way to get around the conflict is just to alias core.stdc.stdio as something else and then use the fully qualified name.
import std.stdio;
void main()
{
while (getc() != 'y')
{
writeln("try again");
}
}
auto getc()
{
import stdc = core.stdc.stdio;
return stdc.getc( stdc.stdin );
}
But beware that getc() uses a buffer internally, and won't return until the user presses the enter key, at which point it reads the first char from the buffer and returns that, and will continue to read the next char from the buffer for subsequent calls until it reaches the end. So entering nnn<enter> in the terminal window results in try again being printed 3 times. If you want a method that returns a single char without the need for the enter key, you'll need to look for a library solution, no standard functions for that exist in either C or D.
If you're not concerned with a cross-platform solution, there's a Windows-specific header that defines a getch() function which doesn't use a buffer and returns on every keystroke, rather than on enter. Just add this to your code and replace the call to getc() with a call to getch().
extern( C ) int getch();

How about:
import std.stdio;
void main(){
writefln("Enter something: ");
char entered;
do{
readf(" %c\n", &entered);
writefln("Entered: %s", entered);
}while(entered != 'y');
}
The important bit is the " %c\n".
%c tells readf to match a char rather than a string.

Related

catching Enter in a multiline Fyne Entry widget (more generally, calling "parent classes")

This question is more about Go than Fyne. Having extended Fyne's Entry widget is the prescribed fashion, I want to detect when Enter (Return) is pressed and use it as a signal that I need to act on the content of the Entry. I want Shift-Return to add a newline to the text without signalling that I need to act.
Given a struct that starts with
type myEntry struct {
widget.Entry
.....more... }
It's easy enough to add
func (m *myEntry) TypedKey(key *fyne.KeyEvent) {
if key.Name == "Return" {
///send m.Text somewhere...
} else {
//WRONG: m.(*widget.Entry).TypedKey(key) //give Key to Entry widget to process
}
}
but the else clause doesn't compile. So after having decided this isn't a Key I want to intercept, how do I give it back to widget.Entry? Other questions here about calling "base classes", which Go doesn't quite have, don't seem to cover this case.
I thought I could finesse this by adding
type myEntry struct {
widget.Entry
me *Fyne.Focusable
and setting me to the address of myEntry on creation, so I could simply call me.TypedKey. But keys were not handled, and then there was a crash. Setting me=&myNewEntryObject on creation apparently isn't sufficiently "widget.Entry-like" to win the day.
I know Go isn't an OO language, but extending a type and then redirecting calls back to the parent type is a fundamental programming technique; I'd go as far as saying there's no point in extending a struct if you can't get back to the "base struct's" behaviour from the extension. What am I missing?
Embedded types without a name can be referenced using the name of the type - so the following will work:
func (m *myEntry) TypedKey(key *fyne.KeyEvent) {
if key.Name == "Return" {
// send m.Text somewhere...
} else {
Entry.TypedKey(key)
}
}

Solving tcsncpy_s.inl assertion (line 24)

I've a fairly simple program which needs user input in the form of a text string. I've a CLR form with an edit box and I need to take that input and pass it into my class which just copies it to a member variable.
In the Form.h code, handling the TextChanged event is...
int textLength = m_userDest->TextLength;
if (textLength > 2 && textLength < 5)
{
// Could be an ICAO code in here
char dest[5];
String^ text = m_userDest->Text->ToUpper();
sprintf_s(dest, 5, "%s", text);
airTraffic.SetUserDest(dest);
}
My class (airTraffic) SetUserDest function is just
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
When this is run I get this debug assertion, it doesn't stay on the screen and automatically clears after a few seconds.
Debug Assertion Failed!
Program: ...sual Studio 2010\Projects\FSAirTraffic\Debug\FSAirTraffic.exe
File: f:\dd\vctools\crt_bld\self_x86\crt\tcsncpy_s.inl
Line: 24
Expression: ((_Dst)) != NULL && ((_SizeInBytes)) > 0
I don't have an f:\ drive so I'm guessing this is some internal Microsoft(?) code so I can't see the context of the assertion and exactly what it's problem is. I don't have a file called tcsncpy_s.inl on my machine.
If I don't call my class function then there's no assertion so I assumed that was the problem.
Curiously though, when stepping through the debugger the assertion occurs as I step out of the TextChanged event, with the rest of the functions operating as intended (as far as I can see).
Does anyone know what the problem is and how I can go about solving it?
I don't understand how your code works. You use m_userDest twice, first it appears to be a pointer to a structure of some sort, maybe a handle to a TextBox control:
int textLength = m_userDest->TextLength;
Later you pass it to strncpy_s, which needs a char*, not a pointer to some structure.
void CAirTraffic::SetUserDest(char* dest)
{
strncpy_s(m_userDest, 5, dest, 5);
}
While it's possible for a structure to implicitly convert to a char*, it's not possible for a structure pointer to do so. Perhaps there's a smart pointer involved? Or you are using the same member variable name for completely different purposes in different classes1?
In any case, strncpy_s is inspecting the value of its first argument and not liking it.
1 Note that the new "wisdom" saying not to use Hungarian notation has destroyed the ability to understand this code in textual form. We don't have an IDE providing mouseover information about the data type of variables. Applications Hungarian is still a good idea in the real world, despite how many "best practices" documents decry it. Amazing how many code style documents are written from a purely theoretical basis.

I am writing a chat app that will have irc style commands. What is the best way to structure the program to process those commands?

I am writing what is essentially a chat program. I want to include some special irc style commands in it and I just can't seem to conceptualize how to structure the program. I'm wondering if people could help me out from a high level perspective. I'm not looking for code, just ideas on how to best proceed.
My best attempt is to have a Command struct like below:
type Command struct {
name string // the name of the command
function string // the function that will be called upon match
help string // the help message for the command
regex string // the regex pattern that will run the command
}
and then have a slice of Commands and just iterate over that every time I receive a message from the client. If the received data matches the regex then have the reflect (I think this will work) package call "function". For some reason, I feel like there has to be a better way. I'm learning to code Go on my own and don't have resources available to me to bounce ideas off of. I would very much appreciate your thoughts on this.
In IRC style commands usually a command line looks like this:
/cmd [param1] [param2] ... [paramn]
When such a command is received, you can split it using strings.Split() to get the parts or tokens of the command. By this you will have the first token identifying the command.
You can build a map[string]Command map where you map from text commands to their Command structure. In this map you can get commands by simply indexing the map, e.g.:
cmdMap := make(map[string]Command)
// Populate map
textCmd := "/help"
cmd := cmdMap[textCmd]
If you want to have command aliases (e.g. you want /help and /h and /? all to do the same), you can store the list of aliases for each command and when you build the cmdMap, also add entries for all aliases to point to the same Command structure, in which case you should define it like this:
cmdMap := make(map[string]*Command)
helpCmd := &Command{...} // Create help command
cmdMap["/help"] = helpCmd
cmdMap["/h"] = helpCmd
cmdMap["/?"] = helpCmd
Note: you could also strip off the leading slash '/' and just use the rest of the command ("help", "h" and "?" in this case) to init your map, it's up to you.
Also you don't have to store the name of the function, functions in Go are values so you can have a function field in your Command struct and then you can call that function without reflection. For example:
func DoSomething() {
fmt.Println("Doing something...")
}
var someFv = DoSomething
// And now you can do:
someFv()
See Function types and Function literals in the Go Language Specification.
First off, you don't need to use reflect. You can have the Command struct contain a member with a func type.
type Command struct {
name string // the name of the command
f func(string) // the function that will be called upon match
help string // the help message for the command
regex regexp.Regexp // the regex pattern that will run the command
}
func processMessage(text string){
for _,cmd := range(allCmds){
if cmd.regex.MatchString(text){
cmd.f(text)
return
}
}
defaultAction(text) //or just add a catch-all with a regex of `.*`
}
Then you can add commands with a function of the appropriate signature:
cmd := Command{name: "foo",f: func(text string){fmt.Println(text)}}
it doesn't have to have exactly that signature. You can have it accept a connection or whatever. You also don't have to inline the function definition, you can reference any function you want that has the appropriate signature.

not receiving '>' after using at+cmgs

I am using SIM900 GSM module connect to my AVR microcontroller.My compiler is Code Vision AVR.
I want to send a message and I don’t want to use delay.I use an usart rx interrupt. I want to receive '>' in rx interrupt after sending number.Then send my meessage.
But '>' charachter wasn’t received. I am checking this process with a 'a' variable. First of all 'a' variable is equal to zero and after 1 minute is equal to 2. But it is never equal to 3. As a result my message haven't been sent. I can't find my problem!
interrupt [USART_RXC] void usart_rx_isr(void)
{
char status,data;
status=UCSRA;
data=UDR;
if ((status & (FRAMING_ERROR | PARITY_ERROR | DATA_OVERRUN))==0)
{
rx_buffer[rx_wr_index++]=data;
if(a==2)
{
if(data=='>')
a=3;
}
#if RX_BUFFER_SIZE == 256
// special case for receiver buffer size=256
if (++rx_counter == 0)
{
#else
if (rx_wr_index == RX_BUFFER_SIZE) rx_wr_index=0;
if (++rx_counter == RX_BUFFER_SIZE)
{
rx_counter=0;
#endif
rx_buffer_overflow=1;
}
}
}
void main()
{
//...rest of code
printf("at+cmgf=1%1c",enter);
printf("at+cmgda=%1c%s%1c%1c",q,del,q,enter);
while (1)
{
//...rest of code
RTC();
if(minute!=1*count)
flag1=0;
if(minute==1*count && flag1!=1)
{
flag1=1;
count++;
a=1;
}
if(a==1)
{
printf("at+cmgs=%1c%s%1c%1c",q,tel,q,enter);
a=2;
}
if(a==3)
{
printf("Ba salam\rTemperature=%d\rHumidity=%d\rWind Direction=%s\rWind Speed=%d%1c%1c",temperature(),humidity(),direct1,anemometer(),cz,enter);
a=0;
}
}
}
You are not doing proper parsing of the responses from the modem.
First of all, never, ever, ever use time as a separator for command and response. You MUST read and parse everything received from the modem until you get a final response. Absolutely nothing else will work reliably. See this answer for some hints on how to fix.
And secondly, for AT+CMGS you MUST wait for a sequence of four characters, \r\n>, before sending data. There is also hints about this in the above linked answer.
You appear to be sending commands using lower case letters. The user manual specifies capital letters, that is, AT not at.
There is also something wrong with the minute-count code at the top of the loop. The flag1 will be set back to 0, which will eventually change a to 1 again, which will cause the message to be sent again. I don't think this is your immediate problem but it should be corrected.
We also don't know if the message is getting through to the SIM900. Maybe trying testing this by sending the AT commands over a terminal and checking the return values. (Your code doesn't check if the first two commands are acknowledged by the SIM900, for example.)
EDIT:
Looking more closely, I see that your code is not following the protocol set out in the manual for sending a text. This may be because the manual has a typographical error. It has two sections labelled "Sending a Text", but one of them is actually for reading a text.
You don't need to include the AT+CMGDA=”DEL ALL” part. This is in the section for reading a text. Also, you have misspelled ”DEL ALL” as "DElALL".
The bigger problem is that sending the two commands so close together is clobbering the return codes.

C++(Visual Studio 2012): Copying a function's parameter char* to a dynamically allocated one

I have this structure defined and a class in my project. It is a class that holds id numbers generated by GetIdUsingThisString(char *), which is a function that loads a texture file into GPU and returns an id(OpenGL).
The problem is, when I try to read a specific file, the program crashes. When I run this program in VS with debugging it works fine, but running .exe crashes the program(or running without debugging from MSVS). By using just-n-time debugger I have found out that, for num of that specific file, Master[num].name actually contains "\x5" added(concatenation) at the end of the file path, and this is only generated for this one file. Nothing out of this method could do it, and I also use this type of slash / in paths, not \ .
struct WIndex{
char* name;
int id;
};
class Test_Class
{
public:
Test_Class(void);
int AddTex(char* path);
struct WIndex* Master;
TextureClass* tex;
//some other stuff...
};
Constructor:
Test_Class::Test_Class(void)
{
num=0;
Master=(WIndex*)malloc(1*sizeof(WIndex));
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");
Master[0].id=GetIdUsingThisString(Master[0].name);
}
Adding a new texture:(The bug)
int Test_Class::AddTex(char* path)
{
num++;
Master=(WIndex*)realloc(Master,(num+1)*sizeof(WIndex));
Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
strcpy(Master[num].name,path);<---HERE
Master[num].id=GetIdUsingThisString(path);
return Master[num].id;
}
At runtime, calling AddTex with this file would have path with the right value, while Master[num].name will show this modified value after strcpy(added "\x5").
Question:
Is there something wrong with copying(strcpy) to a dynamically allocated string? If i use char name[255] as a part of the WIndex structure, everything works fine.
More info:
This exact file is called "flat blanc.tga". If I put it in a folder where I intended it to be, fread in GetIdUsingThisString throws corrupted heap errors. If I put it in a different folder it is ok. If I change it's name to anything else, it's ok again. If I put a different file and give it that same name, it is ok too(!!!). I need the program to be bug free of this kind of things because I won't know which textures will be loaded(if I knew I could simply replace them).
Master[num].name=(char*)malloc(strlen(path)*sizeof(char));
Should be
Master[num].name=(char*)malloc( (strlen(path)+1) * sizeof(char));
There was not place for the terminating NULL character
From http://www.cplusplus.com/reference/cstring/strcpy/:
Copies the C string pointed by source into the array pointed by
destination, including the terminating null character (and
stopping at that point).
The same happens here:
Master[0].name=(char*)malloc(strlen("Default")*sizeof(char));
strcpy(Master[0].name,"Default");
Based on the definitions (below) - you should use strlen(string)+1 for malloc.
A C string is as long as the number of characters between the beginning of the string and the terminating null character (without including the terminating null character itself).
The strcpy() function shall copy the string pointed to by s2 (including the terminating null byte)
Also see discussions in How to allocate the array before calling strcpy?

Resources