Target readers: software engineers, architects, IT professionals, designers, etc.
Article goal: to improve our work efficiency
Table of contents
Understand code and generate function snippets
- How to let ChatGPT guide your programming projects
- How to use ChatGPT as your programming assistant
let's start.
overview
This article is divided into two parts; they are:
- start a programming project
- Understand code and generate function snippets
start a programming project
Let's consider a simple project: you want to set up a REST API server that will help you take a "screen capture" of an entire web page for a provided URL. (Optional) The REST API can accept an additional optional parameter of email address. In this case, screenshots are not returned, but emailed.
This is a project involving several components. You need something that listens for HTTP requests and responds accordingly, like a REST API server. You'll also need to grab the URL and take screenshots like a normal web browser. There's also logic in there, depending on whether an email address is provided; the output can be a returned image file, or send an email with an attachment.
If you are not familiar with how to create a REST API server or don't know the tools available, you can ask ChatGPT for help. Just write down all the details in the prompt and ask:
I need to create a REST API server that takes a URL as input, captures a screenshot of a webpage as JPEG and returns it as output. Optionally, the user may provide an email address as additional input. In this case, the screenshot should be emailed instead of returned. Can you help me with this procedure?
From this, ChatGPT generates the following suggestions:
certainly! I can help you. To create a REST API server that captures screenshots of web pages and handles optional email functionality, you can use Node.js with a few additional packages. Here's an overview of the steps you can follow:
1. Set up a new Node.js project and initialize it with npm:
mkdir screenshot-api cd screenshot-api npm init
2. Install the necessary packages. You needexpress
an API serverpuppeteer
to capture screenshots andnodemailer
send emails:npm install express puppeteer nodemailer
3. Createindex.js
the file and set up the base server with Express:const express = require('express'); const app = express(); const port = 3000; app.get('/screenshot', async (req, res) => { const url = req.query.url; const email = req.query.email; // Capture the screenshot using Puppeteer // Handle the response based on whether an email is provided }); app.listen(port, () => { console.log(`Server is running on port ${port}`); });
4.
/screenshot
Inside the route, use Puppeteer to capture a screenshot of the web page and handle the response accordingly:const puppeteer = require('puppeteer'); app.get('/screenshot', async (req, res) => { const url = req.query.url; const email = req.query.email; // Launch Puppeteer const browser = await puppeteer.launch(); const page = await browser.newPage(); // Navigate to the provided URL await page.goto(url); // Capture the screenshot const screenshotBuffer = await page.screenshot({ fullPage: true }); // Close the browser await browser.close(); // Handle the response based on whether an email is provided if (email) { // Send the email with the screenshot attachment using Nodemailer } else { // Send the screenshot as the response res.type('image/jpeg'); res.send(screenshotBuffer); } });
5. To handle sending emails with screenshot attachments, add the following code inside the block
if (email)
:const nodemailer = require('nodemailer'); // Create a transporter using your email service provider's details const transporter = nodemailer.createTransport({ service: 'your-email-service-provider', auth: { user: '[email protected]', pass: 'your-email-password', }, }); // Define the email options const mailOptions = { from: '[email protected]', to: email, subject: 'Web Page Screenshot', text: 'Please find the attached screenshot.', attachments: [ { filename: 'screenshot.jpg', content: screenshotBuffer, }, ], }; // Send the email transporter.sendMail(mailOptions, (error, info) => { if (error) { console.error(error); res.status(500).send('Failed to send email.'); } else { console.log(`Email sent: ${info.response}`); res.send('Screenshot emailed successfully!'); } });
Be sure to replace
'your-email-service-provider'
,'[email protected]'
, and'your-email-password'
with the details of your actual email service provider.6. Finally start the server:
node index.js
Now, when you make a GET request tohttp://localhost:3000/screenshot?url={URL}
, the server will capture a screenshot of the provided URL. If an email address is also providedemail={EMAIL}
, the server will send the screenshot as an email attachment instead of returning it directly.Remember to handle errors according to your requirements and add any necessary error checking or validation.
That's it! You now have a basic REST API server that can capture screenshots of web pages and optionally email them. Feel free to enhance it further according to your needs.
Here is a very detailed result of how to accomplish this programming task. The responses cover all the requirements, but you should note that ChatGPT will make some design decisions for you, such as which programming language to use, when you don't specify explicitly in the prompt.
It's not easy to take into account all the details on the first run, but the nature of ChatGPT allows you to provide follow-up prompts to modify answers, for example:
For the above problem, I want to use Python and FastAPI as web framework and Selenium as web browser. Can you rewrite this?
ChatGPT's response now becomes:
certainly! This is a revised version of the solution, using Python, FastAPI as the web framework, and Selenium for web browser automation.
1. Install the necessary packages. You need
fastapi
,uvicorn
to run the server andselenium
,webdriver_manager
to manage the network drivers:pip install fastapi uvicorn selenium webdriver_manager
2. Create a new file calledmain.py
and import the required modules:from fastapi import FastAPI, HTTPException from fastapi.responses import FileResponse from pydantic import BaseModel from selenium import webdriver from webdriver_manager.chrome import ChromeDriverManager from selenium.webdriver.chrome.options import Options from selenium.common.exceptions import WebDriverException from io import BytesIO app = FastAPI()
3. Define the request model to process the input data:
class ScreenshotRequest(BaseModel): url: str email: str = None
4. Create a route for web page screenshots:
@app.get("/screenshot") async def capture_screenshot(request: ScreenshotRequest): options = Options() options.headless = True try: # Set up the Chrome webdriver driver = webdriver.Chrome(ChromeDriverManager().install(), options=options) driver.set_window_size(1280, 720) # Navigate to the provided URL driver.get(request.url) # Capture the screenshot screenshot = driver.get_screenshot_as_png() screenshot_buffer = BytesIO(screenshot) # Close the browser driver.quit() if request.email: # Send the email with the screenshot attachment return "Screenshot emailed successfully!" else: # Return the screenshot as a response return FileResponse(screenshot_buffer, media_type="image/png") except WebDriverException: raise HTTPException(status_code=400, detail="Failed to capture screenshot.")
5. Start the server with Uvicorn:
uvicorn main:app --reload
Now, when you make a GET request to http://localhost:8000/screenshot?url={URL}, the server will capture a screenshot of the provided URL. If an email address is also provided, you can handle sending an email with a screenshot attachment using the field email={EMAIL} in the request. email
Remember to handle errors according to your requirements and add any necessary error checking or validation.
NOTE: This solution assumes Chrome is installed on your computer. If you use a different browser, you will need to adjust your web driver accordingly.
That's it! You now have a REST API server using Python, FastAPI, and Selenium to capture web page screenshots and handle optional email functionality.
You can see that you didn't provide any unnecessary detail in the follow-up prompt other than mentioning "the above issue", but ChatGPT can accurately "translate" the Node.js implementation to Python and use the library you specified.
This is a great result, although you may still have to polish the code. An example is that the browser screen size definitely affects how the web page is rendered, but in the above the size is hardcoded because you didn't specify that it should be adjusted in the hint. Another potential reason to polish the generated code is to catch other coding style issues or to add defenses against security issues.
In summary, as with other use cases, being clear enough to enter more details in the prompt is key to getting a useful response. In the case of programming tasks, layout details are crucial
- what is the goal
- What is the input and output format
- Which tools should the program use
- What are the different situations a program might encounter and how they should be handled
Understand code and generate function snippets
Sometimes, instead of writing one big program, you want to write a smaller function. You can ask ChatGPT to generate a function for you using a prompt similar to the one above, but you need to specify the output format, eg function or class.
In fact, you can also do the reverse, by giving ChatGPT the code and asking it to explain it in English. It can be useful at times, especially when deciphering other people's code. Let's consider the following example:
Please explain what the following code does:
float det(float** a, float k) { float s = 1, ret = 0, **b; int i, j, m, n, c; if (k == 1) { return a[0][0]; } else { b = (float**) malloc(sizeof(float*)*k); for (i = 0; i < k; i++) b[i] = (float*) malloc(sizeof(float)*k); ret = 0; for (c = 0; c < k; c++) { m = 0; n = 0; for (i = 0; i < k; i++) { for (j = 0; j < k; j++) { b[i][j] = 0; if (i != 0 && j != c) { b[m][n] = a[i][j]; if (n < (k - 2)) n++; else { n = 0; m++; } } } } ret = ret + s * (a[0][c] * det(b, k - 1)); s = s * -1; }; for (i = 0; i < k; i++) free(b[i]); }; free(b); return ret; }
This prompt is simple: just one key word, "explain." But note how you provide code to ChatGPT: use backticks to follow Markdown's code fence syntax to refer to programs. This helps identify which are your directives and which are not.
While it's not a very long program, ChatGPT explains the code in great detail. It also determines the high-level intent, which is to compute the determinant of the matrix. Here is the response:
The code you provided is a recursive implementation of computing the determinant of a square matrix using Laplace expansion.
Here's a step-by-step breakdown of what the code does:
- The function takes two parameters: a pointer
det
to a two-dimensional array ( ) representing the matrix , and the size of the matrix ( ).float** a
float k
- It declares some variables:
s
for symbols,ret
for determinant values, and**b
as temporary matrices.- It checks for
k
equal to 1. If yes, it means we have reached the base case of a 1×1 matrix, and the function returns a single value in the matrix, the determinant.- If
k
it is greater than 1, the calculation continues.b
It dynamically allocates memory for ak
temporary matrix of size xk
.- It is initialized
ret
to 0.- It enters a loop that iterates over each column of the first row of the matrix
a
.- Inside the loop, it resets the index
m
and sumn
to 0.- It enters a nested loop that iterates over each element of the matrix
a
.b
Inside the nested loop, itm
sets the element at position , in the temporary matrixn
to 0.- It checks if the current element is not in the first row (
i != 0
) and not in the current column (j != c
).a
If the element is not in the first row or the current column, the value is copied from the matrix to the temporary matrix at position, .b
m
n
m
Itn
updates the index based on the position of the next element in theb
.b
After the nested loop, it computes the determinant of the submatrix by recursively calling the function with the temporary matrix and size .det
b
k - 1
- It multiplies the determinant of the submatrix by sign
s
(alternating sign).- It multiplies the sign
s
by -1 to switch the sign for the next iteration.- It adds to the running sum the product of the sign, the element in the first row (
a[0][c]
), and the determinant of the submatrixret
.- The loop continues to the next column.
- After the loop finishes, it frees the memory allocated for each row of the temporary matrix
b
.- It frees the memory allocated for the temporary matrix
b
.- Finally, it returns the calculated determinant value
ret
.In summary, the code recursively computes the determinant of a square matrix by performing a Laplace expansion along the first row. It uses a temporary matrix to store the resulting submatrix excluding the first row and selected columns. The recursion continues until the base case of a 1×1 matrix is reached.
Subsequent improvement code
This code is not easy to understand at first glance. There may be a way to make it easier to read. Indeed, ChatGPT can do a good job in this situation, with a very simple follow-up tip:
Can you rewrite this code and add comments for clarity?
The key words here are "for clarity" and "adding a comment". ChatGPT provides the following response:
certainly! Here's a revised version of the code with comments explaining each step:
float determinant(float** matrix, int size) { float sign = 1; // Sign of the determinant float result = 0; // Determinant value float** submatrix; // Temporary submatrix int i, j, m, n, c; // Loop variables // Base case: 1x1 matrix if (size == 1) { return matrix[0][0]; } else { // Allocate memory for the temporary submatrix submatrix = (float**)malloc(sizeof(float*) * size); for (i = 0; i < size; i++) { submatrix[i] = (float*)malloc(sizeof(float) * size); } // Calculate the determinant for (c = 0; c < size; c++) { m = 0; n = 0; // Create the submatrix by excluding the first row and the current column for (i = 0; i < size; i++) { for (j = 0; j < size; j++) { submatrix[i][j] = 0; // Copy values to the submatrix if (i != 0 && j != c) { submatrix[m][n] = matrix[i][j]; // Update submatrix indices if (n < (size - 2)) { n++; } else { n = 0; m++; } } } } // Calculate the determinant of the submatrix recursively result += sign * matrix[0][c] * determinant(submatrix, size - 1); // Flip the sign for the next iteration sign *= -1; } // Free the memory allocated for the submatrix for (i = 0; i < size; i++) { free(submatrix[i]); } free(submatrix); return result; } }
I have added comments above each important part of the code to explain what it does. This should make the code more readable and easier to understand.
This version is undoubtedly easier to read.
Plus, you can ask for more. Examples include a requirement to catch bugs or potential security issues in the code. Let's ask ChatGPT to generate some unit test code:
Can you give me some unit test cases to make sure this works well?
Without needing any further explanation, here is the response:
certainly! Here are a few unit test cases to verify the correctness of the function
determinant
:Test Case 1: 2×2 Matrix
float matrix1[2][2] = { {2, 3}, {1, 4}}; float** ptrMatrix1 = (float**)matrix1; float det1 = determinant(ptrMatrix1, 2); // Expected output: 5
Test case 2: 3×3 matrixfloat matrix2[3][3] = { {6, 1, 1}, {4, -2, 5}, {2, 8, 7}}; float** ptrMatrix2 = (float**)matrix2; float det2 = determinant(ptrMatrix2, 3); // Expected output: -306
Test case 3: 4×4 matrixfloat matrix3[4][4] = { {1, 0, 2, -1}, {3, 0, 0, 5}, {2, 1, 4, -3}, {1, 0, 5, 0}}; float** ptrMatrix3 = (float**)matrix3; float det3 = determinant(ptrMatrix3, 4); // Expected output: -20
These test cases cover matrices of different sizes (2x2, 3x3, and 4x4) and include positive, negative, and zero determinant values.determinant
You can verify that the function is working correctly by comparing the calculated determinant value with the expected output .
But it's clear that the unit test code misses one corner case: 1x1 matrices. This shows that ChatGPT is not always perfect. You can only use it as your assistant, not as a replacement. You should always verify the results.
summarize
In this article, you learned how ChatGPT can help you with programming. Not only can it generate code as part of the response to your question, but it can also figure out the intent of the code you provide. Specifically, you've learned:
- You can use ChatGPT to generate initial code for a software project, or to generate test code for a function
- You can ask ChatGPT to explain the code to you
- You can leverage ChatGPT to refactor and clean up your code