现在大模型能力非常强,可以帮我们减少不少的查资料的时间,我给出两个建议,和几个编程问题,给大家提供一个新的思路。
精准高效的描述问题
现在需求是需要将一个char * 的字符数组转换成int型,很简单的需求,如果你这么问
// 帮我写一个函数,将字符型转换成int型
大模型肯能会给你一个python的代码,那肯定不对,加上一个c++ , 和关键字
// 帮我写一个函数,c++,输入char *,将其转换成int ,返回int
好了,这个时候他就可能给你c++代码了,这个时候你就会想,他代码会不会有错,能用库函数就用库函数。
// c++库函数,输入char *,将其转换成int ,返回int
这个时候他就会给你atoi这个函数的使用说明了,还会给你demo
就是两个方面,一方面是尽可能多的给出关键词,这样大模型的结果不会跑偏,另一方面是追问,跑偏了之后,追加问题。
保持批判,不能全信
serverAddress.sin_addr.s_addr = inet_addr(master_ip.c_str()); 这行代码当master_ip是localhost的时候,能正常运行吗?
这个问题,他回答的是 可以, 会自动把localhost改成127.0.0.1,我当时信了,哈哈,然后后面老是不能连接上服务端,结果gdb发现他不能接受localhost。
所以gpt很聪明,有时候也很傻,要保持一个批判的思路,他给的代码可能会出错。
示例一 翻译文档
这个真的太舒服了,英文文档可以直接复制给gpt ,然后在后面加一句 “ 翻译成中文 ” 就好了,但是可能会有字数限制,这里推荐一个AI的翻译网站,deepl,也很香,还可以chrome插件。
示例二 写简单的代码
// 帮我写一个二分查找的代码,c++
#include <iostream>
#include <vector>
int binarySearch(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // found the element
} else if (arr[mid] < target) {
left = mid + 1; // continue searching in the right half
} else {
right = mid - 1; // continue searching in the left half
}
}
return -1; // element not found
}
int main() {
std::vector<int> arr = {2, 5, 8, 12, 16, 23, 38, 56, 72, 91};
int target = 23;
int result = binarySearch(arr, target);
if (result != -1) {
std::cout << "Element found at index: " << result << std::endl;
} else {
std::cout << "Element not found in the array." << std::endl;
}
return 0;
}
这个就是他生成的
示例三 查API和命令
// c++ ptrace函数的作用,参数,和返回值,给我一个demo
ptrace 是一个 Linux 系统调用,可以用于跟踪进程的执行和修改进程的行为。
作用:
跟踪进程的系统调用
检查和修改进程的内存
获取和修改寄存器的内容
控制目标进程的执行
等等
参数:
request: 定义要执行的操作,例如跟踪、设置寄存器值、读取内存等。
pid: 要操作的目标进程的进程 ID。
addr: 进程内存地址,根据具体的操作可能需要提供该参数。
data: 用于传递或接收数据,根据具体的操作可能需要提供该参数。
regs: 进程的寄存器状态,根据具体的操作可能需要提供该参数。
返回值:
根据操作的具体结果,返回不同的值。一般来说,成功执行时返回 0,错误时返回 -1。
以下是一个简单的 C++ 演示,展示了如何使用 ptrace 来跟踪另一个进程的系统调用。由于 ptrace 涉及到操作系统级的功能,因此需要在 Linux 系统上运行。
#include <iostream>
#include <sys/ptrace.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main() {
pid_t pid = fork();
if (pid == 0) {
// Child process
ptrace(PTRACE_TRACEME, 0, 0, 0); // Allow parent to trace this process
execl("/bin/ls", "ls", nullptr);
} else {
// Parent process
waitpid(pid, nullptr, 0);
long orig_eax = ptrace(PTRACE_PEEKUSER, pid, 4 * ORIG_EAX, 0); // Read the system call number
std::cout << "The child made a system call " << orig_eax << std::endl;
ptrace(PTRACE_CONT, pid, 0, 0); // Continue the child's execution
}
return 0;
}
在这个示例中,我们创建了一个子进程并让它执行 /bin/ls 命令。父进程使用 ptrace 跟踪子进程的系统调用,并输出子进程所调用的系统调用号。这只是 ptrace 功能的一小部分,你可能需要根据具体的需求进行更详细和特定的操作。
示例四 写测试程序和shell
int binarySearch(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // found the element
} else if (arr[mid] < target) {
left = mid + 1; // continue searching in the right half
} else {
right = mid - 1; // continue searching in the left half
}
}
return -1; // element not found
} 帮我写几个测试用例,包括临界值,查找成功和失败,和空数组
以下是针对给出的二分查找函数的一些测试用例:
#include <iostream>
#include <vector>
int binarySearch(const std::vector<int>& arr, int target) {
int left = 0;
int right = arr.size() - 1;
while (left <= right) {
int mid = left + (right - left) / 2;
if (arr[mid] == target) {
return mid; // found the element
} else if (arr[mid] < target) {
left = mid + 1; // continue searching in the right half
} else {
right = mid - 1; // continue searching in the left half
}
}
return -1; // element not found
}
int main() {
// 测试用例1: 查找成功
std::vector<int> arr1 = {1, 3, 5, 7, 9, 11, 13, 15};
int target1 = 7; // 中间值
int result1 = binarySearch(arr1, target1);
std::cout << "Index of " << target1 << " is " << result1 << std::endl;
// 测试用例2: 查找失败
int target2 = 6; // 不存在的值
int result2 = binarySearch(arr1, target2);
std::cout << "Index of " << target2 << " is " << result2 << std::endl;
// 测试用例3: 边界值
std::vector<int> arr2 = {4, 8, 12, 16, 20, 24, 28};
int target3 = 16; // 边界值
int result3 = binarySearch(arr2, target3);
std::cout << "Index of " << target3 << " is " << result3 << std::endl;
// 测试用例4: 空数组
std::vector<int> arr3;
int target4 = 5; // 空数组
int result4 = binarySearch(arr3, target4);
std::cout << "Index of " << target4 << " in empty array is " << result4 << std::endl;
return 0;
}
这些测试用例包括了查找成功、查找失败、边界值和空数组的情况。你可以运行这些测试用例来验证二分查找函数的功能。
示例五 了解新工具,找demo
// flex是啥?有什么作用?给我一个demo
Flex 是一个用于生成词法分析器的工具,也称作词法分析器生成器。它可以根据用户定义的正则表达式规则来生成 C 或 C++ 代码,用于识别输入中的词法单元(如关键字、标识符、操作符等)。Flex 的作用是帮助开发者更轻松地构建词法分析器,从而用于编程语言解析、文本分析等领域。
以下是一个简单的示例,展示了如何使用 Flex 来定义一些词法规则,并生成词法分析器代码。假设我们要识别简单的算术表达式中的加法操作符。
首先,我们创建一个名为 demo.l 的 Flex 源文件:
%{
#include <iostream>
%}
%%
"+" { std::cout << "加法操作符" << std::endl; }
. { } // 忽略其他字符
%%
int main() {
yylex();
return 0;
}
然后,我们使用 Flex 工具将其编译成 C++ 代码:
flex demo.l
g++ lex.yy.c -lfl -o lexer
最后,运行生成的可执行文件:
./lexer
在输入中输入 +,你将会看到输出 "加法操作符"。
这只是一个非常简单的示例,Flex 还可以处理更复杂的词法规则并生成对应的词法分析器。通过定义适当的规则和动作,Flex 生成的词法分析器可以用于识别和处理更复杂的词法结构。
反正不了解的就问,出bug了也给gpt,他可能会告诉你问题在哪里。
// 帮我写一个cmake文件,头文件在include下,y源文件在src下,需要链接库pthread
以下是一个简单的 CMakeLists.txt 文件示例,用于构建一个项目,该项目包含头文件在 include 目录下,源文件在 src 目录下,并且需要链接 pthread 库。
cmake_minimum_required(VERSION 3.5)
project(YourProjectName)
# 设置 C++ 标准
set(CMAKE_CXX_STANDARD 11)
# 设置包含的头文件路径
include_directories(include)
# 添加源文件
file(GLOB SOURCES "src/*.cpp")
# 生成可执行文件
add_executable(YourExecutable ${SOURCES})
# 链接 pthread 库
find_package(Threads REQUIRED)
target_link_libraries(YourExecutable Threads::Threads)
请将 YourProjectName 替换为你的项目名称,将 YourExecutable 替换为你的可执行文件名称。
这个示例假设你的项目的源文件都是以 .cpp 结尾的,如果包含其他类型的源文件,你需要适当地修改 file(GLOB SOURCES "src/*.cpp") 部分。
你可以将这个 CMakeLists.txt 文件放在项目的根目录下,并在根目录下创建 include 和 src 目录,然后将相应的头文件和源文件放在这些目录中。然后使用 cmake 命令来生成 Makefile (或者其他构建系统的配置文件),然后使用构建系统来编译和链接你的项目。
这个cmakelist肯定是有错误的,但是我们可以改嘛,这里给一个正确版本的吧。
cmake_minimum_required(VERSION 3.13)
project(redis-starter-cpp)
set(CMAKE_CXX_STANDARD 20) # Enable the C++20 standard
set(SOURCE_FILES src/Server.cpp)
# 添加 -g 选项
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g")
# 头文件搜索路径
include_directories(${PROJECT_SOURCE_DIR}/include)
# 获取所有源文件列表
file(GLOB_RECURSE SOURCES "src/*.cpp" "include/*.h")
add_executable(server ${SOURCE_FILES} ${SOURCES})
target_link_libraries(server -pthread)
示例六 改bug
int minEditCost(string str1, string str2, int ic, int dc, int rc) {
str1=" "+str1;
str2=" "+str2;
vector<vector<int>> dp(str1.size(),vector<int>(str2.size(),0));
for(int i=1;i<dp[0].size();i++){
dp[0][i]=i*ic;
}
for(int i=1;i<dp.size();i++){
dp[i][0]=i*dc;
for(int j=1;j<dp[0].size();j++){
if(str1[i]==str2[j]){
dp[i][j]=min(dp[i-1][j],min(dp[i-1][j-1],dp[i][j-1]));
}else{
dp[i][j]=min(dp[i-1][j]+dc,min(dp[i-1][j-1]+rc,dp[i][j-1]+ic));
}
}
}
return dp.back().back();
} 哪里不对?(这是leetcode上的题目,我有几个测试用例没过)
在你的代码中,你试图实现用于计算两个字符串之间的最小编辑成本的动态规划算法。算法应该能够正确计算插入、删除和替换操作的成本,但是有几个关键的问题需要注意和修正:
初始化问题:
在初始化dp[0][i]的时候,你正确地处理了插入成本,即将str2中的字符插入到str1中。
对于dp[i][0],你正确地处理了删除成本,即将str1中的字符删除以匹配str2。
转移方程问题:
当str1[i] == str2[j]时,你设置了dp[i][j]为min(dp[i-1][j], min(dp[i-1][j-1], dp[i][j-1]))。这不正确,因为当两个字符相同时,最佳操作是不进行任何操作(即直接采用左上角的值),所以应该直接使用dp[i-1][j-1]。
当字符不同时,你的计算是dp[i][j] = min(dp[i-1][j] + dc, min(dp[i-1][j-1] + rc, dp[i][j-1] + ic)),这部分是正确的,正确地处理了删除、替换和插入成本。
代码修正:
当两个字符相同时,应该直接使用dp[i-1][j-1]的值。
对于字符不同的情况,你的逻辑是正确的。
修正后的代码如下:
cpp
int minEditCost(string str1, string str2, int ic, int dc, int rc) {
str1 = " " + str1;
str2 = " " + str2;
vector<vector<int>> dp(str1.size(), vector<int>(str2.size(), 0));
for (int i = 1; i < dp[0].size(); i++) {
dp[0][i] = i * ic; // Cost of inserting str2's characters into str1
}
for (int i = 1; i < dp.size(); i++) {
dp[i][0] = i * dc; // Cost of deleting str1's characters to match str2
for (int j = 1; j < dp[0].size(); j++) {
if (str1[i] == str2[j]) {
dp[i][j] = dp[i-1][j-1]; // No cost if characters are the same
} else {
dp[i][j] = min(dp[i-1][j] + dc, // Delete from str1
min(dp[i-1][j-1] + rc, // Replace str1's character with str2's
dp[i][j-1] + ic)); // Insert into str1
}
}
}
return dp.back().back();
}
这个修正确保了在字符相同时不会错误地增加编辑成本,并且保持了在字符不同时采用正确的编辑操作。
AI插件推荐
这里推荐一下vscode 插件 fittencode,可以写代码,写测试程序,还可以改bug,虽然比不上chatgpt4,但是他不要钱,而且很快,不需要翻墙。
使用下来,chatgpt4还是比较聪明的,一些比较偏僻的yacc语法,sql连表查询都可以搞定。
一些小问题gpt都可以解决,省下来很多时间。我们就可以专注于gpt做不到的,比方说,系统设计,代码调试,环境配置,还是需要我们自己解决。
另外,gpt写的代码一定要自己看一下,不然找bug要找半天。