I'm creating a menu driven program in C where I have to ask for user input, then use only the first character of the input in my program. In addition to the code below, I've also tried #define MAX_CHAR 1 and using it instead of EOF in the while loop, among other things.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void print_menu();
void uppercase(char *string);
int main()
{
char i = 0, c = 0;
char selection[0];
print_menu();
while((c = getchar()) != EOF)
{
selection[i++] = c;
selection[i] = '\0'; //insert NULL at end of string
uppercase(selection);
switch(selection[i])
{
case 'c':
uppercase(selection);
printf("%s\n", selection );
print_menu();
break;
case 'X':
printf("The program is exiting, Schuss!\n" );
exit(0);
default:
printf("\nYou entered: %s\n", selection);
print_menu();
break;
}
}
return 0;
}
void print_menu() //gives code for menu
{
printf("Select a menu item and hit enter: \n" );
printf("C) Convert the string to uppercase\n");
printf("M) Display this menu\n");
printf("X) Exit the program\n");
}
void uppercase(char *string)
{
int c = 0;
while (string[c] != '\0')
{
if (string[c] >= 'a' && string[c] <= 'z')
{
string[c] = string[c] - 32;
}
c++;
}
}
If I type Yes! when running the program, I expect the output to be
You entered: Yand then the menu prints.
Currently the output is
You entered: Y
Select a menu item and hit enter:
C) Convert the string to uppercase
M) Display this menu
X) Exit the program
You entered: YE
Select a menu item and hit enter:
C) Convert the string to uppercase
M) Display this menu
X) Exit the program
You entered: S
Select a menu item and hit enter:
C) Convert the string to uppercase
M) Display this menu
X) Exit the program
You entered: S!
Select a menu item and hit enter:
C) Convert the string to uppercase
M) Display this menu
X) Exit the program
You entered:
Select a menu item and hit enter:
C) Convert the string to uppercase
M) Display this menu
X) Exit the program
^C
I'm pretty sure it's a problem with the while loop, haven't figured out how to fix it though. Eventually I'll have more menu items and cases. So for example, the user will enter A and it'll print a then print the menu again to wait for the next menu selection until the user enters 'X' to exit. Also, I do know there are two function calls for uppercase and that's intentional at this point.
EDIT: I'm wanting getchar() to read one character as it's designed to do. Then do whatever matches the case for that character. Then print the menu again (this part is included in each case statement). Then repeat from step 1 (which is "read one character").
I've changed my code to put getchar() outside the while loop and set the loop to while(1) instead which does result in reading only one character but also creates an infinite loop printing You entered: B and the menu. So that's progress, kind of.
How to read a single character with getchar in C?
You can read ONLY a single character using getchar.
I have to ask for user input, then use only the first character of the input in my program.
You can do that by reading an entire line and using only the first character of the line.
char line[100]; // Make it large enough.
while( fgets(line, 100, stdin) != NULL )
{
uppercase(line);
char selection = line[0];
switch (selection)
{
...
}
}
How to read a single character with getchar in C?
Just in this way:
getchar();
By the way, you are overwriting some memory here:
char i = 0, c = 0;
char selection[0]; // What?! An array of 0 elements?!
...
selection[i++] = c; // Where are you storing the value?
selection[i] = '\0'; // Same here
And note that after some while loops, your i variable will have a value of 12? 34? 1234?, because you don't initilize it to 0 before you do selection[i++] = c, each time you do it.
even though the following code has no undefined behavior and does allow the user to input up to 128 characters, there is nothing in the OPs code, nor does this code that makes use of the first (up to) 4 characters
#include <stdio.h> // getchar(), prinf()
//#include <string.h>
//#include <stdlib.h> // exit(), EXIT_SUCCESS
#include <ctype.h> // toupper()
void print_menu( void );
//void uppercase( char *string );
#define MAX_CHARS (128)
int main( void )
{
size_t i = 0;
int c; // getchar() returns an int, not a char
//char selection[0];
char selection[ MAX_CHARS+1 ]; // +1 to allow for NUL terminator byte
print_menu();
while( i < MAX_CHARS && (c = getchar()) != EOF && 'X' != toupper(c) )
{
if( '\n' == c ) // ignore any newlines
continue;
selection[i++] = (char)toupper(c);
selection[i] = '\0'; //insert NUL byte at end of string
//uppercase(selection);
switch(selection[i-1]) // -1 because 'i' is the termination byte
{
//case 'c':
// //uppercase(selection);
// printf("%s\n", selection );
// print_menu();
// break;
//case 'X':
// printf("The program is exiting, Schuss!\n" );
// //exit(0);
// exit( EXIT_SUCCESS );
// break;
default:
printf("\nYou entered: %s\n", selection);
print_menu();
break;
}
}
printf("The program is exiting, Schuss!\n" );
//return 0; // not needed for 'main()' in modern C
} // end function: main
void print_menu() //gives code for menu
{
// note: C concatenates successive literal strings
printf("Select a menu item and hit enter: \n"
"X) Exit the program\n"
"any other key appends to input, except newline\n");
} // end function: print_menu
//void uppercase(char *string)
//{
// int c = 0;
// while (string[c] != '\0')
// {
// if (string[c] >= 'a' && string[c] <= 'z')
// {
// string[c] = string[c] - 32;
// }
// c++;
// }
//}
Related
I want to break this loop when the user press enters twice. Meaning, if the user does not enter a character the second time, but only presses enter again, the loop must break.
char ch;
while(1) {
scanf("%c",&ch);
if(ch=='') { // I don't know what needs to be in this condition
break;
}
}
It is not possible to detect keypresses directly in C, as the standard I/O functions are meant for use in a terminal, instead of responding to the keyboard directly. Instead, you may use a library such as ncurses.
However, sticking to plain C, we can detect newline characters. If we keep track of the last two read characters, we can achieve similar behavior which may be good enough for your use-case:
#include <stdio.h>
int main(void)
{
int currentChar;
int previousChar = '\0';
while ((currentChar = getchar()) != EOF)
{
if (previousChar == '\n' && currentChar == '\n')
{
printf("Two newlines. Exit.\n");
break;
}
if (currentChar != '\n')
printf("Current char: %c\n", currentChar);
previousChar = currentChar;
}
}
Edit: It appears that the goal is not so much to detect two enters, but to have the user:
enter a value followed by a return, or
enter return without entering a value, after which the program should exit.
A more general solution, which can also e.g. read integers, can be constructed as follows:
#include <stdio.h>
#define BUFFER_SIZE 64U
int main(void)
{
char lineBuffer[BUFFER_SIZE];
while (fgets(lineBuffer, BUFFER_SIZE, stdin) != NULL)
{
if (lineBuffer[0] == '\n')
{
printf("Exit.\n");
break;
}
int n;
if (sscanf(lineBuffer, "%d", &n) == 1)
printf("Read integer: %d\n", n);
else
printf("Did not read an integer\n");
}
}
Note that there is now a maximum line length. This is OK for reading a single integer, but may not work for parsing longer input.
Credits: chux - Reinstate Monica for suggesting the use of int types and checking for EOF in the first code snippet.
You can store the previous character and compare it with the current character and enter, like this:
char ch = 'a', prevch = '\n';
while(1){
scanf("%c",&ch);
if((ch=='\n') && (ch == prevch)){// don't know what needs to be in this condition
break;
}
prevch = c;
}
Note that the previous character by default is enter, because we want the program to stop if the user hits enter at the very start as well.
Working like charm now
char ch[10];
while(1){
fgets(ch, sizeof ch, stdin);
if(ch[0]=='\n'){
break;
}
}
In class I need to use scanf to get integers to work with. Problem is I do not know to end the while loop. I wait for '\n' in the code, but it is passing all tests. The program has to complete for grading.
How to make code work when input includes several '\n' in input and spacebars at the end of input.
All numbers are given with spacebar between.
# include <stdio.h>
int main()
{
int numbers;
char ch;
int stop = 0;
while(scanf("%d%c", &numbers, &ch))
{
if((ch == '\n') stop++;
#my_code
if (stop == 1) break;
}
while(scanf("%d%c", &numbers, &ch)) { if((ch == '\n') .... has a couple of problems.
If the line of input has only white-space like "\n" or " \n", scanf() does not return until non-white-space is entered as all leading white-spaces are consumed by "%d".
If space occurs after the int, the "\n" is not detected as in "123 \n".
Non-white-space after the int is discarded as in "123-456\n" or "123x456\n".
how to end loop?
Look for the '\n'. Do not let "%d" quietly consume it.
Usually using fgets() to read a line affords the more robust code, yet sticking with scanf() the goal is to examine leading white-space for the '\n'
#include <ctype.h>
#include <stdio.h>
// Get one `int`, as able from a partial line.
// Return status:
// 1: Success.
// 0: Unexpected non-numeric character encountered. It remains unread.
// EOF: end of file or input error occurred.
// '\n': End of line.
// Note: no guards against overflow.
int get_int(int *dest) {
int ch;
while (isspace((ch = fgetc(stdin)))) {
if (ch == '\n') return '\n';
}
if (ch == EOF) return EOF;
ungetc(ch, stdin);
int scan_count = scanf("%d", dest);
return scan_count;
}
Test code
int main(void) {
unsigned int_count = 0;
int scan_count;
int value;
while ((scan_count = get_int(&value)) == 1) {
printf("%u: %d\n", ++int_count, value);
}
switch (scan_count) {
case '\n': printf("Normal end of line.\n"); break;
case EOF: printf("Normal EOF.\n"); break;
case 0: printf("Offending character code %d encountered.\n", fgetc(stdin)); break;
}
}
I currently have a homework assignment and I used gets.
The professor said I should be using getchar instead.
What is the difference?
How would I change my code to use getchar? I can't seem to get it right.
code:
#include <stdio.h>
#include <string.h>
#include <strings.h>
#define STORAGE 255
int main() {
int c;
char s[STORAGE];
for(;;) {
(void) printf("n=%d, s=[%s]\n", c = getword(s), s);
if (c == -1) break;
}
}
int getword(char *w) {
char str[255];
int i = 0;
int charCount = 0;
printf("enter your sentence:\n"); //user input
gets(str);
for(i = 0; str[i] != '\0' && str[i] !=EOF; i++){
if(str[i] != ' '){
charCount++;
} else {
str[i] = '\0'; //Terminate str
i = -1; //idk what this is even doing?
break; //Break out of the for-loop
}
}
printf("your string: '%s' contains %d of letters\n", str, charCount); //output
strcpy(w, str);
// return charCount;
return strlen(w); //not sure what i should be returning.... they both work
}
gets() was supposed to get a string from the input and store it into the supplied argument. However, due to lack of preliminary validation on the input length, it is vulnerable to buffer overflow.
A better choice is fgets().
However, coming to the usage of getchar() part, it reads one char at a time. So basically, you have to keep reading from the standard input one by one, using a loop, until you reach a newline (or EOF) which marks the end of expected input.
As you read a character (with optional validation), you can keep on storing them in str so that, when the input loop ends, you have the input string ready in str.
Don't forget to null terminate str, just in case.
I am new to C programming.
I was curious as to see how much I have learnt C.
Therefore I thought of creating a program in which I could simply create a file and write in it.
The name of the file, I thought, should be less that 100 chars. But it doesn't matter if it is a string or one word or a letter.
I couldn't complete because I was stuck on fact that how to input a string for a file name(eg, Project work, New Doc1, etc)
So I wrote this;
int main()
{
int a = 0;
while(a != 5)
{
puts("Put a number: ");
scanf("%i", &a);
if(a == 1)
{
char name[30];
printf("Put a name: ->>");
for(int i = 0;i < 31 && name[i] != '\n';i++)
{
name[i] = getchar();
}
char ex[50] = ".txt";
strcat(name,ex);
printf("%s",name);
}
}
return 0;
}
The problem is while inputting the name, it doesn't stop at the next (when I press enter) and some how it is not printing the right file name either.
There's a lot of problems with you approach.
It's not good to mix scanf with another input primitives, you must flush stdin from any remaining characters.
Any string must end in '\0' in order to mark that string as complete. So you must reserve space to this character.
When you concat you must obey the limit of the string.
If you use printf, the string will be only displayed after flushing the stdout (when you put '\n' in the end of the string, flush is done)
Try this:
#include <stdio.h>
#include <string.h>
int main()
{
int a = 0;
while(a != 5)
{
int ch;
puts("Put a number: ");
scanf("%d", &a);
/* flush any remaining characters */
while ((ch=getchar()) != EOF && ch != '\n'); /* issue 1 */
if(a == 1)
{
int i = 0;
char name[30];
printf("Put a name: ->>");
fflush(stdout); /* issue 4 */
while ((ch=getchar()) != EOF && ch != '\n' && i < 25) /* issue 3 */
name[i++] = ch;
name[i] = '\0'; /* issue 2 */
/* flush any remaining characters [if input > 25 chars] */
if (ch != EOF && ch != '\n') while ((ch=getchar()) != EOF && ch != '\n');
char ex[50] = ".txt";
strcat(name,ex); /* issue 3 */
printf("%s\n",name);
}
}
return 0;
}
Also, consider use getline and atoi instead of getchar and scanf
#include<stdio.h>
main()
{
static char stop_char='y';
char input=0;
do{
printf("please input a character\n");
scanf("\n%c",&input);
}while(input!=stop_char);
}
hi I would like to ask how I would modify this code for the question: (It only accepts one input then prints it out. I want it to keep going until I hit enter (\n) twice.
#include <stdio.h>
#define MAXLENGTH 1000
int main(void) {
char string[MAXLENGTH];
fgets(string, MAXLENGTH, stdin );
printf("%s\n", string);
return 0;
}
I'm confused at the fgets(string, MAXLENGTH, stdin ); line, what does stdin mean/do?
EDIT: Chris, I've tried your way:
#include <stdio.h>
#define MAXLENGTH 1000
int main(void) {
char string[MAXLENGTH];
do {
if (!fgets(string, MAXLENGTH, stdin ))
break;
printf("%s", string);
}
} while (string[0] != '\n');
return 0;
}
It prints after i hit enter but i want to type the whole list first then allow it to print the list after I press enter twice.
Try this:
#include <stdio.h>
#include <string.h>
#define MAXLENGTH 1000
int main(void)
{
char string[MAXLENGTH];
int i = 0;
for(;;++i)
{
string[i] = getchar();
if (i > 0 && string[i] == '\n' && string[i-1] == '\n') break;
}
string[i] = 0;
printf("Print it again:\n%s",string);
return 0;
}
do {
if (!fgets(string, MAXLENGTH, stdin ))
break;
printf("%s", string);
} while (string[0] != '\n');
will keep reading input and printing it until it sees a blank line (hitting enter twice in a row) or until EOF.
stdin refers to the program's standard input, which is whatever input source it is connected to when you run it. If you're just running it at the command line with no extra shell redirections, that will be the keyboard.
If you want to make entire input to be printed after the return key is pressed twice you can do:
char string[MAXLENGTH]; // to hold a single input line.
char strings[MAXLENGTH]=""; // to hold the entire input lines.
do {
if (fgets(string, MAXLENGTH, stdin ) == NULL)
break;
strcat(strings,string);
} while (string[0] != '\n');
printf("%s", strings);