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

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
}

Related

C strtok() and strcmp() issues

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int args, char* argv[])
{
const int CBUFF = 1024;
char input[CBUFF];
char wkdir[CBUFF];
char* command;
printf("Welcome to MyShell...\n");
while(1)
{
getcwd(wkdir, CBUFF);
printf("%s ? ", wkdir);
fgets(input, CBUFF, stdin);
command = strtok(input, " ");
if(strcmp(command, "cd") == 0)
{
char* path;
path = strtok(NULL, " ");
if(chdir(path) != 0)
{
printf("ERROR: COULD NOT CHANGE DIRECTORY TO SPECIFIED PATH");
}
}
if(strcmp(command, "exit") == 0) break;
}
return 0;
}
I am running into an issue creating a very simple command shell in C. The input is only being read the way I want it too when I add a space after my directive. I know that it has something to do with my improper use of the strtok() function but am not able to figure out what I am doing wrong. I have read the documentation of <string.h> and am turning up blank.
Behavior I want:
Directive "exit" to exit from program.
Current behavior:
Must add space after directive to get it to parse correctly ie. "exit " or "cd " is entered.
You left the trailing newline in the buffer. Get rid of it.
char *got = fgets(input, CBUFF, stdin);
if (!got) return ; /* EOF -- treat like exit */
size_t gotlen = strlen(got);
if (got[gotlen] == '\n') got[gotlen] = 0;

Segmentation Fault With Strcmp With One Input

I am having an issue with the following code.
I have a global variable
char tokens[512][80];
Along with code:
int main(int argc, char** argv) {
char *input = malloc(sizeof(char) * 80);
while (1) {
printf("mini-shell>");
fgets(input, 80, stdin);
parse(input);
if (strcmp(tokens[0], "cd") == 0) {
cd();
}
else if (strcmp(tokens[0], "exit") == 0) {
exit(1);
}
}
}
void parse(char str[]) {
int index = 0;
char* str_ptr = strtok(str, " ");
while (str_ptr != NULL) {
strcpy(tokens[index], str_ptr);
str_ptr = strtok(NULL, " \0\r\n");
//printf("%d\n", index);
index = index + 1;
}
}
I found that if I enter exit for stdin I get a Segmentation fault, but if I enter cd .. for stdin I don't. Why is this so?
We don't know what the definition of the cd() function is, but there are a number of things that you may wish to consider in this program.
First, I don't believe there's any benefit to dynamically allocating 80 bytes of memory for the input buffer when you can easily do so automatically on the stack with char input[80]; - this is free and easy and requires no deallocation when you're done.
If you do this, you derive the size with fgets(input, sizeof input, stdin) where if you change the size of your input line from 80 to some other number, you only have to change it once: the sizeof on an array pulls the size directly.
Your parse() routine needs a little bit of help also. It's a really good idea to declare the function via the extern as shown so that when the compiler sees you call the function in the loop (right after the fgets), it knows the parameter and return types. Otherwise it has to make assumptions.
Because parse() is splitting apart the line you read from input, it's not required to copy the strings to some other place, so you can turn tokens from a multi-dimensional array into a simple array of pointers. As you run strtok() through the line to split up the parameters, you can store just the pointer, knowing that they will be pointing to stable data until the next fgets().
Also: your code does not strictly require or use this, but adding a NULL pointer to the end of the tokens list is a really good idea: otherwise, how does the caller know how many parameters were actually entered? This code checks whether the user entered just a blank line or not.
We've also change the loop around a little bit so the strtok() is called just once instead of twice, including the \n as noted in the comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *tokens[512];
extern void parse(char *str);
int main(int argc, char** argv) {
char input[80];
while (1) {
printf("mini-shell> "); fflush(stdout); // make sure user sees prompt
fgets(input, sizeof input, stdin);
parse(input);
if (tokens[0] == NULL) continue; // user entered blank line
if (strcmp(tokens[0], "cd") == 0) {
cd();
}
else if (strcmp(tokens[0], "exit") == 0) {
exit(1);
}
}
}
void parse(char *str) {
int index = 0;
char* str_ptr;
while ( (str_ptr = strtok(str, " \n")) != NULL)
{
tokens[index++] = str_ptr;
str = NULL; // for next strtok() loop
}
tokens[index] = NULL;
}

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;
}

Strange output from custom string object

I'm working on the second half of a program for class and the objective of the program is simple, but I can't figure out what's causing this output for my program. Basically, we have to read a file, using a function we wrote for the string header. We should then print out all the four-letter words in that file, obviously ignoring punctuation and whitespace. I've got the logic for that down, but what I can't figure out is why, even though I check to see if the length of the string is 4 before printing it, I sometimes get output that's clearly longer than 4. Here is input text from the file I'm using.
This is a test of the program which will only print out the four letter words in this file. Let's see if it works!
And this is the output I'm getting...
This
test
willham
onlyham
fourtam
thissrm
filesrm
Here is the main program: http://pastebin.com/xviETPFm
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "mystring.h"
int fTerminate(char ch, int * pbDiscardChar);
int main(int argc, char ** argv) {
MYSTRING str;
FILE * in;
if((str = mystring_init_default()) == MYSTRING_STATUS_ERROR) {
printf("Error initializing MYSTRING object.\n");
return -1;
}
if((in = fopen("book.txt", "r")) == NULL) {
printf("Error opening file \"book.txt\". Does the file exist?\n");
return -1;
}
while(mystring_input(str, in, 1, fTerminate) != MYSTRING_STATUS_ERROR) {
if(mystring_size(str) == 4) {
mystring_output(str, stdout);
printf("\n");
}
}
mystring_destroy(&str);
return 0;
}
int fTerminate(char ch, int * pbDiscardChar) {
// Terminate on whitespace characters or non-alpha characters.
return (*pbDiscardChar = ((isspace(ch) || (isalpha(ch) == 0))?1:0));
}
And just in case you need it, here is the input function: http://pastebin.com/vD71hGEt
MyString_Status mystring_input(MYSTRING hString,
FILE * hFile,
int bIgnoreLeadingWhiteSpace,
int (*fTerminate)(char ch, int * pbDiscardChar)) {
char ch = '\0';
int eofCheck = 0;
int t, discard;
mystring_truncate(hString, 0);
if(hFile == NULL) return MYSTRING_STATUS_ERROR;
eofCheck = fscanf(hFile, "%c", &ch);
// If bIgnoreWhiteSpace is true, gobble leading whitespace.
if(bIgnoreLeadingWhiteSpace) {
while(isspace(ch)) {
eofCheck = fscanf(hFile, "%c", &ch);
if(eofCheck == EOF) return MYSTRING_STATUS_ERROR;
}
}
// Add all valid characters to the string, overwriting the old string.
while(eofCheck != EOF) {
t = fTerminate(ch, &discard);
if(discard == 0) mystring_push(hString, ch);
if(t) return MYSTRING_STATUS_SUCCESS;
eofCheck = fscanf(hFile, "%c", &ch);
}
if(eofCheck == EOF) return MYSTRING_STATUS_ERROR;
return MYSTRING_STATUS_SUCCESS;
}
It clearly works for the first two strings, so what happened with the rest of them? Does my computer just like ham?

passing value of array to the start of the loop

My goal is to have the user view the history of entered commands (historyArray - done) and allow him to re-run any command in history, by entering history 1, history 2 where 1 and 2 is the number of the list of commands as printed-out from historyArray.
I have managed to obtain the index from the second parameter (history 1) of the user input. My question is now, how to execute that specific command obtained from history N?
So, for example:
hshell> test [Enter]
Command not found
hshell> history 1
Command not found
Here is my progress:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[])
{
int i=0; int j=0; int k=0;
int elementCounter = 0;
char inputString[100];
char *result=NULL;
char delims[] = " ";
char historyArray[30][20] = {0};
char tokenArray[20][20] ;
int tempIndex = 0;
char hCommand[2][20]={0};
do
{
j = 0;
printf("hshell>");
gets(inputString);
strcpy (historyArray[k], inputString);
k = (k+1) % 20;
if (elementCounter <= 20)
{
elementCounter++;
}
if (elementCounter == 21)
{
k = 20;
for (i=0; i<20; i++)
{
strcpy(historyArray[i], historyArray[i+1]);
}
strcpy (historyArray[19], inputString);
}
// Break the string into parts
result = strtok(inputString, delims);
while (result!=NULL)
{
strcpy(tokenArray[j], result);
j++;
result= strtok(NULL, delims);
}
if (strcmp(tokenArray[0], "exit") == 0)
{
return 0;
}
else if (strcmp(tokenArray[0], "history") == 0)
{
if (j>1)
{
tempIndex = atoi(tokenArray[1]);
strcpy(hCommand,historyArray[tempIndex-1]);
puts(hCommand);
// tempIndex = atoi(tokenArray[j]);
//puts(tempIndex);
}
else
{
//print history array
for (i=0; i<elementCounter-1;i++)
printf("%i. %s\n", i+1, historyArray[i]);
}
}
else
{
printf("Command not found\n");
}
}while (1);
}
hCommand is where I store the command as obtained from historyArray.
I am using a Windows machine.
After getting the name of the command you wanna execute I would suggest going through the system call exec. Take into account the exec replaces the current process image with the one you are going to execute. Otherwise you might be interested in fork.
EDIT#1 Then I believe you need this API. Note that I am not familiar which of those functions are equivalent to the ones I have provided in first place. With a bit time you could figure it out, right? :)
You can use the 'system' function in stdlib.h.
#include <stdlib.h>
int system(const char *command);
This function is included in both windows and *nix. You do not need to worry about calling fork or CreateProcess separately, this will take care of it for you. See the MSDN documentation for details.
In your code, you would write:
system(hCommand);
It will return when the command finishes (it is a synchronous call).

Resources