gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 20:16:26 28 4
gpt4 key购买 nike

我正在编写一个 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 语句感到抱歉。

最佳答案

  • 您的主程序应包括 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 个参数,因为它们是用空格分隔的。

等等

关于指向字符数组的 Char * = "ls\0"不等于等效的字符串 "ls\0",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10165744/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com