我正在try 用C语言编写一个类似于Ubuntu终端的应用程序,它支持命令Touch、ls和Clear(在某种程度上).(在run函数中)当我使用Touch命令创建文件时,命令被解析,名称被放入new_thing char[]中.它将文件名分配给new_thing.在每个命令之后,我使用Memset重置变量new_thing.然而,当我使用ls命令时,名称是空白的,我不知道为什么.

我try 更改重置变量的方式,但无济于事.在我看来,无论我将new_thing设置为什么,每个文件名都被设置为new_thing,即使我只设置了一次文件.代码如下.

手C

    #include "file_explorer.h"
    
    int main(void)
    {
      run();
      return 0;
    }

file_explorer.h

    #ifndef FILE_EXPLORER_H_
    #define FILE_EXPLORER_H_
    
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    #include <stdbool.h>
    #include <string.h>
    
    #define READ_PERMISSIONS    0x04
    #define WRITE_PERMISSIONS   0x02
    #define EXECUTE_PERMISSIONS 0x01
    #define ADMIN_PERMISSIONS   0x07
    #define LS_COMMAND    "ls"
    #define CD_COMMAND    "cd"
    #define PWD_COMMAND   "pwd"
    #define MKDIR_COMMAND "mkdir"
    #define TOUCH_COMMAND "touch"
    
    typedef struct File File;
    typedef struct Folder Folder;
    
    struct File {
      char *file_name;
      char *file_path;
      uint8_t file_permissions;
      char *contents;
    };

    struct Folder {
      char *folder_name;
      char *folder_path;
      File files[5];
      Folder *folders[2];
    };

    File new_file( char * , uint8_t );
    char *add_contents(char * );
    Folder new_folder( char * );
    void change_directory(char * );
    void print_file(char * );
    void run();
    
    #endif

文件资源管理器.c

    #include "file_explorer.h"
    
    char current_path[100] = "";
    char input[100] = "";
    char command[10] = "";
    char new_thing[90] = "";
    Folder home;
    
    File new_file(char *file_name, uint8_t file_permissions)
    {
      File file = {
        .file_name = file_name,
        .file_path = current_path,
        .file_permissions = file_permissions,
        .contents = NULL
      };
      return file;
    }
    
    char * add_contents(char * contents)
    {
      return contents; 
    }
    
    Folder new_folder(char *folder_name)
    {
      Folder folder = {
        .folder_name = folder_name,
        .folder_path = current_path,
        .files = NULL,
        .folders = NULL
      };
      return folder;
    }
    
    void change_directory(char *directory)
    {
      strcat(current_path, "/");
      strcat(current_path, directory);
    }
    
    void print_file(char *contents)
    {
      if (contents == NULL)
      {
        printf("ERROR: File empty\n");
      } else 
      {
        printf("%s\n", contents);
      }
    }
    
    void run()
    {
      system("clear");
      home = new_folder("home");  
      int counter = 0;
      while (true)
      {
        printf("parker@PARKERMASON%s$ ", current_path);
        fgets(input, sizeof(input), stdin);
        input[strcspn(input, "\n")] = 0;
        memset(command,0,strlen(command));
        memset(new_thing,0,strlen(new_thing));
    
        if (input[0] == 't' && input[1] == 'o' && input[2] == 'u' && input[3] == 'c' && input[4] == 'h' && input[5] == ' ')
        {
          int i = strlen(TOUCH_COMMAND) + 1;
          strcpy(command, TOUCH_COMMAND);
           
          for (int j = 0; j < strlen(input) - strlen(TOUCH_COMMAND) - 1; j++)
          {
            new_thing[j] = input[i];
            i++;
          }
          
          if (counter == 0)
          {
            home.files[0] = new_file(new_thing, ADMIN_PERMISSIONS);
            printf("%s\n", home.files[0].file_name);
          } else if (counter == 1)
          {
            home.files[1] = new_file(new_thing, ADMIN_PERMISSIONS);
          } else if (counter == 2)
          {
            home.files[2] = new_file(new_thing, ADMIN_PERMISSIONS);
          } else if (counter == 3)
          {
            home.files[3] = new_file(new_thing, ADMIN_PERMISSIONS);
          } else if (counter ==  4)
          {
            home.files[4] = new_file(new_thing, ADMIN_PERMISSIONS);
          } else
          {
            printf("Folder full\n");
          }
          counter++;
        } else if (input[0] == 'l' && input[1] == 's' && input[2] == '\0')
        {
          for (int j = 0; j < sizeof(home.files) / sizeof(home.files[0]); j++)
          {
            if (home.files[j].file_name != NULL)
            {
              printf("%s ", home.files[j].file_name);
            } else
            {
              printf("EMPTY ");
            }
          }
        printf("\n"); 
        } else if (input[0] == 'c' && input[1] == 'd' && input[2] == ' ')
        {
          int i = strlen(CD_COMMAND) + 1;
          strcpy(command, CD_COMMAND);
          
          for (int j = 0; j < strlen(input) - strlen(CD_COMMAND) - 1; j++)
          {
            new_thing[j] = input[i];
            i++;
          }
        }
        else if (input[0] == 'c' && input[1] == 'l' && input[2] == 'e' && input[3] == 'a' && input[4] == 'r' && input[5] == '\0')
        {
          system("clear");
        }
      }
    }

推荐答案

File new_file(char *file_name, uint8_t file_permissions){
    File file = {
        .file_name = file_name,
    //...
}

上述代码片段将指针参数file_name存储到 struct file.特别是,它不复制原始字符串.这意味着每当更新file_name指向的缓冲区时,您通过file.file_name观察到的字符串也会更新.

调用此函数时使用

home.files[0] = new_file(new_thing, ADMIN_PERMISSIONS);

与上面的组合在一起,它意味着home.files[0].file_name == new_thing,并且它们指向相同字符串的开头,所以当您这样做时并不奇怪

memset(new_thing,0,strlen(new_thing));

并判断home.files[0].file_name后,它是空的.

您实际上想要做的是在 struct 中存储字符串的副本.如果您的系统支持,则可以在strdup之前完成此操作.

File new_file(char *file_name, uint8_t file_permissions){
    File file = {
        .file_name = strdup(file_name),
    //...
}

请注意,您需要适当地释放file.file_name的内存,以避免内存泄漏.

如果没有strdup个,则应该手动分配缓冲区并将字符串复制到其中.

File new_file(char *file_name, uint8_t file_permissions){
    char* file_name_copy = malloc(strlen(file_name)+1);
    if(!file_name_copy){
        //error handling, early return
    }
    strcpy(file_name_copy, file_name);
    File file = {
        .file_name = file_name_copy,
    //...
}

附注:

input[0] == 't' && input[1] == 'o' && input[2] == 'u' && input[3] == 'c' && input[4] == 'h' && input[5] == ' '

这真的是不必要的冗长,应该只是strncmp(input, "touch ", 6).

else if (counter == 1)
{
    home.files[1] = new_file(new_thing, ADMIN_PERMISSIONS);
} else if (counter == 2)
{
    home.files[2] = new_file(new_thing, ADMIN_PERMISSIONS);
}
//...

这只是

else if(counter < 5){
    home.files[i] = new_file(new_thing, ADMIN_PERMISSIONS);
}
//...

C++相关问答推荐

生成C代码时自动复制/生成' tmwtypes.h '依赖项

在x86汇编中,为什么当分子来自RDRAND时DIV会引发异常?

你能用自己的地址声明一个C指针吗?

从组播组地址了解收到的数据包长度

为什么在C中二维字符数组会有这样的行为?

警告:C++中数组下标的类型为‘char’[-Wchar-subpts]

在一个小型玩具项目中实现终端历史记录功能

在c++中使用堆栈的有效括号

RawMotion的XInput2错误(具有较高值的XISelectEvents上的BadValue)

为什么数组的最后一个元素丢失了?

如何在提取的索引中分配空值?

链接到底是如何工作的,我在这里到底做错了什么

Tic-tac-toe:从文件加载存储

不确定如何处理此编译错误

Linux Posix消息队列

在Ubuntu上使用库部署C程序的最佳实践

浮点正零何时不全为零?

在同一范围内对具有相同类型的变量执行的相同操作在同一C代码中花费的时间不同

在分配内存后使用指针是未定义的行为吗?

段错误try 访问静态字符串,但仅有时取决于构建环境