string与char*比较 ——why use string

本文对比了 C++ 中 string 类与 char* 的区别,详细介绍了 string 类的优势,如内存管理、运算符重载及字符串操作函数等,并展示了 string 在实际项目中的实现方式。

stringchar*比较

1 string是一个类,char*是一个指向char型的指针。

         string封装了char*,管理这个字符串封装了char*,是一个char*型的容器,使用灵活性强便于功能扩展。

2 不用考虑内存释放和越界

         String封装了char*,负责管理char*字符串,管理为char*所分配的内存。

         每一次string的复制,取值都由string类负责维护,不用担心复制越界和取值越界等。

3  string支持运算

重载运算符:

         string a;string b;string c;

         相加运算: c = a + b      ;

比较运算:a > b,          a != b;

4  能提供系列字符串操作函数

         查找find,拷贝copy,删除delete

         替换replace,插入insert

……

5 支持扩展

         使用静态内存或者动态内存

         使用资源ID加载字符串

         操作安全使用锁

         最本质的区别就是:string是一个类,char是基本类型,string封装了char

string的实现和应用

  C++标准库STL里面提供string的实现。

  这里看一下我工作平台中string的实现方式,感觉写的还不错,值得学习。

class String
{
public:
// Default constructor
String() : m_bufType(BUF_TYPE_NONE), m_buf(NULL)
{
}

// Initialized with resource ID
String(const U32 id);

// Copy constructor
String(const String &other) :
m_bufType(BUF_TYPE_NONE),
m_buf(NULL)
{
assignWith(other);
}

// Destructor
~String()
{
//保证分配的内存能够被释放
clear();
}

// Operator基本的运算操作 [],=,*,==,+=,……
public:
// RETURNS: The character at given position index
WChar operator [] (S32 index) const
{
return getItem(index);
}

// RETURNS: The buffer of the string
String &operator =(const String &other);

// RETURNS: The buffer of the string.
operator const WChar *() const
{
return m_buf;
}

// RETURNS: Return VFX_TRUE the string is equal to the other.
Bool operator ==(const String &other) const
{
return compareWith(other) == 0;
}

// RETURNS: Return VFX_TRUE the string is *not* equal to the other.
Bool operator !=(const String &other) const
{
return compareWith(other) != 0;
}

// RETURNS: Reference to the string
String &operator +=(const String &other)
{
appendWith(other);
return *this;
}

// Method
public:
// RETURNS: The character at given position index
WChar getItem(
S32 index // [IN] The position index to get
) const
{
return m_buf[index];
}

// SEE ALSO: unlockBuf
WChar *lockBuf(
VfxU32 initialLength // [IN] The initial buffer length, included zero terminal.
);

// SEE ALSO: lockBuf
void unlockBuf();

// RETURNS: The buffer of the string
const WChar *getBuf() const
{
return m_buf;
}

// RETURNS: The charactor numbers of the string.
U32 getLength() const;

// RETURNS: Return VFX_TRUE if the string is empty or NULL
Bool isEmpty() const
{
return m_buf ? (m_buf[0] == 0) : VFX_TRUE;
}

// RETURNS: Reference to the string
String &setEmpty();

// RETURNS: Return VFX_TRUE if the string is NULL
VfxBool isNull() const
{
return m_buf == NULL;
}

// RETURNS: Reference to the string
String &setNull()
{
clear();
return *this;
}

// RETURNS: Return VFX_TRUE if the string buffer is dynamic
Bool isDynamic() const
{
return VFX_FLAG_HAS(m_bufType, BUF_TYPE_DYNAMIC);
}

// RETURNS: Reference to the string
String &loadFromRes(ResId res_id);

// RETURNS: Reference to the string
String &loadFromMem(const WChar *mem);

// RETURNS: Reference to the string
String &format(const WChar *format, ...);

// RETURNS: Reference to the string
String &format(const WChar *format, ...);

protected:
const WChar *cloneBuf(const WChar *buf);
// Implementation
private:
BufTypeEnum m_bufType;
const WChar *m_buf;

// Helper methods
void clear();
void assignWith(const String &ohter);
void appendWith(const String &ohter);
S32 compareWith(const String &str) const;
};



转载于:https://www.cnblogs.com/bastard/archive/2012/01/07/2315885.html

char* filename_completion_function(const char* text, int state) { static DIR* dir = NULL; static char *filename = NULL, *dirname = NULL; static size_t filename_len = 0; struct dirent* entry; char* temp; size_t len; // 状态重置:当state==0时,表示新的补全请求 if (state == 0) { // 释放之前资源(增加空指针检查) if (dir) { closedir(dir); dir = NULL; } if (filename) { XFREE(MTYPE_TMP, filename); filename = NULL; } if (dirname) { XFREE(MTYPE_TMP, dirname); dirname = NULL; } // 解析text,分离目录文件名部分 const char *temp_ptr = strrchr(text, '/'); if (temp_ptr) { // 提取文件名部分(最后一个斜杠之后的内容) filename = XSTRDUP(MTYPE_TMP, temp_ptr + 1); if (!filename) return NULL; // 提取目录部分(包括最后一个斜杠) len = temp_ptr - text + 1; // 包括斜杠 dirname = XMALLOC(MTYPE_TMP, len + 1); if (!dirname) { XFREE(MTYPE_TMP, filename); return NULL; } strncpy(dirname, text, len); dirname[len] = '\0'; // 确保终止符 } else { // 没有斜杠,说明只有文件名(保持无前缀) filename = XSTRDUP(MTYPE_TMP, text); if (!filename) return NULL; dirname = XSTRDUP(MTYPE_TMP, ""); // 空字符串代替"./" if (!dirname) { XFREE(MTYPE_TMP, filename); return NULL; } } // 处理家目录展开(~user) if (dirname[0] == '~') { char *expanded = tilde_expand(dirname); if (expanded) { XFREE(MTYPE_TMP, dirname); dirname = expanded; } } filename_len = filename ? strlen(filename) : 0; // 打开目录(处理空目录名情况) const char *open_path = (dirname[0] == '\0') ? "." : dirname; dir = opendir(open_path); if (!dir) { XFREE(MTYPE_TMP, filename); XFREE(MTYPE_TMP, dirname); filename = NULL; dirname = NULL; return NULL; } } // 如果目录流未打开或资源未初始化,返回NULL if (!dir || !filename || !dirname) { return NULL; } // 遍历目录,寻找匹配项 while ((entry = readdir(dir)) != NULL) { // 跳过隐藏文件(以.开头),除非文件名以.开头 if (filename[0] != '.' && entry->d_name[0] == '.') { // 但允许匹配显式指定的隐藏文件 if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) { continue; } } // 检查文件名是否匹配 size_t entry_len = strlen(entry->d_name); if (entry_len < filename_len) { continue; } if (strncmp(entry->d_name, filename, filename_len) == 0) { // 计算路径长度(避免空目录名问题) size_t dir_len = strlen(dirname); len = dir_len + entry_len + 2; // +1 for null, +1 for possible '/' temp = XMALLOC(MTYPE_TMP, len); if (!temp) continue; // 分配失败则跳过 // 拼接目录文件名(处理空目录名) if (dir_len > 0) { snprintf(temp, len, "%s%s", dirname, entry->d_name); } else { strncpy(temp, entry->d_name, len); } // 检查是否为目录(使用d_type优化性能) int is_dir = 0; #if defined(_DIRENT_HAVE_D_TYPE) || defined(__linux__) if (entry->d_type == DT_DIR) { is_dir = 1; } else if (entry->d_type == DT_LNK || entry->d_type == DT_UNKNOWN) { // 需要stat检查 struct stat st; if (stat(temp, &st) == 0 && S_ISDIR(st.st_mode)) { is_dir = 1; } } #else // 没有d_type支持的系统使用stat struct stat st; if (stat(temp, &st) == 0 && S_ISDIR(st.st_mode)) { is_dir = 1; } #endif // 如果是目录,添加斜杠 if (is_dir) { size_t cur_len = strlen(temp); if (cur_len + 1 < len) { temp[cur_len] = '/'; temp[cur_len + 1] = '\0'; } else { // 重新分配以容纳斜杠 char *new_temp = XREALLOC(MTYPE_TMP, temp, cur_len + 2); if (new_temp) { temp = new_temp; strcat(temp, "/"); } } } // 返回当前匹配项 return temp; } } // 没有更多匹配项,清理资源 closedir(dir); dir = NULL; XFREE(MTYPE_TMP, filename); XFREE(MTYPE_TMP, dirname); filename = NULL; dirname = NULL; return NULL; } 我还是使用的这个函数 上层还是: char** cmlsh_completion(char* text, int start, int end) { char** matches; pal_printf("\ncmlsh_completion: enter------------------\n"); matches = completion_matches(text, cmlsh_completion_matches); // 如果命令补全失败,再尝试路径补全 if (!matches || !matches[0]) { matches = filename_completion_matches(text, filename_completion_function); } return matches; } 最上层是: void cmlsh_readline_init() { /* Input mode set to RAW mode. */ readline_zebos_set_excl_raw_input_mode(); /* '?' is the description function. */ rl_bind_key('?', cmlsh_describe); rl_bind_key('\t', rl_complete); /* Register completion function. */ rl_attempted_completion_function = (CPPFunction*)cmlsh_completion; } 但是这个代码逻辑只能显示文件夹,不能显示当前路径下的普通文件 例如: 假设当前etc目录下有1.txt 2.txt abc子目录,然后我输入dir e再按tab键补全,想要的效果是能显示出dir etc/ , 然后我再按tab键进行联想,应该要显示的是dir etc/1.txt ,然后我再按tab键进行联想,应该要显示的是dir etc/2.txt , 然后我再按tab键进行联想,应该要显示的是dir etc/abc/,然后我再按tab键进行联想,应该要显示的是dir etc/ 这样循环显示,每次只显示一次
07-29
#include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/wait.h> #include <sys/types.h> #include <signal.h> #define MAX_INPUT_SIZE 1024 #define MAX_ARGS 64 void execute_command(char **args); /* 执行命令 */ int main() { char input[MAX_INPUT_SIZE] = {0}; /* 存储用户输入缓冲区 */ char *args[MAX_ARGS] = {NULL}; /* 命令参数 */ char *token = NULL; /* 分割字符串 */ int arg_count = 0; /* 参数计数器 */ while (1) { printf("myshell > "); fflush(stdout); /* 获取输入, 处理 EOF */ if (fgets(input, sizeof(input), stdin) == NULL) { break; } /* 移除换行符 */ input[strcspn(input, "\n")] = '\0'; /* 处理 exit 命令 */ if (strcmp(input, "exit") == 0) { printf("Exiting shell...\n"); break; } /* 解析命令参数 */ token = strtok(input, " "); while (token != NULL && arg_count < MAX_ARGS - 1) { args[arg_count++] = token; token = strtok(NULL, " "); } args[arg_count] = NULL; /* 执行命令 */ execute_command(args); } return 0; } /* 执行命令函数 */ void execute_command(char **args) { /* 检查是否为内置命令 */ if (strcmp(args[0], "stop") == 0) { printf("Error: 'stop' is not a command. It should appear in program output.\n"); return; } pid_t pid = 0; int pipefd[2] = {0}; if (pipe(pipefd) == -1) { perror("pipe"); exit(EXIT_FAILURE); } pid = fork(); if (pid == -1) { perror("fork"); exit(EXIT_FAILURE); } else if (pid == 0)/* 子进程 */ { /* 关闭读取端 */ close(pipefd[0]); /* 重定向输出到管道 */ dup2(pipefd[1], STDOUT_FILENO); close(pipefd[1]); /* 执行命令 */ execvp(args[0], args); /* 执行失败 */ fprintf(stderr, "myshell: %s: command not found\n", args[0]); exit(EXIT_FAILURE); } else /* 父进程 */ { close(pipefd[1]); /* 关闭写入端 */ char buffer[MAX_INPUT_SIZE] = {0}; /* 输出缓冲区 */ ssize_t bytes_read = 0; /* 读取字节数 */ ssize_t total_printed = 0; /* 已打印字节数 */ char *stop_pos = strstr(buffer, "stop"); /* 检测输出中是否包含 stop */ /* 读取子进程输出 */ while ((bytes_read = read(pipefd[0], buffer, sizeof(buffer)-1)) > 0) { /* 确保字符串终止 */ buffer[bytes_read] = '\0'; /* 检测输出中是否包含 stop */ if (stop_pos) { /* 1、打印 stop 之前的内容 */ size_t keep_len = stop_pos - buffer; if (keep_len > 0) { printf("%.*s", (int)keep_len, buffer); fflush(stdout); } /* 2、打印stop本身 */ printf("stop"); fflush(stdout); /* 3、终止子进程并打印消息 */ kill(pid, SIGTERM); printf("\nReceived 'stop' in output. Terminating child process.\n"); fflush(stdout); /* 跳过后续处理 */ continue; } else /* 未检测到 stop 时正常打印输出 */ { printf("%s", buffer); fflush(stdout); } } close(pipefd[0]); /* 关闭读取端 */ waitpid(pid, NULL, 0); /* 等待子进程结束 */ } } 这是我的主要功能程序 #include <stdio.h> int main() { for (int i = 0; i < 5; i++) { printf("count: %d\n", i); if (i == 3) { printf("stop"); } } printf("This line should not be printed.\n"); return 0; } 这是我的测试程序 现在运行了./main后,输入以下内容: myshell > ./te myshell: ./te: command not found myshell > ./test count: 0 count: 1 count: 2 count: 3 stop Received 'stop' in output. Terminating child process. myshell > cat test.c cat: cat: No such file or directory cat: cat: No such file or directory #include <stdio.h> int main() { for (int i = 0; i < 5; i++) { printf("count: %d\n", i); if (i == 3) { printf("stop Received 'stop' in output. Terminating child process. myshell > 为什么会输出两个cat再输出test.c中的内容
最新发布
08-08
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值