How to catch Tab keystroke in input? (ncurses) - c

I'm using ncurses and I'm getting input string with getstr(). I want to make something like autocompletion by Tab keystroke. However, I don't see a way to catch Tab with getstr(). I tried this:
char input = 0;
while (input != '\n')
switch (input = getch())
{
case '\t':
printw("Got Tab\n");
break;
default:
addch(input);
break;
}
But in this case I have to write my own handlings for Backspace, Delete etc., what is undesirable and essentialy is reinventing of wheel.

Maybe try:
switch (input = getch())
{
case KEY_STAB:
printw("Got Tab\n");
break;
default:
addch(input);
break;
}
Complete list of keys

This one works fine for me:
#include <cstdio>
#include <conio.h>
int main() {
char input = 0;
while (input != '\n') {
input = getch();
switch (input)
{
case '\t':
printf("T");
break;
case '\b':
printf("\b \b");
break;
default:
printf("%c", input);
break;
}
}
}
using the latest g++

Related

Trouble getting a switch function to loop properly

I'm writing a program to 'encrypt' an inputted string of text by using a switch statement to correlate the given character with a symbol, and output that symbol in the place of the character. I put it in a while loop, the idea being that it would loop the full switch function each time until the received character is EOF. On a guess, I believe it is looping through just the first character, because I don't advance the getchar() statement, but I'm not sure how to do that so any help would be greatly appreciated. I say this because if I use return instead of break, it closes the while loop and only takes that first letter, if I use a break then it spams the first 'encrypted' char.
#include <stdlib.h>
#include <stdio.h>
/* C program to encrypt a given text message, assuming all lowercase */
int main() {
int Input, Encrypted;
printf("Please type your message\n");
Input = getchar();
while (Input != EOF) {
switch (Input) {
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'");break;
return 0;
}
}
return 0;
}
The simplest solution would be to remove the line
Input = getchar();
and to replace the line
while (Input != EOF) {
with:
while ( (Input=getchar()) != EOF && Input != '\n' ) {
Alternatively, if you find this while condition too confusing, you could also use an infinite loop, instead, like this:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
switch ( c )
{
case 'a':printf("!"); break;
case 'b':printf("#"); break;
case 'c':printf("#"); break;
case 'd':printf("$"); break;
case 'e':printf("%%"); break;
case 'f':printf("^"); break;
case 'g':printf("&"); break;
case 'h':printf("*"); break;
case 'i':printf("`"); break;
case 'j':printf("~"); break;
case 'k':printf("-"); break;
case 'l':printf("_"); break;
case 'm':printf("="); break;
case 'n':printf("+"); break;
case 'o':printf("["); break;
case 'p':printf("{"); break;
case 'q':printf("]"); break;
case 'r':printf("}"); break;
case 's':printf(";"); break;
case 't':printf(":"); break;
case 'u':printf("|"); break;
case 'v':printf(","); break;
case 'w':printf("<"); break;
case 'x':printf("."); break;
case 'y':printf(">"); break;
case 'z':printf("'"); break;
}
}
return 0;
}
Note that most character sets (such as ASCII) store the characters a to z consecutively. With these character sets, you don't need the long switch statement. Instead, you can simplify it to the following:
#include <stdlib.h>
#include <stdio.h>
int main( void )
{
printf("Please type your message\n");
for (;;) //infinite loop, equivalent to while(true)
{
const char map[] = "!##$%^&*`~-_=+[{]};:|,<.>'";
int c;
c = getchar();
if ( c == EOF || c == '\n' )
break;
if ( 'a' <= c && c <= 'z' )
putchar( map[c-'a'] );
}
return 0;
}

Reading file line by line - why I get the first line only?

I have a task in university to write a C program which reads a file and counts the number of single and multi comments. The problem I have is that the second while() only reads the first line and so the returned comments are 0.
Previously I read the file character by character, but that's not the task requirement. Why does this program read only the first line and not the others?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char **argv) {
FILE *fp;
int c, i = 0;
char path[256], ch, line[80];
unsigned int multi = 0;
unsigned int single = 0;
enum states {
PLAIN_TEXT,
SLASH,
STAR,
SINGLE_COMMENT,
MULTI_COMMENT,
QUOTES
} state = PLAIN_TEXT;
printf("Write file's name\n");
gets(path)
fp = fopen(path, "r");
if (!fp) {
// give an error message
} else {
while (fgets(line, sizeof(line), fp) != NULL) {
while (i < sizeof(line)) {
printf("%d.%c", i, line[i]);
switch (state) {
case PLAIN_TEXT:
switch (line[i]) {
case '/': i++;
state = SLASH;
break; // found a slash. In the next loop the switch argument will be SLASH
case '"': i++;
state = QUOTES;
break; // found a quote. Quoted text (there might be a '//' inside)
default: i++;
break; // found an ordinary character
}
break;
case QUOTES:
switch (line[i]) {
case '"': i++;
state = PLAIN_TEXT;
break; // Gets out the string;
case ' ':i++;
state = PLAIN_TEXT;
break;
default: i++;
state = QUOTES;
break; // Still a quoted text;
}
break;
case SLASH:
switch (line[i]) {
case '/': i++;
state = SINGLE_COMMENT;
break; // found a slash => a possible single comment found
case '*': i++;
state = MULTI_COMMENT;
break; // found a star => a possible multi comment found
default: i++;
state = PLAIN_TEXT;
break; // found an ordinary character
}
break;
case STAR:
switch (line[i]) {
case '/': i++;
state = PLAIN_TEXT;
multi++;
break; // Increments the multi comment and the next characher will be treated as a plain_taxt
default: i++;
state = MULTI_COMMENT;
break; // Still multi comment
}
break;
case SINGLE_COMMENT:
switch (line[i]) {
case '\n':i++;
state = PLAIN_TEXT;
single++;
break; // End of the single comment line. Increment the counter and the next character will be treated as a plain_text
default: i++;
break;
}
break;
case MULTI_COMMENT:
switch (line[i]) {
case '*': i++;
state = STAR;
break; // Found a multi comment. The next state will be star.
default: i++;
break;
}
break;
default: i++;
break;
}
}
}
fclose(fp);
printf("Single-comment : %8u\n", single);
printf("Multi-comment : %8u\n", multi);
}
return 0;
}
To enumerate the characters on the line, you must reinitialize i to 0 for each line and stop at the null terminator or at the newline character

Why printf("\n") doesn't go to the next line?

I'm trying to write a short program that puts each word on a new line. The new line can be confirmed by tabulator, space or enter. The end of program is putting "#" in console. I have the problem that when I put "enter" to the console it writes next characters in the same line.
The second idea is to make all of this in a table, so I can put formatted text all together in the end. I can't figure this out either.
#include<stdio.h>
#include <conio.h>
#define STOP '#'
int main()
{
char ch;
while ((ch = (_getch())) != STOP) {
switch (ch) {
case '\n':
printf("\n");
break;
case '\t':
printf("\n");
break;
case ' ':
printf("\n");
break;
default:
putchar(ch);
}
}
printf("\nEND");
_getch();
return 0;
}
Because hitting "enter" issues a carriage return char (\r), not a linefeed one.
I noticed it when the cursor jumped back at the start of the line when I pressed "enter".
Fix your code like this (factorize the case statements too):
#include<stdio.h>
#include <conio.h>
#define STOP '#'
int main()
{
char ch;
while ((ch = (_getch())) != STOP) {
switch (ch) {
case ' ':
case '\t':
case '\r': // what was missing
printf("\n");
break;
default:
putchar(ch);
}
}
printf("\nEND");
_getch();
return 0;
}
You probably get a carriage return ('\r') which is what Return typically generates.
So you need to check for that, too. Your code can be simplified:
int main(void)
{
while((ch = _getch()) != STOP)
{
if(ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t')
ch = '\n';
putchar(ch);
}
}
Since we're always printing exactly one character per iteration, no need to use multiple printing functions. Also, using printf() to print a single constant character is overkill.

character comparison using switch

I'm comparing strings character by character.
Here's a part of my code that's causing problems:
switch(line[1]) {
case 'u':
switch(line[2]) {
case 't':
switch(line[3]) {
case 't':
switch(line[4]) {
case 'o':
switch(line[5]) {
case 'n':
switch(line[6]) {
case 's':
printf("buttons\n");
case ' ':
printf("not buttons\n");
break;
}
break;
}
break;
}
break;
}
break;
}
}
For line[6], if an s character exists it should print out "buttons", if there's a space, it should print out "not buttons"
If I have a config file that contains:
buttons 13
button 3
buttons 3
I get:
buttons
not buttons
buttons
not buttons
If I have:
buttons 3
I get:
buttons
not buttons
I get a "buttons" and "not buttons" for every buttons entry and get nothing for the "button 3" entry
thanks
You will always get not buttons when there is buttons because you are not breaking after case 's'.Therefore it won't stop when an line[6] is s.
And you used all these nested switches just to compare a string.Better use strcmp to check if its buttons or button.
Instead of complicating nested switch, use this
FILE * fi; // input file handle
char line[9], c;
while (feof(fi) == 0) {
// Read only required chars
fgets(line, 8, fi);
line[8] = '\0';
while ((c = getc(fi)) != '\n' && c != EOF);
// Simplified comparison
if (strncmp(line, "button", 6) == 0) {
if (line[6] == 's') printf("buttons\n");
else if (line[6] == ' ') printf("not buttons\n");
}
}
Here's a simpler, cleaner version of the code:
if (strncmp(line, "button", 6)==0)
{
if (line[6]=='s')
printf("buttons");
else printf("button");
}

Command Line Menu in C

I'm trying to implement a command line menu in C so that when the user enters a character, it will instantly process the character and carry out specific functions. The problem is, whenever I try to make it so that after each input is processed, the menu displays again and is ready for new input, the program will just continually read input and never process it unless I exit the program.
This is the code that works 1 time through:
char command;
command = getchar();
switch(command){
case 'c':
//create a new hash table;
break;
case 'l':
//look up a word;
break;
case 'f':
//read a file
break;
case 'p':
//print the table;
break;
case 'r':
//Remove a word
break;
case 'q':
exit(0);
break;
}
However, if I try to place it into an infinite loop to continually run, like I said, it will never process the inputs until I exit the program.
This code should work for you — it works for me. Note the use of int for the variable command.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
int command;
while ((command = getchar()) != EOF)
{
switch(command)
{
case 'c':
printf("Create a new hash table\n");
break;
case 'l':
printf("Look up a word\n");
break;
case 'f':
printf("Read a file\n");
break;
case 'p':
printf("Print the table\n");
break;
case 'r':
printf("Remove a word\n");
break;
case 'q':
printf("Quit\n");
exit(0);
break;
default:
printf("Unexpected input %d (0x%.2X) ('%c')\n",
command, command, isgraph(command) ? command : '.');
break;
}
}
return 0;
}

Resources