把sprintf进行改造
时间: 2023-10-24 09:06:32 浏览: 47
sprintf是C语言的标准库函数,用于将格式化的数据写入字符串中。如果要对其进行改造,可以考虑以下两种方案:
1. 使用安全的格式化函数
sprintf存在缓冲区溢出的风险,可以使用安全的格式化函数snprintf来代替。snprintf函数会限制输出字符的数量,避免缓冲区溢出。
例如,原有的代码可能是这样的:
```
char str[100];
int num = 123;
sprintf(str, "The number is %d", num);
```
使用snprintf进行改造后,可以这样写:
```
char str[100];
int num = 123;
snprintf(str, sizeof(str), "The number is %d", num);
```
这样就可以避免缓冲区溢出的问题。
2. 使用字符串模板库
除了使用标准库函数,还可以考虑使用字符串模板库来进行格式化输出。字符串模板库可以提供更加灵活和安全的格式化方式,避免了手动编写格式化字符串的麻烦。
例如,可以使用C++11标准库中的std::string和std::to_string函数来进行字符串拼接和数值转换,代码可能是这样的:
```
#include <string>
int num = 123;
std::string str = "The number is " + std::to_string(num);
```
这样不仅避免了缓冲区溢出的问题,而且还可以更加灵活地进行格式化输出。
相关问题
请帮我进行系统调用编程 ,要求如下使用系统调用open read write,完成一个C语言程序:该程序接收两个参数,参数1作为要读写的文件,参数2作为标志位,标识是读还是写。功能完成对参数1所示文件的读写,该文件的内容为 “学号 MYFILE”,其中学号填为自己的学号。 改造上面的程序,使用semaphore,并利用该程序生成2个进程,这两个进程写同一个文件,要求:a.互斥写,即只有一个进程写完后,才能让另一个进程写; b. 一个进程写入内容:“自己学号的后3位PROC1 MYFILE1”;另一个进程写入内容:“自己学号的后3位PROC2 MYFILE2” 请提交代码截图和运行结果截图
好的,首先是第一个要求的程序实现:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
int main(int argc, char* argv[]) {
if (argc != 3) {
printf("Usage: %s filename flag\n", argv[0]);
exit(1);
}
int fd;
if (strcmp(argv[2], "r") == 0) {
fd = open(argv[1], O_RDONLY);
} else if (strcmp(argv[2], "w") == 0) {
fd = open(argv[1], O_WRONLY);
} else {
printf("Invalid flag: %s\n", argv[2]);
exit(1);
}
if (fd == -1) {
perror("open");
exit(1);
}
char buf[20];
if (read(fd, buf, 20) == -1) {
perror("read");
exit(1);
}
if (strcmp(argv[2], "r") == 0) {
printf("Content of file %s: %s\n", argv[1], buf);
} else {
char* my_file = malloc(sizeof(char) * 10);
sprintf(my_file, "MYFILE%d", atoi(argv[1]+6));
sprintf(buf, "%sPROC%d", argv[1]+7, getpid()%2+1);
if (write(fd, buf, strlen(buf)) == -1) {
perror("write");
exit(1);
}
printf("Content written to file %s: %s\n", my_file, buf);
free(my_file);
}
if (close(fd) == -1) {
perror("close");
exit(1);
}
return 0;
}
```
然后是使用 semaphore 实现的程序:
```c
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <string.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
printf("Usage: %s filename\n", argv[0]);
exit(1);
}
sem_t* sem_write;
sem_t* sem_read;
sem_t* sem_mutex;
int fd;
char* buf;
char* my_file;
sem_write = sem_open("write", O_CREAT, 0644, 1);
sem_read = sem_open("read", O_CREAT, 0644, 0);
sem_mutex = sem_open("mutex", O_CREAT, 0644, 1);
if (sem_write == SEM_FAILED || sem_read == SEM_FAILED || sem_mutex == SEM_FAILED) {
perror("sem_open");
exit(1);
}
fd = open(argv[1], O_RDWR | O_CREAT | O_TRUNC, 0644);
if (fd == -1) {
perror("open");
exit(1);
}
if (ftruncate(fd, 40) == -1) {
perror("ftruncate");
exit(1);
}
buf = mmap(NULL, 40, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (buf == MAP_FAILED) {
perror("mmap");
exit(1);
}
my_file = malloc(sizeof(char) * 10);
sprintf(my_file, "MYFILE%d", getpid()%2+1);
int pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
} else if (pid == 0) {
// child process
while (1) {
sem_wait(sem_write);
sem_wait(sem_mutex);
sprintf(buf, "%sPROC1", argv[0]+7);
memcpy(buf+10, " ", 6);
memcpy(buf+16, my_file, strlen(my_file));
if (write(fd, buf, strlen(buf)) == -1) {
perror("write");
exit(1);
}
printf("Content written to file %s by child process: %s\n", my_file, buf);
sem_post(sem_mutex);
sem_post(sem_read);
}
} else {
// parent process
int i;
for (i = 0; i < 10; i++) {
sem_wait(sem_read);
sem_wait(sem_mutex);
sprintf(buf, "%sPROC2", argv[0]+7);
memcpy(buf+10, " ", 6);
memcpy(buf+16, my_file, strlen(my_file));
if (write(fd, buf, strlen(buf)) == -1) {
perror("write");
exit(1);
}
printf("Content written to file %s by parent process: %s\n", my_file, buf);
sem_post(sem_mutex);
sem_post(sem_write);
}
if (waitpid(pid, NULL, 0) == -1) {
perror("waitpid");
exit(1);
}
}
if (munmap(buf, 40) == -1) {
perror("munmap");
exit(1);
}
if (close(fd) == -1) {
perror("close");
exit(1);
}
if (sem_close(sem_write) == -1 || sem_close(sem_read) == -1 || sem_close(sem_mutex) == -1) {
perror("sem_close");
exit(1);
}
if (sem_unlink("write") == -1 || sem_unlink("read") == -1 || sem_unlink("mutex") == -1) {
perror("sem_unlink");
exit(1);
}
free(my_file);
return 0;
}
```
注意到以上程序需要在 Linux 系统上运行,且需要安装 GCC 编译器。如果你不确定自己的操作系统和环境,可以先询问一下。
改造上面的程序,使用semaphore,并利用该程序生成2个进程,这两个进程写同一个文件,要求:a.互斥写,即只有一个进程写完后,才能让另一个进程写; b. 一个进程写入内容:“自己学号的后3位PROC1 MYFILE1”;另一个进程写入内容:“自己学号的后3位PROC2 MYFILE2”
以下是改造后的程序,使用了信号量来实现进程间的互斥:
```c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <semaphore.h>
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
int fd;
char buffer[BUFFER_SIZE];
size_t bytes;
if (argc != 3) {
fprintf(stderr, "Usage: %s <filename> <process_id>\n", argv[0]);
exit(EXIT_FAILURE);
}
// 创建信号量
sem_t *sem = sem_open("/my_sem", O_CREAT, 0644, 1);
if (sem == SEM_FAILED) {
perror("sem_open");
exit(EXIT_FAILURE);
}
// 打开文件
fd = open(argv[1], O_RDWR);
if (fd == -1) {
perror("open");
exit(EXIT_FAILURE);
}
// 获取信号量
if (sem_wait(sem) == -1) {
perror("sem_wait");
exit(EXIT_FAILURE);
}
// 写入文件
char *content = malloc(BUFFER_SIZE);
sprintf(content, "%sPROC%s MYFILE%s\n", &argv[2][strlen(argv[2])-3], &argv[2][strlen(argv[2])-1], &argv[2][strlen(argv[2])-1]);
bytes = write(fd, content, strlen(content));
if (bytes == -1) {
perror("write");
exit(EXIT_FAILURE);
}
printf("Process %s write %zu bytes: %s\n", argv[2], bytes, content);
free(content);
// 释放信号量
if (sem_post(sem) == -1) {
perror("sem_post");
exit(EXIT_FAILURE);
}
// 关闭文件
if (close(fd) == -1) {
perror("close");
exit(EXIT_FAILURE);
}
return 0;
}
```
该程序接收两个参数:文件名和进程ID。进程ID为1表示第一个进程,为2表示第二个进程。
程序使用了 `sem_open` 函数创建了一个名为 `/my_sem` 的信号量,并初始化为1。在进程写文件时,先使用 `sem_wait` 函数获取信号量,然后进行文件写入操作,最后使用 `sem_post` 函数释放信号量。
在写入文件时,程序会根据进程ID生成相应的字符串,写入到文件中。其中,后3位为学号的后3位,PROC1 表示第一个进程,PROC2 表示第二个进程,MYFILE1 和 MYFILE2 分别表示第一个进程写入的文件名和第二个进程写入的文件名。
请注意,该程序中使用的信号量只能在同一台计算机上的进程间进行互斥,如果要在不同计算机上的进程间进行互斥,请使用其他的进程间通信方式,如管道、网络套接字等。