如何使用strtok_r()将值传递给数组

时间:2015-03-17 03:56:24

标签: c

我正在写一个简单的shell。我需要在这个shell上添加一个历史记录功能,这将允许我检查我的shell收到的先前命令。 我已经尝试了这么久,我无法弄清楚为什么我的command []数组在这里是NULL

for (command[numargs] = strtok_r(buf," ",&inner_ptr);
                         command[numargs];
                         command[numargs] = strtok_r(NULL," ",&inner_ptr))
                        ++numargs;

                        printf("%s \n",command[numargs]);

printf(“%d \ n”,numargs);                 如果(numargs)                     执行(安培;命令[numargs]);

这意味着我的shell总是执行NULL

// shell代码。 Boojum,感谢您修复代码,错误是打印两个“? - >”

//壳牌

#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <iostream>
#include <signal.h>
#include <string.h>
#include <fstream>

using namespace std;
#define ARGLENGTH  100
int execute(char *command[]);

int main()
{
int option;
int his_size=0;
char buffer[ARGLENGTH];
char *history[his_size];
int numargs = 0;
printf("Press 1 to input from keyboard, 2 to input from file .mshrc\n");
    scanf("%d",&option);
switch (option){
    case 1: 
        while(1)
        {
            printf("?-> ");
            if (fgets(buffer, ARGLENGTH, stdin))
            {
                char *outer_ptr=NULL;
                for (char *buf=strtok_r(buffer, ";\n\r", &outer_ptr);
                     buf;
                     buf=strtok_r(NULL, ";\n\r", &outer_ptr) )
                {
                    if (strcmp(buf, "exit") == 0){
                        return 0;
                    }
                    if (strcmp(buf, "history") == 0){
                        for(int a=0;a<=numargs;a++){
                            printf("command history: %s \n", history[a]);
                        }
                    }

                    char *command[1000000];
                    char *inner_ptr=NULL;
                    //int numargs = 0;

                    for (command[numargs] = strtok_r(buf," ",&inner_ptr);
                         command[numargs];
                         command[numargs] = strtok_r(NULL," ",&inner_ptr))
                        ++numargs;

                        printf("%s \n",command[numargs]);
                        printf("%d \n",numargs);
                    if (numargs)
                        execute(&command[numargs]);
                }
            }
        }

    case 2:
        FILE *fr;

        fr=fopen("example.txt","rt");
           if( fr == NULL )
               {
                  perror("Error while opening the file.\n");
                  exit(EXIT_FAILURE);
               }

            while(fgets(buffer, ARGLENGTH, fr) != NULL ){
                char *outer_ptr=NULL;
                for (char *buf=strtok_r(buffer, ";\n\r", &outer_ptr);
                     buf;
                     buf=strtok_r(NULL, ";\n\r", &outer_ptr) )
                {
                    if (strcmp(buf, "exit") == 0)
                        return 0;
                    int numargs = 0;
                    char *command[1000000];
                    char *inner_ptr=NULL;
                    for (command[numargs] = strtok_r(buf," ",&inner_ptr);
                         command[numargs];
                         command[numargs] = strtok_r(NULL," ",&inner_ptr))
                        ++numargs;
                    if (numargs)
                        execute(command);

                }
            }
            fclose(fr);
            return main();

    }
        return 0;
}   

int execute(char *command[])
{
    int pid,exitstatus;
    pid = fork();
    if( pid==-1 ){
            perror("fork failed");
            exit(1);
        }
    else if( pid==0 ){
           execvp(command[0], command);
            perror("execution failed");
            exit(1);
        }
        else {
                while (wait(&exitstatus) != pid);
        }
 }

1 个答案:

答案 0 :(得分:1)

问题似乎在于您将每一行作为单个命令的参数读取,然后在给出空行时执行它。如,

?-> ls
?-> -al
?->

将提供扩展目录列表。

如果您只想使用空格来分隔参数,这可能是strtok()的一个很好的用途。我怀疑这样的事情更像你想要的东西:

int main()
{
    char *command[1000000];
    int numargs = 0;
    char buffer[ARGLENGTH];

    while(1) {
        printf("?-> ", numargs);
        if( fgets(buffer, ARGLENGTH, stdin) && *buffer != '\n' ) {
            command[numargs++] = strtok(buffer, " \n\r");
            while (command[numargs++] = strtok(NULL, " \n\r"))
                ;
            if( numargs > 0 ){
                /* command[numargs] = NULL; -- No longer needed, strtok() does this */
                execute(command);
                numargs = 0;
            }
        }
        if (command[0][0] == 'e'){
            break;}
    }
    return 0;
}

您还需要查看其他边缘案例问题:例如,空白行或以&#34; e&#34;开头的行。但这应该有助于你开始。

编辑:这里有一些更接近于我如何写这个包括在分号上拆分命令的东西。这次我做了几个风格变化,即将变量声明移动到更接近它们首次使用的位置。

int main()
{
    while(1)
    {
        printf("?-> ");
        char buffer[ARGLENGTH];
        if (fgets(buffer, ARGLENGTH, stdin))
        {
            char *outer_ptr=NULL;
            for (char *buf=strtok_r(buffer, ";\n\r", &outer_ptr);
                 buf;
                 buf=strtok_r(NULL, ";\n\r", &outer_ptr) )
            {
                if (strcmp(buf, "e") == 0)
                    return 0;
                int numargs = 0;
                char *command[1000000];
                char *inner_ptr=NULL;
                for (command[numargs] = strtok_r(buf," ",&inner_ptr);
                     command[numargs];
                     command[numargs] = strtok_r(NULL," ",&inner_ptr))
                    ++numargs;
                if (numargs)
                    execute(command);
            }
        }
    }
    return 0;
}