「已注销」 2023-03-17 21:12 采纳率: 100%
浏览 74
已结题

c语言使用linux shell的vim编程,在使用指针的时候,值莫名其妙消失了。

图一结果展示

img

图二问题部分代码

img

经过测试 在这个//fill the command structrue部分之后,这里的token[2]就消失了,我测试的用例是“abc;”, 测试结果为图1

command.c

#include <string.h>
#include "command.h"
#include <stdio.h>
#include <stdlib.h>

// whether is separator
int separator(char *token)
{
        int i = 0;
        char *commandSeparators[] = {pipeSep, conSep, seqSep, NULL};

        while(commandSeparators[i] != NULL) {
            if(strcmp(token, commandSeparators[i]) == 0)
            {
                return 1;
            }
            ++i;
        }

    printf("\nin separator\ntoken: %s\n", token);

        return 0;
}

// fill one command structure with details
void fillCommandStructure(Command *cp, int first, int last, char *sep)
{
    cp->first = first;
        cp->last = last - 1;
    cp->sep = sep;
}

// process standard in/out redirections in a command
void searchRedirection(int tknum, char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
    int i;
    for( i = cp->first; i <= cp->last; ++i)
    {
        if(strcmp(token[i], "<") == 0)
        {
            // convert from char array to char
            int k = 0;
            char t[cp->last-i];
            for(int j = i + 1; j <= cp->last; j++)
            {
                t[k] = token[j][0];
                ++k;
            }

            // dynamic allocate memory
            cp->stdin_file = (char*)malloc(cp->last-i);

            for(int l = 0; l < cp->last -i; l++)
            {
                cp->stdin_file[l] = t[l];
            }

            cp->stdin_file[cp->last-i] = '\0';

            ++i;

        } else if (strcmp(token[i], ">") == 0)
        {
            int k = 0;
                        char t[cp->last-i];
                        for(int j = i + 1; j <= cp->last; j++)
                        {
                                t[k] = token[j][0];
                            ++k;
            }

            cp->stdout_file = (char*)malloc(cp->last-i);

                        for(int l = 0; l < cp->last - i; l++)
            {
                cp->stdout_file[l] = t[l];
            }

            cp->stdout_file[cp->last-i] = '\0';

            ++i;
        }
    }
}

// build command line argument vector for execvp function
void buildCommandArgumentArray(char (*token)[MAX_NUM_COMMANDS], Command *cp)
{
    int n = cp->last - cp->first + 1;

    printf("n: %d\n", n);

    // re-allocate memoery for argument vector
    cp->argv = (char**) realloc(cp->argv, sizeof(char*)*n );
    
    if(cp->argv == NULL)
    {
        perror("realloc");
        exit(1);
    }

    // build the argument vector
    int i;

    int k = 0;



    printf("first: %d\n last: %d\n", cp->first, cp->last);

    for(i = cp->first; i <= cp->last; ++i)
    {
        if(strcmp(token[i], ">") == 0 || strcmp(token[i], "<") == 0)
            ++i;
        else
        {
            cp->argv[k] = token[i];
            printf("k %d\nargvk %s\ntoken %s\n", k, cp->argv[k], token[i]);
            ++k;
        }
    }

    cp->argv[k] == NULL;
}

int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int nTokens)
{
    for(int i = 0; i < nTokens;++i)
        {
                printf("token: %s\n", token[i]);
        }

        // if line is empty
    
    if (nTokens == 0)
        return 0;    
    
    // check the first token
    
    if (separator(token[0]))
        return -3;

    // check the last token, add ";" if necessary
    
    if (!separator(token[nTokens-1]))
    {
        strcpy(token[nTokens], seqSep);
        ++nTokens;
    }

    //fill the command structure

    int first = 0;
    int last = 0;
    char *sep;
    int c = 0;

    for(int i = 0; i < nTokens; ++i)
    {
        last = i;
        if (separator(token[i]))
        {
            sep = token[i];
            
            if(first == last)
                return -2;

            fillCommandStructure(&(command[c]), first, last, sep);
            ++c;

            first = i + 1;
        }
    }

    printf("\nafter fill\n");

    for(int i = 0; i < nTokens;++i)
        {
                printf("token: %s\n", token[i]);
        }


    // check the last token of the last command
    if (strcmp(token[last], pipeSep) == 0)
        return -4;

    int nCommands = c;

    // handle standard in/out redirection and build command line argument vector
    
    for (int i=0; i < nCommands; ++i)
    {
        searchRedirection(nTokens, token, &(command[i]));
        buildCommandArgumentArray(token, &(command[i]));
    }

    return nCommands;

command.h

#define MAX_NUM_COMMANDS 1000

#define pipeSep "|"
#define conSep "&"
#define seqSep ";"

struct CommandStruct {
        int first;
        int last;
        char *sep;

    // new fields
    
    char ** argv;
    char *stdin_file;
    char *stdout_file;
};

typedef struct CommandStruct Command;

int separateCommands(char (*token)[MAX_NUM_COMMANDS], Command command[], int cmd_num);


main.c

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

#include "command.h"

char* s_gets(char* st, int n)
{
        char* ret_val;
        int i = 0;

        ret_val = fgets(st, n, stdin);

        if(ret_val)
        {
                while (st[i] != '\n' && st[i] != '\0')
                        i++;
                if (st[i] == '\n')
                {
                        st[i] = '\0';
                }
                else
                {
                        while (getchar() != '\n')
                        {
                                continue;
                        }
                }
        }

        return ret_val;
}

char* tostring(char des[], char src)
{
    des[0] = src;

    des[1] = '\0';

    return des;
}

int main()
{
    while(1)
    {
        char str[MAX_NUM_COMMANDS];

    char tokens[2][MAX_NUM_COMMANDS];

        int cmd_num = 0;

        printf("$\n");

        s_gets(str, MAX_NUM_COMMANDS);

    cmd_num = strlen(str);

    for(int i = 0; i < cmd_num; ++i)
    {
        tostring(tokens[i], str[i]);    
    }

        Command cmdlst[MAX_NUM_COMMANDS];

        cmd_num = separateCommands(tokens, cmdlst, cmd_num);

    puts("");

    printf("return value is: %d\n",cmd_num);

    puts("");

    for(int i = 0; i < cmd_num; ++i)
        {
            printf("fst %d\n", cmdlst[i].first);
            printf("lst %d\n", cmdlst[i].last);
          printf("sep %s\n", cmdlst[i].sep);
        if(cmdlst[i].stdin_file != NULL)
            printf("stdin file: %s\n", cmdlst[i].stdin_file);
        if(cmdlst[i].stdout_file != NULL)
            printf("stdout file: %s\n", cmdlst[i].stdout_file);
        
        puts("");    
    }

    // clean pointer
    for(int i = 0; i < cmd_num; ++i)
    {
        if(cmdlst[i].stdin_file != NULL)
            free(cmdlst[i].stdin_file);
        if(cmdlst[i].stdout_file != NULL)
            free(cmdlst[i].stdout_file);
    }

    puts("");
    }

    return 0;
}

  • 写回答

4条回答 默认 最新

  • MarkHan_ 2023-03-17 22:30
    关注

    该回答引用GPTᴼᴾᴱᴺᴬᴵ
    根据提供的代码和信息,出现问题的地方可能是在fillCommandStructure函数中:

    void fillCommandStructure(Command *cp, int first, int last, char *sep)
    {
        cp->first = first;
        cp->last = last - 1;
        cp->sep = sep;
    }
    
    
    

    其中,cp->last 的值是 last - 1。由于 last 的值是从 0 开始计数的索引,因此在使用此索引访问数组时,数组中的最后一个元素将被忽略。这可能是导致出现问题的原因。
    ·
    为了解决这个问题,你可以尝试将 fillCommandStructure 函数中的 cp->last = last - 1 修改为 cp->last = last,或者在调用 fillCommandStructure 函数时将 last 参数传递为实际上应该是最后一个元素的索引值加 1,例如 last + 1。
    ·
    另外,fillCommandStructure 函数的调用在 separator 函数中进行。因此,还应该确保 fillCommandStructure 函数的调用不会在数组的最后一个元素上执行。你可以通过在 for 循环中将 i < nTokens - 1 作为条件来实现这一点,以避免在数组的最后一个元素上调用该函数。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(3条)

报告相同问题?

问题事件

  • 系统已结题 3月25日
  • 已采纳回答 3月17日
  • 赞助了问题酬金20元 3月17日
  • 赞助了问题酬金20元 3月17日
  • 展开全部

悬赏问题

  • ¥15 求购HI3519AV100开发板
  • ¥15 请问1553 RT怎么测试,没有BC有方法吗
  • ¥100 业务编程如何选择学习方向和内容?
  • ¥15 wamp3.3.5安装完成后图标正常显示绿色,鼠标左右键点击图标均无反应。求解决方法。
  • ¥15 鼠标点击的这条记录了什么?
  • ¥15 在写pid调速的程序时,电机始终维持最大速度
  • ¥15 【有偿】调用DXGI截图初始化失败,提示0xf 887a0004
  • ¥15 请问如何查看手机root记录?
  • ¥15 商城小程序订单号重复
  • ¥15 学校优化算法sbo和蚁群算法怎么结合