简体   繁体   English

将字符串解析为以null终止的数组的最佳方法是什么?

[英]What is the best way to parse a string into a null terminated array?

I am writing a simple command line interpreter. 我正在编写一个简单的命令行解释器。 My code reads a string using scanf and parses it using the function getArgs() shown below, and then uses that array as an argument to execvp to perform a command such as ls. 我的代码使用scanf读取一个字符串,并使用下面显示的getArgs()函数对其进行解析,然后将该数组用作execvp的参数来执行诸如ls之类的命令。 It works if I call only 'ls' but when I call 'ls -la', it gives the same result as 'ls'. 如果我仅调用“ ls”,则它起作用,但是当我调用“ ls -la”时,其结果与“ ls”相同。

void getArgs(char* command, char* args[]){

    int i = 0;
    char* p = strtok(command, " "); 
    args[i] = p;

    while(p != NULL){
        i++; 
        p = strtok(NULL, " ");
        args[i] = p;
}
}

Here is my main function which includes the initialization of the arguments given: 这是我的主要功能,其中包括给定参数的初始化:

int main(){
char *args[1024];
char example[30]; 
char exit[5] = {'q', 'u', 'i', 't', '\0'};
int f1; 
int status;
size_t n = sizeof(args)/sizeof(args[0]);

while(strncmp(example, exit, 30) !=0){

    printf(">>>");
    scanf("%s", example);
    getArgs(example, args);
    int x = strncmp(args[0], exit, 30);

    if (x != 0){
        f1 = fork(); 
        if (f1 != 0){
            /* wait  for child process to terminate */
            waitpid(f1, &status, 0);
        }
        else{myExec(args);}}         
    else{
        return 0;}}
    return 0; 
}

My guess as to the problem is that my argument array, args, is not null terminated and so when I attempt to use it in myExec(): 我对这个问题的猜测是我的参数数组args不是以null结尾的,因此当我尝试在myExec()中使用它时:

void myExec(char* args[]){
    execvp(args[0], args);
}

this does not work. 这行不通。 So my question is, can I set the item after the last non-empty part of my array to null to try to get this to work? 所以我的问题是,我可以将数组的最后一个非空部分之后的项目设置为null来尝试使其工作吗? If so, how can I do that? 如果是这样,我该怎么做? Is there a better way to solve this? 有没有更好的方法来解决这个问题?

The -la is being ignored because scanf("%s", example); -la被忽略,因为scanf("%s", example); will stop at the first space. 将停在第一个空格。 I suggest 我建议

scanf(" %29[^\n]", example);

Which will 哪个会

  • Ignore whitespace left in the buffer from the previous command. 忽略上一条命令留在缓冲区中的空格。
  • Restrict the string input from overflowing. 限制字符串输入的溢出。
  • Allow space seperators in the command. 在命令中允许使用空格分隔符。

Note too that in the first execution of while(strncmp(example, exit, 30) !=0) the example is an uninitialised variable, so that needs to be 还要注意,在第一次执行while(strncmp(example, exit, 30) !=0)example是未初始化的变量,因此需要

char example[30] = "";

The %s directive stops scanning at the first whitespace character, so it won't properly capture any commands with spaces (such as ls -la ). %s指令在第一个空格字符处停止扫描,因此它将无法正确捕获任何带有空格的命令(例如ls -la )。 You should use fgets to get user input if you want to preserve any whitespace: 如果要保留任何空格,应使用fgets获取用户输入:

if ( fgets( example, sizeof example, stdin ) )
{
  getArgs( example, args);
  ...
}

fgets will read up to sizeof example - 1 characters into example (including the newline!) and 0-terminate the string. fgets最多读取sizeof example - 1 example包含sizeof example - 1字符(包括换行符!),字符串以0结尾。 You may want to take that newline into account with your strtok call. 您可能需要在strtok调用中考虑换行符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM