我正在尝试在c中编写一个将#识别为注释字符的shell。例如,如果我输入命令" ls#这是注释",程序不应该识别#之后的字符。
以下是我目前的代码:
/* See Chapter 5 of Advanced UNIX Programming: http://www.basepath.com/aup/
* for further related examples of systems programming. (That home page
* has pointers to download this chapter free.
*
* Copyright (c) Gene Cooperman, 2006; May be freely copied as long as this
* copyright notice remains. There is no warranty.
*/
/* To know which "includes" to ask for, do 'man' on each system call used.
* For example, "man fork" (or "man 2 fork" or man -s 2 fork") requires:
* <sys/types.h> and <unistd.h>
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/wait.h>
#include <string.h>
#define MAXLINE 200 /* This is how we declare constants in C */
#define MAXARGS 20
/* In C, "static" means not visible outside of file. This is different
* from the usage of "static" in Java.
* Note that end_ptr is an output parameter.
*/
static char * getword(char * begin, char **end_ptr) {
char * end = begin;
while ( *begin == ' ' )
begin++; /* Get rid of leading spaces. */
end = begin;
while ( *end != '\0' && *end != '\n' && *end != ' ' )
end++; /* Keep going. */
if ( end == begin )
return NULL; /* if no more words, return NULL */
*end = '\0'; /* else put string terminator at end of this word. */
*end_ptr = end;
if (begin[0] == '$') { /* if this is a variable to be expanded */
begin = getenv(begin+1); /* begin+1, to skip past '$' */
if (begin == NULL) {
perror("getenv");
begin = "UNDEFINED";
}
}
return begin; /* This word is now a null-terminated string. return it. */
}
/* In C, "int" is used instead of "bool", and "0" means false, any
* non-zero number (traditionally "1") means true.
*/
/* argc is _count_ of args (*argcp == argc); argv is array of arg _values_*/
static void getargs(char cmd[], int *argcp, char *argv[])
{
char *cmdp = cmd;
char *end;
int i = 0;
/* fgets creates null-terminated string. stdin is pre-defined C constant
* for standard intput. feof(stdin) tests for file:end-of-file.
*/
if (fgets(cmd, MAXLINE, stdin) == NULL && feof(stdin)) {
printf("Couldn't read from standard input. End of file? Exiting ...\n");
exit(1); /* any non-zero value for exit means failure. */
}
while ( (cmdp = getword(cmdp, &end)) != NULL ) { /* end is output param */
/* getword converts word into null-terminated string */
if (strchr(cmdp, '#') != NULL) {
}
argv[i++] = cmdp;
/* "end" brings us only to the '\0' at end of string */
cmdp = end + 1;
}
argv[i] = NULL; /* Create additional null word at end for safety. */
*argcp = i;
}
static void execute(int argc, char *argv[])
{
pid_t childpid; /* child process ID */
childpid = fork();
if (childpid == -1) { /* in parent (returned error) */
perror("fork"); /* perror => print error string of last system call */
printf(" (failed to execute command)\n");
}
if (childpid == 0) { /* child: in child, childpid was set to 0 */
/* Executes command in argv[0]; It searches for that file in
* the directories specified by the environment variable PATH.
*/
if (-1 == execvp(argv[0], argv)) {
perror("execvp");
printf(" (couldn't find command)\n");
}
/* NOT REACHED unless error occurred */
exit(1);
} else /* parent: in parent, childpid was set to pid of child process */
waitpid(childpid, NULL, 0); /* wait until child process finishes */
return;
}
int main(int argc, char *argv[])
{
char cmd[MAXLINE];
char *childargv[MAXARGS];
int childargc;
while (1) {
printf("%% "); /* printf uses %d, %s, %x, etc. See 'man 3 printf' */
fflush(stdout); /* flush from output buffer to terminal itself */
getargs(cmd, &childargc, childargv); /* childargc and childargv are
output args; on input they have garbage, but getargs sets them. */
/* Check first for built-in commands. */
if ( childargc > 0 && strcmp(childargv[0], "exit") == 0 )
exit(0);
else if ( childargc > 0 && strcmp(childargv[0], "logout") == 0 )
exit(0);
else
execute(childargc, childargv);
}
/* NOT REACHED */
}
答案 0 :(得分:0)
你必须把测试放在while循环之外。
static void getargs(char cmd[], int *argcp, char *argv[])
{
char *cmdp = cmd;
char *end, *hash;
int i = 0;
/* fgets creates null-terminated string. stdin is pre-defined C constant
* for standard intput. feof(stdin) tests for file:end-of-file.
*/
if (fgets(cmd, MAXLINE, stdin) == NULL && feof(stdin)) {
printf("Couldn't read from standard input. End of file? Exiting ...\n");
exit(1); /* any non-zero value for exit means failure. */
}
// check if we have a comment
hash = strchr(cmd,'#');
if(hash != NULL){
// just overwrite it with NULs
while(*hash != '\0'){
*hash = '\0';
hash++;
}
}
while ( (cmdp = getword(cmdp, &end)) != NULL ) { /* end is output param */
/* getword converts word into null-terminated string */
argv[i++] = cmdp;
/* "end" brings us only to the '\0' at end of string */
cmdp = end + 1;
}
argv[i] = NULL; /* Create additional null word at end for safety. */
*argcp = i;
}