Why is my input not being passed into the if statements? - c

Here is my code:
#include "game.h"
#define LINEINPUT 30
int loadMainMenu(void);
void playGame()
{
Cell board[BOARD_HEIGHT][BOARD_WIDTH];
char input[LINEINPUT + EXTRA_SPACES];
printInstructions();
while( getchar() != '\n' );
initialiseBoard(board);
while(TRUE)
{
displayBoard(board, NULL);
printf("At this stage of the program, only two commands are acceptable:\n");
printf("load <g>\n");
printf("quit\n");
fgets(input, LINEINPUT , stdin);
if(input[strlen(input) - 1] != '\n')
{
printf("BUFFER OVERFLOW\n");
readRestOfLine();
EXIT_FAILURE;
continue;
}
if(strcmp(input, "test") == 0)
{
printf("success!\n");
continue;
}
if(strcmp(input, "load 1") == 0)
{
printf("lfdsfsdfoad");
loadBoard(board, BOARD_1);
continue;
}
if(strcmp(input, "load 2") == 0)
{
loadBoard(board, BOARD_2);
continue;
}
if(strcmp(input, "quit") == 0)
{
loadMainMenu();
break;
}
}
}
i have cut it down so that it doesn't take up too much space. I was editing some of it this morning trying to fix things up and somehow, it doesnt read my inputs anymore. Well it does read my inputs but doesnt use strcmp to check if input matches and run the functions in the if statements. It was working fine previously but i did not change anything much.

As evidenced by your first if statement, fgets() returns strings with the \n line ending present. You'll want to either strip off that character, or add it to the strings you're testing against.

Related

Is there a way i can prevent EOF in C?

So I'm scanning strings from a file and comparing them with the string from a stack. If i scan all the string from the file and don't find the one from the stack i want to rewind the file, pop the string from the stack and continue unless the stack is empty.
char buffer[ENOUGH];
while(fscanf(stream, "%s", buffer) != EOF)
{
if(strcmp(buffer, tos->string) == 0)
{
pop(&tos);
//do something with the string
}
// here i would need something to stop the EOF
}
I have a file like this:
02.01.2021 8:45 8:57 9:45
03.01.2021 15:40 16:30
05.01.2021 07:30 08:30
And stack contains:
01.01.2021 <- TOS
02.01.2021
03.01.2021
04.01.2021
So i need to find 01.01.2021 in file and if not there remove it from stack.
To avoid reading the stream till the end of file, just break from the loop. Also note that you should compare the return value of fscanf() to 1 to detect all cases of failure. fscanf() will not return 0 for the %s or %c conversions, but would do so for other specifiers in case of a match failure that does not happen at end of file. Also pass a maximum number of characters to avoid undefined behavior on long input strings.
char buffer[100];
while (fscanf(stream, "%99s", buffer) == 1) {
if (strcmp(buffer, tos->string) == 0) {
pop(&tos);
//do something with the string
break; // break from the loop.
}
}
rewind(stream);
Probably something like this:
while (1)
{
if (fscanf(stream, "%s", buffer) != EOF)
{
if (strcmp(buffer, tos->string) == 0)
{
if (stack is empty)
break;
pop(&tos);
//do something with the string
}
}
else
{
fseek(stream, 0, SEEK_SET);
}
}
This is untested code, but you should get the idea.
But there is something flawed in your algorithm anyway: what happens if strcmp(buffer, tos->string) is never true?
You can use a method,
#include <stdio.h>
void compare(){
char buffer[ENOUGH];
while(fscanf(stream, "%s", buffer) != EOF){
if(strcmp(buffer, tos->string) == 0){
//do something
}
}
}
int main(void) {
while(!stactIsEmpty()){
pop();
compare();
}
return 0;
}
This code is not tested. I hope you'll get the idea.

Char array being cleared after unrelated function call to fgets?

I'm creating a file management program for a project in C and I have this error which is probably obvious to most programmers but since I'm really bad I can't spot what I have done wrong. My main program is an interface which asks users for a file name and assigns it to the array fileName.
int main() {
char fileName[50];
assignFileName(fileName);
char option[2];
int checkInput;
do {
printf("File management program. Options :\n '1' for File operations (Create, copy, delete or display file)\n '2' for Line operations (Append, delete, display or insert line to file)\n '3' for General operations (Display change log or number of lines for file)\n '4' to select a new file\n '9' to exit program\n");
printf("aaa %s\n", fileName); //first printf check - prints "aaa" and value in fileName
checkInput = checkUserInput(option);
printf("aaa %s\n", fileName); // second printf check = prints only "aaa"
if (checkInput == 1) {
//... etc
}
void assignFileName(char *fileName) {
printf("Enter file name to operate on, or 'E' to exit the program.\n");
do {
if ((fgets(fileName, 50, stdin)) != NULL) {
if (fileName[strlen(fileName)-1] = '\n') {
fileName[strlen(fileName)-1] = '\0';
}
if (strlen(fileName) == 1 && *fileName == 'E') {
exit(0);
} else if (strlen(fileName) == 0) {
printf("Error : Please enter a file name or 'E' to exit.\n");
}
} else {
perror("Error assigning file name ");
}
} while (strlen(fileName) == 0);
}
I'm fairly sure this code is fine. There's probably lots of ways to make it more efficient and if anyone wants to offer their input I will take it into account. However, the problem is later on in the code. I have 2 printf statements to check the value of fileName. After the first one, everything seems to be alright but then the for the second one the value of fileName seems to be cleared, so something is clearly happening in checkUserInput. All checkUserInput does is check the user enters a single digit number :
void flush() {
int ch;
while ((ch = getchar()) != '\n' && ch != EOF) {
}
}
int checkUserInput(char *input) {
if (fgets(input, 3, stdin) != NULL) {
printf("you entered %c\n", input[0]);
if (input[1] == '\n') {
return 1;
} else {
flush();
printf("Error : Please enter one of the options given.\n");
}
} else {
printf("Error : Please try again.\n");
}
return 0;
}
I put more printf statements to error check and it seems after the call to fgets(input, 3, stdin) the value in fileName is cleared. Can anyone explain to me why this is the case? I'm not even passing the array fileName to checkUserInput so I don't even know how the program is changing it. This is a link to what the console displayed : (can't post images sorry not 10 rep).
https://cdn.discordapp.com/attachments/708320229737889832/802557193043050516/unknown.png
All help would be very appreciated. Thanks.
if (fileName[strlen(fileName)-1] = '\n') should be:
if (fileName[strlen(fileName)-1] == '\n')
Note that you can strip the trailing newline with this simple line:
filename[strcspn(filename, "\n")] = '\0';
error was char option[2] when it should be char option[3]. Thanks to #Nate Eldredge and #M Oehm

Reading in user input with space using scanf in a while loop?

I'm working on some code in which I am trying to read in the following commands, which will lead to certain functions in my program being called:
PRINT
INSERT 0,Folders,Folders for storing related papers,25
PRINT
QUIT
I have been trying different ways to read in this input, which comes from ./inventory test02/inventory02-actual.txt < test02/input02.txt > test02/actual02.txt, in which these commands shown above are in the file input-02.txt.
I've primarily been working with scanf, but have tried fgets, but I have had the most success to what I desire with scanf. I originally tried scanf("%s", command) and in this case, scanf does not take in whitespace so the program terminates.
//Keep re-prompting user for commands until you reach EOF{
while ((scanf("%[0-9a-zA-Z, ]s", command) == 1)) {
printf("====================\nCommand? ");
printf("%s\n", command);
if (strcmp(command, "PRINT") == 0) {
print(list);
} else if (strcmp(substring(command, START, INSERT_END), "INSERT") == 0) {
//Get the substring - this is the input after "INSERT"
char string[MAX_LEN_COMMAND];
strcpy(string, substring(command, OFFSET, strlen(command)));
insert(string, list);
} else if (strcmp(command, "PRINTREVERSE") == 0) {
printReverse(list);
} else {
printf("Invalid command passed.\n");
exit(EXIT_BAD_INPUT);
}
}
Currently, when I run my code, only the first command, "PRINT" is read in. It seems like I cannot read the next line of input from input-02.txt. Is there a way I can read in these commands properly? In addition, after my program reads in "INSERT", it then reads in "0,Folders,Folders for storing related papers,25" as a command, which it should not. It should go directly to the next command, which is "PRINT". I have tried using a continue statement after calling the insert method, but that did not work. Does anyone have any suggestions?
EDIT: Updating code with fgets.
Instead of posting all my functions that I called to above, I think passing a printf to show us what the command is might be simple enough for a reproducible example!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define OFFSET 7
#define START 0
#define INSERT_END 5
static const char *substring(char command[], int start, int end);
int main(int argc, char **argv)
{
//Get user input for commands
char command[500];
//Keep re-prompting user for commands until you reach EOF{
while (fgets(command, sizeof(command), stdin) != NULL) {
printf("====================\nCommand? ");
printf("%s\n", command);
if (strcmp(command, "PRINT") == 0) {
printf("%s", command);
} else if (strcmp(substring(command, START, INSERT_END), "INSERT") == 0) {
printf("%s", command);
} else if (strcmp(command, "PRINTREVERSE") == 0) {
printf("%s", command);
} else {
printf("Invalid command passed.\n");
exit(1);
}
}
}
static const char *substring(char command[], int start, int end)
{
int i = 0;
int j = 0;
char *sub;
sub = (char *)malloc(500 * sizeof(char));
for (i = start, j = 0; i <= end; i++, j++) {
sub[j] += command[i];
}
sub[j] = '\0';
return sub;
}
The output I get is:
====================
Command? PRINT
Invalid command passed.
Since you are reading a line, you will have better success with fgets.
char command[101];
while (fgets(command, 100, stdin))
{
// rest of the code can be the same
}

How to take a user command input of varying size and put it into an array

I'm creating two programs that form a game and will be communicating with each other where one of them is essentially a user, but I'm starting off with building one and typing myself to this first program.
I want to input commands such as 'turn d1d2d3d4d5d6' (where the di are dice rolls), 'rerolled d1d2d3d4d5d6' and so forth, theres a bunch of commands. I want my program called player to take these commands and they'll do something with it.
Just to begin with I'm trying to take the input using stdin and putting it in array, then checking the array to see if its a valid command. However I can't seem to use fgetc and the array correctly. What i'm doing currently is just to take the input, put into an array and print it.
I don't actually want it to be 128 size array, I want it to be completely adjustable but I don't know how to do this with fgets. The if loop to check if its NULL is to find out if an array is empty but that's defintely wrong, not sure what to put in place there.
while(1){
int i = 1;
char* command[128];
fgets(command, 128, stdin);
for (i=0; i < 128; i++){
if (command[i] == NULL){
printf("%c\n", command[i]);
}
}
return 0;
}
So to be specific my main goal right now is take a command such as 'eliminated p' from the user and command becomes command=["eliminated","p"]
sample code:
#include <stdio.h>
#include <string.h>
int main(void) {
while(1){
char command[128];
if(NULL == fgets(command, sizeof command, stdin))//or use getline
break;
if(strchr(command, '\n') == NULL){//Too long
printf("Too long\n");
while(getchar() != '\n')
;//clear input
continue;
}
char *operation = strtok(command, " \t\n");
if(operation == NULL){
printf("Empty command\n");
continue;
}
char *operand = strtok(NULL, " \t\n");;
if(operand == NULL){
printf("Empty operand\n");
continue;
}
printf("operation:%s\noperand:%s\n", operation, operand);
char *commands[] = {operation, operand};
//do stuff
}
return 0;
}

do - while loop with multiple conditions in C

I am trying to make a while - do loop to exit when the user types "exit" or "quit". For some reason that I can not understand, I simply can not make it happen. If I apply one of these conditions separately it works just fine, but I need to have both conditions simultaneously.
I searched online and I found several examples even on different programming languages, for example, (PHP) Do-While Loop with Multiple Conditions, (Python) How to do while loops with multiple conditions, (C++) Using multiple conditions in a do…while loop, etc. But no matter what procedure I am following I can make it work with both conditions simultaneously.
The ideal solution would be do add uppercase conditions also, but I can work with that later on as soon as I solve this problem.
Maybe a fresh pair of eyes see something that I am missing.
Sample of code is given below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CHARACTERS 250
#define MAX_USERNAME 12
#define MAX_USERS 1024
#define MIN_REQUIRED 3
#define MAX_PORT 65536
#define MIN_PORT 1
typedef struct rec {
char username[MAX_USERNAME];
char msg[MAX_CHARACTERS];
}RECORD;
/* Usage Instructions void because we do not have any return */
int help(void) {
printf("Usage: test.c [-s <arg0>] [-s <arg1>]\n");
printf("\t-s: a string program name <arg0>\n");
printf("\t-s: a string with a Nickname maximum characters %i <arg2>\n",MAX_USERNAME);
return (1);
}
int main(int argc, char **argv) {
if ( argc < MIN_REQUIRED ) {
printf ("Please follow the instructions: not less than %i argument inputs\n", MIN_REQUIRED);
return help();
}
else if ( argc > MIN_REQUIRED ) {
printf ("Please follow the instructions: not more than %i argument inputs\n", MIN_REQUIRED);
return help();
}
else {
RECORD *ptr_record;
ptr_record = (RECORD *) malloc (sizeof(RECORD));
if (ptr_record == NULL) {
printf("Out of memory!\nExit!\n");
exit(0);
}
char username_argv[MAX_USERNAME];
memset( username_argv, '\0', sizeof(username_argv) );
if (strlen(argv[2]) > 12 ) {
printf("Maximum characters for Nickname: %i\nPlease try again!\n", MAX_USERNAME);
exit(0);
}
strcpy( username_argv, argv[1] );
strncpy( (*ptr_record).username, username_argv, sizeof(username_argv) );
printf("Username pointer: %s\n", (*ptr_record).username);
do {
printf("Please enter your MSG: \n");
scanf ("%s", (*ptr_record).msg);
printf("User MSG: %s\n", (*ptr_record).msg);
//} while ((strcmp((*ptr_record).msg,"exit") != 0) || (strcmp((*ptr_record).msg, "quit") != 0));
//} while (strcmp((*ptr_record).msg, "exit") || strcmp((*ptr_record).msg, "quit") != 0);
//} while ((strcmp((*ptr_record).msg,"exit")) || (strcmp((*ptr_record).msg, "quit")) != 0);
//} while ((*ptr_record).msg != "quit" || (*ptr_record).msg != "exit");
} while (((*ptr_record).msg != exit) || ((*ptr_record).msg != ));
free(ptr_record);
return 0;
} /* End of else */
} /* End of main() */
Try:
} while ((strcmp((*ptr_record).msg,"exit") != 0) &&
(strcmp((*ptr_record).msg,"quit") != 0));
You want NOT (A OR B), not NOT A OR NOT B. Remember De Morgan's laws that say that NOT (A OR B) is the same as NOT A AND NOT B.
Using || is wrong as you will always have at least one condition (operand of ||) or another to be true.
Imagine you string is "exit" then:
(strcmp((*ptr_record).msg,"exit") != 0)
is false
but
(strcmp((*ptr_record).msg,"quit") != 0)
is true.
It means 0 || 1 which yields 1. Same (in the opposite) for the "quit" string (1 || 0 which yields 1). For other strings, both operand of || will be 1 and 1 || 1 yields 1.
It doesn't work, because you want to do the loop while the string is different from "exit" and the string is different from "quit".
If you use an OR, the condition will always be true, because the string can't have both values at the same time.
do {
printf("Please enter your MSG:\n");
scanf ("%s", (*ptr_record).msg);
printf("User MSG: %s\n", (*ptr_record).msg);
} while ((strcmp((*ptr_record).msg, "exit") != 0) && (strcmp((*ptr_record).msg, "quit") != 0));
All of the lines in your example use the logical OR operator || to test both conditions. Try to use the logical AND operator, &&, instead.
The problem with OR is that the way you've got it set up, the condition will always pass, so the application will never quit. If the user typed "quit", then the condition passes because he/she didn't type "exit". Likewise, if the user typed "exit", then he/she didn't type "quit", so the condition still passes. And, of course, if he/she didn't type either one, then the condition passes. That doesn't leave you with any way out of the loop.
Try out this. You should use the && operator because both the conditions need to be true to continue.
do {
printf("Please enter your MSG: \n");
scanf ("%s", (*ptr_record).msg);
printf("User MSG: %s\n", (*ptr_record).msg);
} while (((*ptr_record).msg != "exit") && ((*ptr_record).msg != "quit"));

Resources