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).
Related
i would like to write a code that count how often the argument occurs in the input.
those are the requirements:
It may be assumed
that the lines in the input do not exceed 1024 characters. The string #EOF on the beginning of a line indicates the end of the input. It it not necessary to consider word
boundaries, and overlapping words must be counted as well: with an input of baaaab,
the word aa shall be counted three times. Also, the program must be case sensitive.
i already wrote a code, but i seem to have made some mistakes. Does anyone have an idea?
int main(int argc, char *argv[])
{
char buf[1026]="start";
int count=0;
while (strncmp(buf,"#EOF",4)!=0)
{
fgets(buf, 1025, stdin);
if (strncmp(buf, argv[1], strlen(argv[1]))==0)
{
count++;
}
}
if(argc==1)
printf("Please specify a program argument.");
if(argc>=2)
printf("%d", count);
return 0;
}
this is the program input with the argument let:
Let it be, let it be, let it be, let it be.
Whisper words of wisdom, let it be.
#EOF
and there is no output while it should be 4
this is the program input with argument aa:
aa aaaaa aa
aa aaa
#EOF
and the output is 2 while it should be 9
this is the program input with argument EOF:
De volgende EOF behoort ook tot de invoer: EOF
# Net als deze #EOF. Maar hieronder niet meer.
#EOF
and there is no input while it should be 3
thanks in advance
strncmp() tests for exact equality of the first n characters of each string provided. However, what you want is to count each occurrence, not just if the start of the line matches. For example, if you're looking for "let" in "Let it be, let it be, let it be, let it be.", you're only ever testing "Let" against "let". No match, no count. You never test further down the string.
So what you want to do is to loop over the result of fgets(), like so:
fgets(buf, 1025, stdin);
for (char *p = buf; *p; ++p) {
if (strncmp(p, argv[1], strlen(argv[1])) == 0)
{
count++;
}
}
This will test "let" against "Let", then "et ", then "t i", etc. until you've checked the whole line and counted the matches.
If you were to use strstr() instead of strncmp(), the loop would look like this:
for (char *p = buf; (p = strstr(p, argv[1])); ++p)
{
count++;
}
Your code only counts the first occurrence of the word in each line of input. You need to iterate through each input string to find ALL occurrences. Try something like this:
int main(int argc,char *argv[])
{
char buf[1026] = "start";
int len, matches = 0;
if (argc < 2) {
printf("Please specify a program argument.");
exit(1);
}
len = strlen(argv[1]);
while (strncmp(buf,"#EOF",4) != 0) {
fgets(buf,1025,stdin);
int buflen = strlen(buf);
for (int i = 0; i <= buflen - len; ++i) {
if (strncmp(&buf[i],argv[1],len) == 0)
++matches;
}
}
printf("'%s' found %d times\n",argv[1],matches);
return 0;
}
This is a functional and correct code written based on the answer given by Fred Larson
Big thanks to him.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char buf[1026]="start";
int N;
int count=0;
char *p;
if(argc==1)
{
printf("Please specify a program argument.\n");
return(1);
}
N=strlen(argv[1]);
while (strncmp(buf,"#EOF",4)!=0)
{
fgets(buf, 1025, stdin);
for (p = buf;*p;p++)
{
if (strncmp(p, argv[1], N)==0)
{
if (strncmp(buf,"#EOF",4)!=0)
count++;
}
}
}
if(argc>=2)
printf("%d\n", count);
return 0;
}
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
}
I am trying to build an echo-like command which I named code at xv6. The problem is that if:
Input:
$code Hello World
Output:
user space:Hello user space:World
While the correct output should be:
user space: Hello World
Can somebody help me?
int
main(int argc, char *argv[])
{
int i;
if(argc <= 1){
printf(1," %s user space:", argv[0]);
exit();
}
for(i = 1; i < argc; i++){
printf(1, " print in user space:%s",argv[i]);
}
printf(1, "\n");
exit();
}
program name is also passed as argument to your main function so you have three(as hello and world are considered separate arguments) arguments here .there is several issues in your code ,as you have two arguments first if statement will be false ,and you are not printing correctly in for loop ,following might be helpful :
int main(int argc, char *argv[])
{
int i;
printf("number of arguments : %d ",argc);
//argv array index count from 0
for(i = 0; i < argc; i++){
printf("argument number %d : %s",i,argv[i]); // issue in your code
}
printf("\n");//issue in your code
exit(0);
}
It's possible to use the write command so that you can output to stdout. Between each command line argument an additional space needs to be written.
#include <stdio.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char *argv[]) {
int i;
write(1, "user space: ", 12);
for (i = 1; i < argc; i++) {
size_t len = strlen(argv[i]);
write(1, argv[i], len);
write(1, " ", 1);
}
write(1, "\n", 1);
return 0;
}
The problematic part in your code is here:
for(i = 1; i < argc; i++){
printf(1, " print in user space:%s",argv[i]); //" print in user space:" is printed
//for each iteration
}
As others pointed out, you should rather do:
printf(" print in user space:\n");
for(i = 1; i < argc; i++){
printf("%s",argv[i]);
}
That said, a few more remarks for you:
I never seen a printf that takes an integer as first argument, I assume that the first parameter is not important/is a typo
I am not an expert unix developer, but you can just use "return 0" (or "return 1") to quit your program. You will also be able to return an error code this way, as most unix programs do
If you decide to use printf, be aware that it comes with a nasty security exploit which can expose the caller's stack to a malicious user. Make sure your input is well formed or use a different function if possible
I don't understand why it isn't working. It complains when there are 3 or more args but not when there is only the one Vigenere arg. I have looked at other people who had same problem and they said this worked to resolve.....not sure what I am missing here. When I run ./vigenere, I get a segmentation fault. It works normally with 2 arg like ./vigenere bard and complains when extra arguments are given like ./vigenere bard dfads.
#include <cs50.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main(int argc,string argv[])
{
string sKeyWord = argv[1];
int iKeyLength = strlen(sKeyWord);
int iKey[iKeyLength];
string sPlainText = "";
int counter = 0;
int iAccept = 0;
do
{
if(argc != 2) // <-----this should work whats wrong?
{
printf("Invalid argument! Please enter program name and keyword.\n");
return 1;
}
else if(argv[1])
{
for(int i = 0; i < iKeyLength; i++)
{
if (!isalpha(argv[1][i]))
{
printf("Invalid entry, please use letters only.\n");
return 1;
}
else
{
iAccept = 1;
}
}
}
}while(iAccept == 0);
for(int i = 0; i < iKeyLength; i++)
{
iKey[i] = toupper(sKeyWord[i]) - 65;
}
sPlainText = GetString();
int iPlainText = strlen(sPlainText);
for(int j = 0; j < iPlainText; j++)
{
if(!isalpha(sPlainText[j]))
{
printf("%c",sPlainText[j]);
counter++;
}
if(islower(sPlainText[j]))
{
printf("%c",((((sPlainText[j] - 97) + iKey[(j - counter)%iKeyLength])%26)+ 97));
}
if(isupper(sPlainText[j]))
{
printf("%c",((((sPlainText[j] - 65) + iKey[(j - counter)%iKeyLength])%26)+ 65));
}
}
printf("\n");
return 0;
}
I'd rewrite the top, argument handling section of your program like this.
int main(int argc, char **argv)
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s key\n", argv[0]);
return 1;
}
char *sKeyWord = argv[1];
int iKeyLength = strlen(sKeyWord);
int iKey[iKeyLength];
for (int i = 0; i < iKeyLength; i++)
{
if (!isalpha(sKeyword[i]))
{
fprintf(stderr, "%s: Invalid character '%c' in key; please use letters only.\n",
argv[0], sKeyword[i]);
return 1;
}
iKey[i] = toupper(sKeyWord[i]) - 'A';
}
…your code to read the text to be enciphered and encipher it, etc…
The key point is to check that there is an argv[1] before trying to do anything with it. I eliminated a do { … } while (…); loop because the argument isn't going to change on a second iteration. That allows the iAccept variable to be eliminated. Note that errors are reported on standard error, not standard output. Also notice that the messages are preceded by the program name (argv[0]). A 'Usage' message is often the best way to report a problem; it's a simple reminder to those who run the program what's required. Note too that the error message for the alphabetic check reports the erroneous character; that helps people see what the program thinks is wrong.
This is more or less what the comments were suggesting should be done.
I've not reviewed the enciphering code; there could be undiagnosed problems in that too. There are many related questions on SO that would provide you with answers to any such problems, though.
I am writing a filter that should select all lines having a specified length. I ended up having this code, but I don't know how to specify n. I mean, n (and optionally m) should be replaced by a number of lines in command prompt, but I have no idea how to describe it in the code. I thought of case "%d", but from what I know it's not possible to write it like that. That's the code I have so far:
#include<stdio.h>
#include<string.h>
int main(int argc, char *argv[])
{
int n;
int m;
char line[200];
while(fgets(line,sizeof(line)/sizeof(char), stdin)!=NULL)
{
if(argc>1){
switch(argv[0][0])
{
case 'n':
strlen(line)==n;
break;
case '#n':
strlen(line)<n;
break;
case 'n m':
strlen(line)>=n && strlen(line)<=m;
break;
case 'n#':
strlen(line) > n;
break;
}
printf("%s\n", line);
}}
return 0;
}
Your help would mean a lot to me! I don't really know how to make it work anymore.
I think you should parse the command line outside of your loop. Assuming you are going to require the caller of your program to specify both n and m on the command line, it's a simple matter of grabbing the first two parameters and converting them to integers, and then loop over your stdard input. Something like this:
/* call this minmax.c */
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
int n, m, len;
char line[200];
if (argc < 3) {
printf("Must specify min & max line length.");
return -1;
}
n = atoi(argv[1]);
m = atoi(argv[2]);
while(fgets(line, 200, stdin) != NULL) {
len = strlen(line);
if (len >=n && len <= m)
printf(line);
}
return 0;
}
Assuming you are running on *nix:
cc -ominmax minmax.c
Then call it with the min and max line lengths
./minmax 2 5
This will echo back every line you type that is at least 2 characters, but no more then 5.
I hope I understand well the aim of your desired program and here is the code :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i=1,n,m; // n and m are the variable which holds
// the limited length
if(argc>=3)
{
// you need to execute the program with this form
// program.exe n m <file.txt
n=atoi(argv[1]); // get the value of n
m=atoi(argv[2]); // get the value of m
printf("n=%d m=%d\n",n,m);
}
char line[1000]; // this variable will hold each line of the file
while (fgets(line,sizeof(line),stdin)) // fgets used to read
{ //the lines in file till the newline
int length=strlen(line)-1;
// we decrement the length to get rid of
// the newline character
if (length < n)
{
printf("line %d:%s status: < %d\n",i,line,n);
}
else if (length==n)
{
printf("line %d:%s status: = %d\n",i,line,n);
}
else if (length>n && length <=m)
{
printf("line %d:%s status: %d < <= %d\n",i,line,n,m);
}
else
{
printf("line %d:%s status: > %d\n",i,line,m);
}
i++;
}
return 0;
}
In case the code does not fit to your needs I think it is sufficient and can be taken as a support for your exact program as it encompasses everything you need !! Hope it helps !!