I have written a console application that waits for the user char input.
application has function:
typedef char *ProcessedDataType;
extern ProcessedDataType askUserInput(void){
int i = getchar();
ProcessedDataType local_var = userInputProcessed(i);
return ProcessedDataType;
}
static ProcessedDataType userInputProcessed(int i){
...
return PocessedDataType;
}
Now, I would like to test this function for several inputs. So where normally the cursor would be blinking for user input, now, automatically, entries from a file that contains the choice letters returns. This would then be asserted against the known result.
runTest{
// when console gets input 'A'
ProcessedDataType local_var = askUserInput();
assert('ProcessedA' == local_var); }
// when console gets input 'B'
ProcessedDataType local_var = askUserInput();
assert('ProcessedB' == local_var); }
// when console gets input 'C'
ProcessedDataType local_var = askUserInput();
assert('ProcessedC' == local_var); }
How do I provide the same string parameters to this function when testing? How do I 'feed' the console the inputs A, B, C, etc ...
I do not want to use Preprocessors as here: How to unit test c functions involving IO?
Other than the obvious that "getchar" is only going to collect one character.... I've therefore replaced this method with a method "getchars", but you can eventually replace with what you actually need.
You're going to need to mock the method that would collect user input, in your test.
#define getchars mockgetchars
const char* expected;
char mockgetchars() {
return expected;
}
expected = "AAAAAAA\n";
ProcessedDataType local_var = askUserInput();
assert("AAAAAAA", local_var);
Related
I have a successfully written encryption code that asks the user if they want a left shift or right shift and how much they want to shift by.The goal is to make the program work through functions. I was able to get the first part of the code into a function (school programming exercise), but I am stuck on getting the user input. The function is getValidMessage(); I know I've called it correctly in the main code. I think the issue might be with null terminating the string, but I can't figure out what's wrong.
I have a line of code that should null-terminate it, and I think I made enough changes to the original code that it should work. However, I'm not sure that I implemented the code correctly in the function.
// get message to encrypt
//This is called in the main function
char originalMessage[100];
getValidMessage(&originalMessage, sizeof(originalMessage));
int originalMessageLength = strnlen(originalMessage,
sizeof(originalMessage));
//This is the function
/*
* Gets valid message from user
*/
void getValidMessage(char* message, int messageSize)
{
char originalMessage[100];
bool validMessage = false;
printf("\n");
printf("Enter message to be encrypted (upper case alphabetic
characters only): ");
fgets(originalMessage, messageSize, stdin);
int originalMessageLength = strnlen(originalMessage,
messageSize) - 1;
while (!validMessage)
{
// invalid if non-upper case alpha characters in
// message (don't include newline at end))
validMessage = true;
for (int i = 0; i < originalMessageLength; i++)
{
if (!isupper(originalMessage[i]))
{
printf("\n");
printf("Message must contain only upper "
"case alphabetic characters!\n");
printf("Enter message to be encrypted "
"(upper case alphabetic characters only):");
fgets(originalMessage, messageSize, stdin);
originalMessageLength =
strnlen(originalMessage, messageSize) - 1;
// reset flag and exit for loop
validMessage = false;
break;
}
}
}
originalMessage[originalMessageLength] = '\0';
return originalMessage;
}
I am using a running test code that uses MESSAGE. The entirety of the code should encrypt and decrypt the code to show OGUUCIG and then MESSAGE again. Currently, it just shows a bunch of weird characters.
Note: This is NOT the entirety of the code. It doesn't show the encryption or decryption code. I know that works fine, but I can't get it to work smoothly with a separate function instead of in the main body of the code.
The two functions are about 200 lines since its a bunch of case statements (and they do work properly) so instead of showing I'll just explain what it does. I am currently creating a game similar to checkers.
Function 1: Checks if user input a valid move. If they did not then it would print out "invalid move".
Function 2: Updates the piece that has been moved on the board and displays the new updated board.
In the main function I did a while loop so if user input an invalid move, they will be prompted again. It does that but the board would still be updated. For example: if they chose to move piece 1 to a spot that piece 3 is occupying, the board will update: piece 1's spot is now empty even though it printed out "invalid move". I do not know how to stop function 2 if function 1 printed something.
Here is what I put in the main function.
char pieceToMove, emptySpot;
int moveNumber = 0;
int piecesOnBoard = 15;
while (piecesOnBoard >= 1, ++moveNumber) {
//prompting user input
printf("%d. Enter your move:", moveNumber);
scanf(" %c %c", &pieceToMove, &emptySpot);
checkMoves(pieceToMove, emptySpot, all, the, pieces, ect);
updateBoard(all, the, pieces);
}
Have function 1 return the equivalent of a Boolean value (1 or 0 — true or false, respectively, in C) depending on whether function 1 was successful or if it failed. Check that value before deciding to run function 2 (or not).
One way to do this is define a boolean_t convenience type and kTrue and kFalse values in your header file. These are int values underneath the hood, but this makes code easier to read:
typedef enum boolean {
kFalse = 0,
kTrue
} boolean_t;
In your header file, declare that your first function function_one() will return a boolean_t:
boolean_t function_one(...); /* "..." are the arguments this function takes */
In your implementation file, you write function_one() so that it returns either kTrue or kFalse, depending on whether its work succeeds or fails:
boolean_t function_one(...) {
do_stuff();
if (some_step_fails) {
return kFalse;
}
return kTrue;
}
Again in the implementation file, write the call to function_two() so that it runs only if the return value of function_one() was kTrue:
if (function_one(...) == kTrue) {
function_two();
}
else {
fprintf(stderr, "Error: Something went wrong...\n");
}
I have an assignment due and I am drawing a blank on what exactly to do... I'm sure it is simple but I havent quite gotten the hang of things yet. The assignment is -
Write a program that gives the user 2 menu options: either call a function that will print a greeting and your name 4 times or call a function that will count down from 10 to 0 and then print "Blastoff!". Both functions should use for loops to print the appropriate output.
I have the prompt and the functions done so far... but I am unsure of how to display one or the other depending on the choice the user makes. Thank you for your help.
#include <stdio.h>
int main (void){
// declare counter variable
int i;
// prompt the user to make a choice
printf("What would you like to do?\n 1. Print my name\n 2. Count down from 10\n");
printf("\n");
// display greeting and name 4 times
for(i=1;i<=4;i++)
{
printf("Hi, my name is Bridget\n");
}
// display countdown
for(i=10;i>=0;--i)
{
printf("%d\n", i);
}
printf("Blastoff!");
}
You should read the input from user's keyboard:
int c;
c = getchar();
if (c == '1')
{
// display greeting and name 4 times
for(i=1;i<=4;i++)
{
printf("Hi, my name is Bridget\n");
}
}
if (c == '2')
{
// display countdown
for(i=10;i>=0;--i)
{
printf("%d\n", i);
}
}
printf("Blastoff!");
you should use Switch case.
switch(choice) {
case 1: //first for loop
break;
case 2: //second for loop
break;
}
Looks like you are missing a couple of points here. Firstly, you have not yet written any functions. Try looking here to gain some insight on that front.
Secondly, to make a choice based on user input you need to actually get that input somehow. You'll probably want to use scanf.
Lastly, once you have the user's input (say, in a variable declared as int input;) you can use if to control the flow of your program based on that variable like this:
if(input == 1){
greet();
}
else {
countDown();
}
Cheers! If you have any further questions feel free to comment below.
First of all you haven't actually declared you functions. Functions in C should be declared like the main function is. For more info in this see here.
// display greeting and name 4 times
void greeting(){
for(i=1;i<=4;i++)
{
printf("Hi, my name is Bridget\n");
}
}
void countdown() {
// display countdown
for(i=10;i>=0;--i)
{
printf("%d\n", i);
}
printf("Blastoff!");
}
To get the user's input the most common way is by keyboard. scanf accomplishes that in C. Details on scanf here
int main(void){
int i, choice;
//prompt the user to make a choice
// You don't need 2 printf for the newlines stick them to one.
printf("What would you like to do?\n 1. Print my name\n 2. Count down from 10\n\n");
//This takes the user's input and puts it in the variable choice
scanf(%d, &choice);
}
Lastly to decide what to do based on the user input you can use either an if then else statement or a switch. I will provide a solution with an if statement and you can figure the one with the switch on your own. Your final code should look like this.
int main(void){
int i, choice;
//prompt the user to make a choice
// You don't need 2 printf for the newlines stick them to one.
printf("What would you like to do?\n 1. Print my name\n 2. Count down from 10\n\n");
//This takes the user's input and puts it in the variable choice
scanf(%d, &choice);
if(choice == 1){
greeting();
}else{
countdown();
}
}
// display greeting and name 4 times
void greeting(){
for(i=1;i<=4;i++)
{
printf("Hi, my name is Bridget\n");
}
}
void countdown() {
// display countdown
for(i=10;i>=0;--i)
{
printf("%d\n", i);
}
printf("Blastoff!");
}
Bear in mind that this code has a lot of flaws (error checking mainly) but I guess your assigment is not about that.
First of all you need to include libraries with function you will need. You do this by
#include <someLibrary.h>
at the beggining of you document. Libraries mostly have .h extension. Always look for them if you try to do something. You consider them to have best performance and functionality as possible (not always true).
What is next you declare your functions. Function has name, arguments which are going into it, body in which they do something and return value (can be float, int, char etc). If function doesnt return anything, they return void (dont have return at the end). You declare functions before main() with only types of arguments. Whole body is after main (it is better looking).
If you declared function with arguments, you have to provide these arguments to function in () brackets. Even if no arguments are needed, you use them like getch() in example below. Note that function become what it return. If you declared some new variables in function they will be visible only in function. On the other hand function will not see any variable from other function (main too). If you want so, declare global variables (not recommended).
#include <stdio.h>
#include <conio.h> //libraries
void function1(int);
float function2(float); //declaration of functions
int main()
{
char decision;
printf("press 'a' to run function1, press 'b' to run function2\n");
decision=getch(); //first see getch()? look in google for functionality and library !
int someInt=10;
float someFloat=11;
if(decision== 'a')
{
function1(someInt);
}
else if(decision == 'b')
{
printf("%f", funcion2(someFloat)); //example that function become what they return
}
else
{
printf("No decision has been made");
}
getch(); //program will wait for any key press
return 0;
}
void function1(int param1)
{
//print your stuff // this function return void, so doesnt have return; statement
}
float function2(float param1)
{
return 2*param1; //this function have to return some float
}
I'm new to the Gnu Readline library.
I need to call the readline() function when the cursor is at the very last line of the console. But I need to prevent scrolling down when the Return key is pressed; so I'm looking for a way to prevent the output of the carriage return : I'm sure it's possible, but can't find the way to do it.
I tried to use my own rl_getc_function() to trap the Return key (the example below traps y and z keys, but it's just for test purposes) and treat this key in a special way:
My first idea was to run the accept-line command directly, thinking it would not output a carriage return, but actually, it does
My second idea was to redirect the output to /dev/null before calling the accept-line command; but the redirection doesn't seem to apply when the readline() function is already running.
Here is an example of my tests:
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
FILE *devnull; // To test output redirecting
int my_getc(FILE *file)
{
int c = getc(file);
// Let's test something when the 'y' key is pressed:
if (c == 'y') {
// I was thinking that calling "accept-line" directly
// would prevent the output of a carriage return:
rl_command_func_t *accept_func = rl_named_function("accept-line");
accept_func(1, 0);
return 0;
}
// Another test, when 'z' key is pressed:
if (c == 'z') {
// Try a redirection:
rl_outstream = devnull;
// As the redirection didn't work unless I set it before
// the readline() call, I tried to add this call,
// but it doesn't initialize the output stream:
rl_initialize();
return 'z';
}
return c;
}
int main()
{
devnull = fopen("/dev/null", "w");
// Using my function to handle key input:
rl_getc_function = my_getc;
// Redirection works if I uncomment the following line:
// rl_outstream = devnull;
readline("> "); // No freeing for this simplified example
printf("How is it possible to remove the carriage return before this line?\n");
return 0;
}
I'm sure I missed the right way to do it; any help would be appreciated.
I found it : the rl_done variable is made for this.
If I add this code to my my_getc() function, it works well:
if (c == '\r') {
rl_done = 1;
return 0;
}
No carriage return is then inserted, and my next printf() call displays just after the last char I typed.
I am able to limit the user input to 5 characters using GNU readline:
#include <readline/readline.h>
#include <stdio.h>
#include <stdlib.h>
static int limit_rl(FILE *f)
{
if (rl_end > 5) {
return '\b';
}
return rl_getc(f);
}
int main(void)
{
char *str;
rl_getc_function = limit_rl;
str = readline("> ");
printf("%s\n", str);
free(str);
return 0;
}
But, how to read an input with a default value (not a prompt), e.g.:
> ummy
^ cursor here
if user types d and Enter return "dummy"
if user types DEL and Enter return "mmy"
On the homepage of readline a possible use is mentioned:
rl.c is an example program that uses Readline to read a line of input from a user and echo it to the standard output, suitable for use by shell scripts.
and since editing an existing entry could well be part of this, I decided to take a look at its source (direct download link). This indeed shows how to insert a string into the buffer used by readline before it appears on the screen, through the use of a hook function:
Variable: rl_hook_func_t * rl_startup_hook
If non-zero, this is the address of a function to call just before readline prints the first prompt.
(https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#IDX223)
Inside the hook function you can directly manipulate the internal buffer, for example to insert text:
Function: int rl_insert_text (const char *text)
Insert text into the line at the current cursor position. Returns the number of characters inserted.
(https://cnswww.cns.cwru.edu/php/chet/readline/readline.html#IDX295)
The hook function only needs to do this once (it is called only once per readline call inside readline_internal_setup), but apparently rl's author went for the belt-and-suspenders approach and specifically disables it after it has been used.
Relevant snippets from rl.c, comments are mine:
/* a global char * to hold a default initial text */
static char *deftext;
/* the callback function. The argument is supposed to be 'void' per
its declaration:
typedef int rl_hook_func_t (void);
so you cannot provide the default text here */
static int set_deftext ()
{
if (deftext)
{
/* Apparently the "current cursor position" in which text is inserted
is 0, when initially called */
rl_insert_text (deftext);
deftext = (char *)NULL;
/* disable the global 'rl_startup_hook' function by setting it to NULL */
rl_startup_hook = (rl_hook_func_t *)NULL;
}
return 0;
}
// ...
if (deftext && *deftext)
rl_startup_hook = set_deftext;
temp = readline (prompt);