fprintf没有写入文件,尽管fclose()

时间:2015-03-27 06:59:37

标签: c getopt fclose

正如标题所述,我试图用fprintf写入文件,并且我已经在Stack Overflow上搜索了为什么它不会写入文件。我发现它在内存中保存它直到你关闭文件(对吗?),因此使用fclose()。但是,它仍然不适合我。

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


void printHelp()
{
    printf("Usage: fstring [ char ] [ amount ] Optional:[ outfile ]\n"
           "Example: fstring A 100 out.txt\n");
    exit(1);
}

char *f_string(const char *s, int t)
{
    int i; char *dst = malloc(t * strlen(s) + 1);
    for(i = 0; i < t; i++) {
        strcat(dst, s);
    }
    return dst;
}


int main(int argc, char *argv[])
{
    char c; char *file;

    while((c = getopt(argc, argv, "f:")) != -1)
        switch(c) {
        case 'f':
            file = optarg;
            break;
        default:
            printHelp();
            return 1;
        }

    if(argc < 3) {
        printf("You need at least two arguments!\n");
        return 1;
    }

    char *res = f_string(argv[1], atoi(argv[2]));
    FILE *f = fopen(file, "w+");
    if(!f) {
        puts(res);
        exit(0);
    } else {
        fprintf(f, "%s", res);
    }

    fclose(f);
    free(res);
    return 0;
}

我真正不明白的是为什么上面的代码不起作用,但这样做很好:

int main(int argc, char *argv[])
{
    char line[80];

    if(argc != 6) {
        fprintf(stderr, "You need to give 5 arguments!\n");
        return 1;
    }

    FILE *in;
    if(!(in = fopen("spooky.csv", "r"))) {
        fprintf(stderr, "File %s doesn't exist!", in);
        return 1;
    }

    FILE *file1 = fopen(argv[2], "w");
    FILE *file2 = fopen(argv[4], "w");
    FILE *file3 = fopen(argv[5], "w");

    while(fscanf(in, "%79s", line) == 1) {
        if(strstr(line, argv[1]))
            fprintf(file1, "%s\n", line);
        else if (strstr(line, argv[3]))
            fprintf(file2, "%s\n", line);
        else
            fprintf(file3, "%s\n", line);
    }

    fclose(file1);
    fclose(file2);
    fclose(file3);
    return 0;
}

第二个代码可以很好地写入文件。希望有人可以启发我。感谢。

3 个答案:

答案 0 :(得分:2)

根本原因是参数搞砸了。

在调用getopt之后,对参数argv的指向已被操纵,并且不再指向原始参数。因此,当您对argv[1]函数使用argv[2]fstring时,它们不是您传递给main函数的参数。

最简单的修正是在将argv传递给getopt之前将参数存储在临时变量中。

int main(int argc, char *argv[])
{
    char c; char *file;

    char *v1 = argv[1];
    int v2 = atoi(argv[2]);


    while((c = getopt(argc, argv, "f:")) != -1)
        switch(c) {
        case 'f':
            file = optarg;
            break;
        default:
            printHelp();
            return 1;
        }

    if(argc < 3) {
        printf("You need at least two arguments!\n");
        return 1;
    }

    char *res = f_string(v1, v2);
    FILE *f = fopen(file, "w+");
    if(!f) {
        puts(res);
        exit(0);
    } else {
        fprintf(f, "%s", res);
    }

    fclose(f);
    free(res);
    return 0;
}

答案 1 :(得分:2)

来自getopt()的手册页:默认情况下,getopt()会在扫描时置换argv的内容,以便最终所有非选区都在最后

如果您使用选项Abc 10 -f out.txt调用可执行文件,那么在getopt处理argv[1]-fargv[2]out.txtchar *res = f_string(argv[1], atoi(argv[2])); 。所以你必须换行

char *res = f_string(argv[3], atoi(argv[4]));

f_string()

否则,帮助使用是完全错误的,因为根据代码,没有什么是可选的。

必须更正功能char *f_string(const char *s, int t) { int i; char *dst = malloc(t * strlen(s) + 1); dst[0] = '\0'; // <----- for(i = 0; i < t; i++) { strcat(dst, s); } return dst; }

strcat()

如果没有正确的初始化,dst可以从{{1}}的中间开始。

答案 2 :(得分:1)

使用optind找出非可选参数的起始位置。

int main(int argc, char *argv[])
{
    char c; char *file;

    while((c = getopt(argc, argv, "f:")) != -1)
        switch(c) {
        case 'f':
            file = optarg;
            break;
        default:
            printHelp();
            return 1;
        }


    int index = optind;
    if(argc - index + 1 < 3) {
        printf("You need at least two arguments!\n");
        return 1;
    }
    char *res = f_string(argv[index], atoi(argv[index + 1]));
    FILE *f = fopen(file, "w+");
    if(!f) {
        puts(res);
        exit(0);
    } else {
        fprintf(f, "%s", res);
    }

    fclose(f);
    free(res);
    return 0;
}