指向chars =“ls \ 0”数组的Char *不等于字符串等效“ls \ 0”

时间:2012-04-15 20:23:50

标签: c

我正在编写一个shell程序,当将值传递给execv()时,我需要一个指向程序名称的char指针(ls),我需要一个指向数组的指针参数的char指针数组。

我通过并解析用户的输入,如果我输入ls,如果我打印char *printf()打印出“ls”。所以我正确解析该行并存储正确的信息。当我将其传递给execv()时,它会显示错误的路径名称,但是如果我将我的指针手动更改为progs[0] = "ls",那么它可以正常工作。如果我比较两个字符串strcmp(mypointer, "ls"),则会显示虽然mypointer打印出"ls",但它不等同于"ls"

有谁知道为什么?

这是我的shell进程代码:

#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/wait.h>

char **progs;
char ***arguments;
char **mode;
char pathname[] = "/bin/";

int main(int argc, char ** argv){

//printf("\n %s \n", progs);
//fflush(stdout);

char buff[100];
FILE *p;

p = fdopen(0, "r");  //opens FD 0 (Stdin) as a stream

char * pathname;

while(1){

    //printf("I'm at the top");

    if(isatty(1) == 1){ //check to see if stdout is going to the terminal
    printstart();       //if so, print 
    }

    fgets(buff, 100, p); // Gets the input from the stdin and puts it in buff

    int processid = fork();  //fork into child to complete task

    if(processid == 0){

        //initialize all variables

        int numcmd = countcmd(buff);
        int pipes = countpipes(buff);
        int i;
        int j;

        //allocate memory for tokenization

        progs = malloc(numcmd * sizeof(char *));
        arguments = malloc((numcmd) * sizeof(char *));
        mode = malloc((numcmd*2) * sizeof(char *));

        for(i = 0; i < numcmd; i++){
            progs[i] = malloc(10* sizeof(char *));
            mode[i] = malloc(10 * sizeof(char *));
            mode[2*numcmd-1-i] = malloc(10 * sizeof(char*));
            arguments[i] = malloc(15 * sizeof(char *));
                for(j = 0; j < 15; j++){
                arguments[i][j] = malloc(15 * sizeof(char*));
                }
            }

        /////////////////////////////////////////////////////////////////////

        parse(buff); //parses input and places it in the static progs

        for(i = 0; i < 1; i++){

        printf("\n This is progs %s", arguments[0][0]);

        char temp[25];
        //strcpy(temp, "/bin/");
        strcpy(temp, progs[0]);
        //strcat(temp, ' \0');

        //*progs = "ls";
        char * ptr = progs[0];
        for(;*ptr != '\0';){
            printf("This is what pointer poitns to %c \n", *ptr++);
            }
        printf("This is the program: <<%s>>", progs[0]);
        fflush(stdout);
        char * argument[2];
        argument[0] = "ls";
        argument[1] = '\0';
        char * hell = "l\0";

        printf("This is the value of comparison %d\n", strcmp(progs[0], hell));

        char **temparg = arguments[0];
        //char temp[20] = progs[0];

        errno = 0;
        execvp("ls", *argument);

        char * error = strerror(errno);
        printf("This is the error %s", error);
        return;
        }

    }       
        else{
        int status;
        waitpid(processid, &status, WIFEXITED(status));

        }
}

return 0;
}

这是我的parse()代码:

#include <string.h>
#include <stdio.h>
#include "myshell.h"

int parse(char * buff){

//Initialize all variables and pointers
int cmd = 0;
int argument = 0;
int mod = 0;
int j = 0;
int hitargs = 0;
int gotcommand = 0;
int multiarg = 0;

char ** argptr = arguments[cmd];
char * ptr1 = progs[cmd];
char * argptr2 = argptr[argument];
char * ptr2 = mode[mod];

while(buff[j] != '\0'){

    switch(buff[j]){

        case ';':
            cmd++;
            argument = 0;
            multiarg = 1;
            *argptr2++ = '\0';

            argptr = arguments[cmd];
            argptr2 = argptr[argument];
            ptr1 = progs[cmd];

            *ptr2 = buff[j];
            mod += 2;
            ptr2 = mode[mod];

        case ' ':
            if(gotcommand == 0){
            break;
            }
            else{
                if(hitargs == 0){
                hitargs = 1;
                *ptr1++ = '\0';
                argument++;
                argptr2 = argptr[argument];
                }
                else{
                argument++;
                argptr2 = argptr[argument];
                }
                break;
            }
        default:
            if(gotcommand == 0){
                *ptr1++ = (char) buff[j];
                *argptr2++ = buff[j];
                gotcommand = 1;
            }
            else if(gotcommand == 1 && hitargs == 0){
                *ptr1++ = (char) buff[j];
                *argptr2++ = buff[j];
            }
            else if(gotcommand == 1 && hitargs == 1){
                *argptr2++ = buff[j];
            }
    }

j++;
}

*argptr2++ = '\0';
*ptr1++ = '\0';

int cmdflag = 0;
int spaceflag = 0;
int argflag = 0;
int cmdct = 1; //account for null
int argumentct = 1; //account for null termination

return 1;
}

对随机的printf语句感到抱歉。

2 个答案:

答案 0 :(得分:2)

  • 您的主程序应该像解析代码一样包含myshell.h
  • 有缺少的功能(例如countcmd()countpipes()会很有帮助 - 虽然我们可以从他们的名字中猜出一点,但是不清楚它们究竟是做什么的。)
  • 您的主程序中应包含<unistd.h>
  • 您应该收到有关未声明功能的警告(例如fork()),您应该注意并修复这些警告。
    • 如果您没有收到这些警告,则需要在编辑中添加更多警告选项。
    • 如果您使用gcc,则使用-Wall是一个很好的起点。

启用警告后,您会看到:

shex.c:95: warning: passing argument 2 of ‘execvp’ from incompatible pointer type
shex.c:99: warning: ‘return’ with no value, in function returning non-void
  • 后者最好通过return EXIT_FAILURE;exit(EXIT_FAILURE);处理。
  • 前者由execvp("ls", *argument);触发。
  • 对于包含许多参数的内容,使用复数词(参数?)可能更好。
  • ...哦,我知道,有一个全局变量arguments
  • 您声明char ***arguments;哎哟!我偶尔会使用三指针,但只是偶尔使用。在大多数情况下,这是一个太多的指针级别,特别是对于这个练习。
  • 然后还有一个局部变量char *argument[2];
  • 因此,正确的电话是execvp("ls", argument);

我会立即扩展等待代码以至少打印信息:

    else
    {   
        int status;
        int corpse = waitpid(processid, &status, WIFEXITED(status));
        printf("Command exited: PID = %d; status = 0x%.4X\n", corpse, status);
    } 

在您的解析代码中,case ';':会进入case ' ':。如果这是故意的,请记录它(带有/* DROP THROUGH */之类的评论;如果没有,请插入缺少的休息时间。你的default:案件也应该在它之后休息一下。它并不是非常关键,但它是传统的,如果需要处理新案例,可以保护您免受损失。

parse()末尾声明的五个变量的字符串是多余的;它们是从未使用过的局部变量(正如编译器告诉你的那样)。

main()的顶部:

FILE *p;
p = fdopen(0, "r");  //opens FD 0 (Stdin) as a stream

这不是必要的; stdin已作为信息流开放。

您使用p阅读stdin(又名fgets())。总的来说,这很好(优于gets()),但您需要注意fgets()包含gets()没有的换行符,您需要检查返回状态(你可能没有读过任何东西)。您还应该使用sizeof()

if (fgets(buff, sizeof(buff), stdin) == 0)
    ...error - read failed...

内存分配非常复杂。对于像char buff[100];这样的固定大小输入,您可以使用非动态分配。总共不超过50个参数,因为它们是空白的。

答案 1 :(得分:0)

没有查看整个代码,因此可能存在其他错误,但是对于'ls'问题,您需要将以下内容添加到解析代码中:

      while (buff[j] != '\0' && buff[j]  != '\n')

这可确保您不会在*ptr1++ = (char) buff[j];

的命令指针中添加“换行符”

注意fgets如果遇到新行会停止阅读,但会将其作为字符串的一部分包含在内。