鱼C论坛

 找回密码
 立即注册
查看: 2174|回复: 9

[已解决]C语言新手求助:fopen()没法创建文件的问题(大佬勿喷谢谢)

[复制链接]
发表于 2023-1-15 10:35:21 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
本帖最后由 额外减小 于 2023-1-15 11:00 编辑

如题
我想用fopen函数创建一个.c的文件。
但是按照这个代码运行以后却没有在当前文件夹中创建出相应的文件。
请问这是为什么呢
注.程序可以运行,返回值正常
#include <stdio.h>
#include <conio.h>
#include <string.h>
#include <windows.h>

#define TITLEMAXLEN 128
#define TEXTMAXLEN 65536

int main()
{
        char ch=' ',title[TITLEMAXLEN]={'\0'},*ptr=title;
        printf("输入文件名:");
        do
        {
                ch=getch();
                *ptr=ch;
                ptr++;
                printf("%c",ch);
        }
        while(ch!=13); 
        /*输入一行文件名*/
        system("cls");
        
        FILE *fp=fopen(strcat(title,".c"),"w");
        /*以只写打开文件*/
        if(fp=NULL)
        {
                printf("error\n");
        }
        else
        {
                fprintf(fp,"#include <stdio.h>\n\nint main()\n{\n    printf("hello?\\n");\n    return 0;\n}");
        }
        fclose(fp);
        return 0;
}
7.png
这个是32行原来的版本。这个他给我漏掉了,不知道为什么

线索:当我把第24行fopen()的第一个参数改为一个字符串常量的时候,就又可以创建文件了,但fprintf()返回的是-1
最佳答案
2023-1-15 11:23:23
sh-5.1$ ls
main.c
sh-5.1$ cat main.c
#if 0
#include <stdio.h>
#include <string.h>
//#include <conio.h>
//#include <windows.h>
// 上面那两个用不了

#define TITLEMAXLEN 128
//#define TEXTMAXLEN 65536

int main(void) {
    //char ch = ' ', title[TITLEMAXLEN] = {'\0'}, *ptr = title;     // 这样效率不高,因为要全部设置成0,可以的话尽量自己设置一个0
    char title[TITLEMAXLEN], *ptr = title;
    printf("输入文件名:");
    while(1) {
        char ch = getchar();
        if(ch == '\n' || ch == EOF) break;
        *ptr++ = ch;
    }
    *ptr = '\0';
    /*
    do {
        ch = getch();
        *ptr = ch;
        ptr++;
        printf("%c", ch);
    //} while(ch != 13);      // 13 是什么?换行?应该是换行吧,不去查ascii表了,看这个代码的语义,这里应该是换行
    } while(ch != '\n');        // 直接写 '\n' 不就好了,让编译器去查ascii表
                                // 这是在ch是char类型的时候,还知道用13这个数字去查ascii表,如果是其他类型而且变量名还比较神奇的话,这个数字也就没办法知道是什么了
                                // 这就是传说中的神奇数字
    */
    /*输入一行文件名*/
    //system("cls");    // 用不了的说

#if 0
    FILE *fp = fopen(strcat(title, ".c"), "w");
    /*以只写打开文件*/
    //if(fp = NULL) {   // 这是什么操作?请你告诉我
    if(fp == NULL) {
        printf("error\n");
    } else {
                fprintf(fp,"#include <stdio.h>\n\nint main()\n{\n    printf("hello?\\n");\n    return 0;\n}");
    }
    fclose(fp);
#endif
    FILE *fp = fopen(strcat(title, ".c"), "w");
    if(!fp) return -1;
    fprintf(fp,"#include <stdio.h>\n\nint main(void) {\n    printf("hello world!\\n");\n    return 0;\n}");
    fclose(fp);
    return 0;
}
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char filename[1024];
    printf("输入文件名:");
    fgets(filename, 1024, stdin);
    filename[strlen(filename) - 1] = '\0';      // '\n'
    FILE *fp = fopen(filename, "w");
    if(!fp) return -1;
    fprintf(fp,"#include <stdio.h>\n\nint main(void) {\n    printf("hello world!\\n");\n    return 0;\n}");
    fclose(fp);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ls
main  main.c
sh-5.1$ ./main
输入文件名:test.c
sh-5.1$ ls
main  main.c  test.c
sh-5.1$ cat test.c
#include <stdio.h>

int main(void) {
    printf("hello world!\n");
    return 0;
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

 楼主| 发表于 2023-1-15 10:38:41 | 显示全部楼层
等等,这个输入代码的有毒啊?
他给我把反斜杠漏掉了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-15 11:16:19 From FishC Mobile | 显示全部楼层

回帖奖励 +1 鱼币

这个输入方式看的人心惊肉跳的,有必要这么做吗?会不会有奇怪的字符混进文件名里?
检查所有的返回值,看看是哪个函数失败了,检查错误码( errno )可能会给调查问题提供辅助
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-15 11:22:11 | 显示全部楼层
dolly_yos2 发表于 2023-1-15 11:16
这个输入方式看的人心惊肉跳的,有必要这么做吗?会不会有奇怪的字符混进文件名里?
检查所有的返回值,看 ...

好的
我试试
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-15 11:23:23 | 显示全部楼层    本楼为最佳答案   

回帖奖励 +1 鱼币

sh-5.1$ ls
main.c
sh-5.1$ cat main.c
#if 0
#include <stdio.h>
#include <string.h>
//#include <conio.h>
//#include <windows.h>
// 上面那两个用不了

#define TITLEMAXLEN 128
//#define TEXTMAXLEN 65536

int main(void) {
    //char ch = ' ', title[TITLEMAXLEN] = {'\0'}, *ptr = title;     // 这样效率不高,因为要全部设置成0,可以的话尽量自己设置一个0
    char title[TITLEMAXLEN], *ptr = title;
    printf("输入文件名:");
    while(1) {
        char ch = getchar();
        if(ch == '\n' || ch == EOF) break;
        *ptr++ = ch;
    }
    *ptr = '\0';
    /*
    do {
        ch = getch();
        *ptr = ch;
        ptr++;
        printf("%c", ch);
    //} while(ch != 13);      // 13 是什么?换行?应该是换行吧,不去查ascii表了,看这个代码的语义,这里应该是换行
    } while(ch != '\n');        // 直接写 '\n' 不就好了,让编译器去查ascii表
                                // 这是在ch是char类型的时候,还知道用13这个数字去查ascii表,如果是其他类型而且变量名还比较神奇的话,这个数字也就没办法知道是什么了
                                // 这就是传说中的神奇数字
    */
    /*输入一行文件名*/
    //system("cls");    // 用不了的说

#if 0
    FILE *fp = fopen(strcat(title, ".c"), "w");
    /*以只写打开文件*/
    //if(fp = NULL) {   // 这是什么操作?请你告诉我
    if(fp == NULL) {
        printf("error\n");
    } else {
                fprintf(fp,"#include <stdio.h>\n\nint main()\n{\n    printf("hello?\\n");\n    return 0;\n}");
    }
    fclose(fp);
#endif
    FILE *fp = fopen(strcat(title, ".c"), "w");
    if(!fp) return -1;
    fprintf(fp,"#include <stdio.h>\n\nint main(void) {\n    printf("hello world!\\n");\n    return 0;\n}");
    fclose(fp);
    return 0;
}
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void) {
    char filename[1024];
    printf("输入文件名:");
    fgets(filename, 1024, stdin);
    filename[strlen(filename) - 1] = '\0';      // '\n'
    FILE *fp = fopen(filename, "w");
    if(!fp) return -1;
    fprintf(fp,"#include <stdio.h>\n\nint main(void) {\n    printf("hello world!\\n");\n    return 0;\n}");
    fclose(fp);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ls
main  main.c
sh-5.1$ ./main
输入文件名:test.c
sh-5.1$ ls
main  main.c  test.c
sh-5.1$ cat test.c
#include <stdio.h>

int main(void) {
    printf("hello world!\n");
    return 0;
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-15 12:02:12 | 显示全部楼层

谢谢大佬

是我脑抽了

真是麻烦您了
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-15 17:42:47 | 显示全部楼层
再添加个调用编译器的功能
你可能会问,为什么不用system函数
我想说的是,我就是想再练习一下fork+exec函数,^_^
sh-5.1$ cat main.c
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <linux/limits.h>

void write_code(const char *filename) {
    FILE *fp = fopen(filename, "w");
    if(!fp) return;
    fprintf(fp, "#include <stdio.h>\n\nint main(void) {\n    printf("hello world!\\n");\n    return 0;\n}");
    fclose(fp);
}

int compile(const char *filename) {
    int fd = open("/tmp", O_TMPFILE | O_RDWR, 0755);
    pid_t pid = fork();
    if(!pid) {
        const char *argv[] = {"gcc", "-g", "-Wall", "-o", "/dev/stdout", filename, NULL};
        dup2(fd, STDOUT_FILENO); close(fd);
        exit(execvp(argv[0], (void *)argv));
    }
    waitpid(pid, NULL, 0);
    return fd;
}

void run(int fd) {
    char path[PATH_MAX];
    snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
    int new_fd = open(path, O_RDONLY);      // fexecve 要求 fd 是 O_RDONLY
    dup2(new_fd, fd);
    pid_t pid = fork();
    if(!pid) {
        const char *argv[] = {NULL};
        const char *envp[] = {NULL};
        exit(fexecve(fd, (void *)argv, (void *)envp));
    }
    waitpid(pid, NULL, 0);
}

int main(void) {
    char filename[PATH_MAX];
    printf("输入文件名:");
    fgets(filename, PATH_MAX, stdin);
    filename[strlen(filename) - 1] = '\0';
    write_code(filename);
    int fd = compile(filename);
    run(fd);
    close(fd);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
输入文件名:test.c
hello world!
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2023-1-15 17:48:27 | 显示全部楼层
人造人 发表于 2023-1-15 17:42
再添加个调用编译器的功能
你可能会问,为什么不用system函数
我想说的是,我就是想再练习一下fork+exec ...

这个是只有linux才可以使用的吗?
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-15 17:54:12 | 显示全部楼层
额外减小 发表于 2023-1-15 17:48
这个是只有linux才可以使用的吗?

可以试试dev-cpp能不能用
还可以试试,cygwin
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2023-1-15 18:15:17 | 显示全部楼层
既然gcc生成的是一个临时文件,那么直接把C代码也写到临时文件算了
我感觉这样更好
sh-5.1$ cat main.c
#define _GNU_SOURCE

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/wait.h>
#include <linux/limits.h>

int write_code(const char *code) {
    int fd = open("/tmp", O_TMPFILE | O_RDWR, 0644);
    write(fd, code, strlen(code));
    return fd;
}

void compile(int fd) {
    int o_fd = open("/tmp", O_TMPFILE | O_RDWR, 0755);
    pid_t pid = fork();
    if(!pid) {
        const char *argv[] = {"gcc", "-g", "-Wall", "-x", "c", "-o", "/dev/stdout", "/dev/stdin", NULL};
        dup2(fd, STDIN_FILENO); close(fd);
        dup2(o_fd, STDOUT_FILENO); close(o_fd);
        exit(execvp(argv[0], (void *)argv));
    }
    waitpid(pid, NULL, 0);
    dup2(o_fd, fd); close(o_fd);
}

void run(int fd) {
    char path[PATH_MAX];
    snprintf(path, PATH_MAX, "/proc/self/fd/%d", fd);
    int new_fd = open(path, O_RDONLY);      // fexecve 要求 fd 是 O_RDONLY
    dup2(new_fd, fd);
    pid_t pid = fork();
    if(!pid) {
        //const char *argv[] = {NULL};
        const char *argv[] = {"fexecve", "+", "1234", "5678", "sum", NULL};
        const char *envp[] = {NULL};
        exit(fexecve(fd, (void *)argv, (void *)envp));
    }
    waitpid(pid, NULL, 0);
}

int main(void) {
    char code[] =
        "#include <stdio.h>\n"
        "\n"
        "int main(int argc, char *argv[]) {\n"
        "    for(size_t i = 0; i < argc; ++i) {\n"
        "        puts(argv[i]);\n"
        "    }\n"
        "    return 0;\n"
        "}";
    int fd = write_code(code);
    compile(fd); run(fd); close(fd);
    return 0;
}
sh-5.1$ gcc -g -Wall -o main main.c
sh-5.1$ ./main
fexecve
+
1234
5678
sum
sh-5.1$
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-12-24 08:54

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表