I am attempting to execute command lines given by user input but for some reason the execvp() function isn't executing the command. I read in a user input and split it, store it into an array and use the excevp() function to execute it. I even printed out the spots in the array to make sure it was placing the token into the right spot and it is. Here is my code in C
char b[100];
int i = 0;
char *token;
char *array[3];
printf("Please enter the command you want to use: ");
fgets(b, 100, stdin);
token = strtok (b, " ");
while (token != NULL){
array[i++] = token;
printf("%s\n",token);
token = strtok(NULL, " ");
}
printf("%s", array[0]);
printf("%s", array[1]);
execvp(array[0], array);
So for example if I were to type in "ls" into the command line in the program and hit enter it will just go to the next line and nothing will execute. Are there any recommendation to fix this because I am lost on where to begin?
The problem is array[0] is ls\n (as fgets reads newline character as well) and not ls you have to remove \n as well.
You can simply create an array of delimiters like this:
char delimiters[] = " \t\n";
and then simply do
token = strtok(b, delimiters); // Use delimiters instead of only " " (whitespace)
while (token != NULL) {
array[i++] = token;
printf("%s\n", token);
token = strtok(NULL, delimiters); // Use delimiters instead of only " " (whitespace)
}
Related
I have an assignment to write a program that can be used in the bash shell that mimics certain default Unix commands, and we are supposed to build them from scratch. One of these commands is the PS1 command, which is supposed to change the $ prompt to whatever argument the command is given. I have implemented this in the code below, and it works almost perfectly.
Prior to using the PS1 command, the prompt works correctly, it prints the $ and does not indent, rather it lets the user continue typing on the same line. However, after using the command, whenever a prompt is supposed to come up, the program will print the prompt, and then go to a new line. I need it to print the PS1 char* without going to a newline.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, char *argv[]) {
int exit = 0;
char* PS1 = "$";
while(exit == 0){
char* token;
char* string;
char input[500];
printf("%s", PS1);
fgets (input, 500, stdin);
token = strtok(input, " ");
if(strncmp(token, "exit", 4) == 0){
exit = 1;
break;
}
else if(strncmp(token, "echo", 4) == 0){
token = strtok (NULL, " ");
while (token != NULL){
printf ("%s", token);
printf("%s", " ");
token = strtok (NULL, " ");
}
}
else if(strcmp(token, "PS1") == 0){
token = strtok (NULL, " ");
char temp[300];
strcpy(temp, &input[4]);
PS1 = temp; }
}
}
fgets retains the newline character at the end, so that gets printed. You could get rid of that after reading the line:
fgets (input, sizeof(input), stdin);
strtok(input, "\n");
Your code has other issues:
... else if (strcmp(token, "PS1") == 0) {
token = strtok (NULL, " ");
char temp[300];
strcpy(temp, &input[4]);
PS1 = temp;
}
The character array temp is local to the block in curly braces and will be invalid after the closing }. That means that PS1 is a handle to invalid memory. That is undefined bevaiour. It may not be visible right now, but it will bite you later, when you add more commands.
It might be better to make PS1 an array if chars that is visible throughout main and copy to that. (The array can be initialised to hold "$" at the beginning.)
You should also avoid the explicit index at &input[4]. Let the tokenisation with strtok handle this. After all, there might be additional white space and " PS1 Command: " is valid input.
Here is a weird problem:
token = strtok(NULL, s);
printf(" %s\n", token); // these two lines can read the token and print
However!
token = strtok(NULL, s);
printf("%s\n", token); // these two lines give me a segmentation fault
Idk whats happened, because I just add a space before %s\n, and I can see the value of token.
my code:
int main() {
FILE *bi;
struct _record buffer;
const char s[2] = ",";
char str[1000];
const char *token;
bi = fopen(DATABASENAME, "wb+");
/*get strings from input, and devides it into seperate struct*/
while(fgets(str, sizeof(str), stdin)!= NULL) {
printf("%s\n", str); // can print string line by line
token = strtok(str, s);
strcpy(buffer.id, token);
printf("%s\n", buffer.id); //can print the value in the struct
while(token != NULL){
token = strtok(NULL, s);
printf("%s\n", token); // problem starts here
/*strcpy(buffer.lname, token);
printf("%s\n", buffer.lname); // cant do anything with token */
}}
fclose(bi);
return 1;}
Here is the example of string I read from stdin and after parsed(I just tried to strtok the first two elements to see if it works):
<15322101,MOZNETT,JOSE,n/a,n/a,2/23/1943,MALE,824-75-8088,42 SMITH AVENUE,n/a,11706,n/a,n/a,BAYSHORE,NY,518-215-5848,n/a,n/a,n/a
<
< 15322101
< MOZNETT
In the first version your compiler transforms printf() into a
puts() and puts does not allow null pointers, because internally
invokes the strlen() to determine the lenght of the string.
In the case of the second version you add a space in front of format
specifier. This makes it impossible for the compiler to call puts
without appending this two string together. So it invokes the actual
printf() function, which can handle NULL pointers. And your code
works.
Your problem reduces to the following question What is the behavior of printing NULL with printf's %s specifier?
.
In short NULL as an argument to a printf("%s") is undefined. So you need to check for NULL as suggested by #kninnug
You need to change you printf as follows:
token = strtok(NULL, s);
if (token != NULL) printf("%s\n", token);
Or else
printf ("%s\n", token == NULL ? "" : token);
I'm trying to make tokens from an input file. So, I get one line with fgets and feed it to a helper method that takes in a char* and returns a char* of the token. I am utilizing strtok() with delimiter as " " since the tokens are all separated by " ". But, I can't figure out why the code only makes 2 tokens per line and just moves on to the next line even though there is more in that line needed to be tokenized. Here is the code:
char *TKGetNextToken( char * start ) {
/* fill in your code here */
printf("Entered TKGetNextToken \n");
printf(&start[0]);
char* temp = &start[0];
//Delimiters for the tokens
const char* delim = " ";
//store tempToken
char* tempTok = strtok(temp, delim);
//return the token
return tempTok;
}
Here is how I'm storing the tokens in the main method:
//call get next token and get the token and store into temptok
while (temp!= NULL) {
tempTok = TKGetNextToken(temp);
printf("tempTok: %s\n",tempTok);
token.charPtr[tempNum] = tempTok;
tempNum++;
printf("Temp: %s\n",tempTok);
temp = strtok(NULL, " \0\n");
}
So, lets say I have a file.txt with:
abcd ef ghij asf32
fsadf ads adf
The tokens created would be "abcd" and "ef" and it will go on to the next line without making tokens for "ghij" and "asf32".
Use the proper syntax for strtok
char *tempTok = strtok(line, " "); //initialize
while (tempTok != NULL) {
//do the work
tempTok = strtok(NULL, " \n"); //update
}
If you do like above, then you can get the tokens quite easy. Please have a look at this example, which is similar to your code, just remember how you use strtok properly, then it will work. Look at strtok and how it is used in the loop, updating and consumes the char *.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
FILE *fp = fopen("data.txt", "r");
char line[256];
while (fgets(line, sizeof(line), fp)) {
char *tempTok = strtok(line, " ");
while (tempTok != NULL) {
printf("token %s\n", tempTok);
tempTok = strtok(NULL, " \n");
}
}
fclose(fp);
return 0;
}
File data.txt
abcd ef ghij asf32
fsadf ads adf
Output
./a.out
token abcd
token ef
token ghij
token asf32
token fsadf
token ads
token adf
I have this code in my program:
char* tok = NULL;
char move[100];
if (fgets(move, 100, stdin) != NULL)
{
/* then split into tokens using strtok */
tok = strtok(move, " ");
while (tok != NULL)
{
printf("Element: %s\n", tok);
tok = strtok(NULL, " ");
}
}
I have tried adding printf statements before and after fgets, and the one before gets printed, but the one after does not.
I cannot see why this fgets call is causing a segmentation failure.
If someone has any idea, I would much appreciate it.
Thanks
Corey
The strtok runtime function works like this
the first time you call strtok you provide a string that you want to tokenize
char s[] = "this is a string";
in the above string space seems to be a good delimiter between words so lets use that:
char* p = strtok(s, " ");
what happens now is that 's' is searched until the space character is found, the first token is returned ('this') and p points to that token (string)
in order to get next token and to continue with the same string NULL is passed as first argument since strtok maintains a static pointer to your previous passed string:
p = strtok(NULL," ");
p now points to 'is'
and so on until no more spaces can be found, then the last string is returned as the last token 'string'.
more conveniently you could write it like this instead to print out all tokens:
for (char *p = strtok(s," "); p != NULL; p = strtok(NULL, " "))
{
puts(p);
}
EDITED HERE:
If you want to store the returned values from strtok you need to copy the token to another buffer e.g. strdup(p); since the original string (pointed to by the static pointer inside strtok) is modified between iterations in order to return the token.
I want to add string "ay" to each word by using both strtok and strncat. But there seemed to be a conflict somewhere that I cannot find. It only gives me the first word "Computeray" for an output. Help?
#include <stdio.h>
#include <string.h>
int main(void)
{
char str[] = "Computer science is hard";
char* Token;
char* work = "ay";
Token = strtok(str, " ");
while (Token != NULL)
{
strncat(Token, work, 2);
printf("%s", Token);
Token = strtok(NULL, " ");
}
return 0;
}
You're modifying the string (with strcat) and expecting strtok to still behave properly - that's not going to work. Instead of using strcat, just print the "ay" separately:
while (Token != NULL)
{
printf("%say ", Token);
Token = strtok(NULL, " ");
}
Even if it were working the way you'd like, you'd be overwriting a bunch of your input along the way. Probably not what you were going for - if you need to build up a whole new string, you should do it into a new buffer, instead of overwriting the input.