0

C を学習しながら、Makefile の変数に簡単な変更を加える練習用プログラムを作成しています。このプログラムを実行するたびに segfault が発生しますが、その理由がわかりません。「r+」fopen モードまたは fseek() の使用に関係があると思われます。コードは次のとおりです。

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

void rewind(FILE *f)
{   
    long start = 0;
    fseek(f, start, SEEK_SET);
}


int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("arguments too many or too few. use: setfile <filename> (minus .c extension)\n");
        exit(1);
    }
    FILE *mfile = fopen("Makefile", "r+"); // note to self: r+ is for a file that already exists
    FILE *old_mfile = fopen("OLD.Makefile", "r+");  // w+ erases the file and starts in read-write mode with a fresh one
    char line[200];
    char *fn_ptr;
    char *name = argv[1];

    while(fgets(line, 199, mfile)) // first create the backup
    {   
        fputs(line , old_mfile); // before changing the line, write it to the backup
    }
    rewind(mfile); // reset the files to position 0
    rewind(old_mfile);
    puts("Makefile backed-up as 'OLD.Makefile'");

    while(fgets(line, 199, old_mfile)) // now lets loop again and rewrite with the new FNAME
    {
        if((fn_ptr = (strstr(line, "FNAME= "))))
        {
            fn_ptr += strlen("FNAME= ");
            int i;
            for(i = 0; i < strlen(name); i++)
            {
                *(fn_ptr+i) = *(name+i);
            }
            *(fn_ptr+i) = '\0';

        }
        // printf("%s", line); // for debugging
        fputs(line , mfile);
    }
    printf("FNAME is now: '%s'\n", argv[1]);
    fclose(mfile);
    fclose(old_mfile);
    return 0;
}
4

2 に答える 2

3

この行をもう一度確認してください。

FILE *old_mfile = fopen("OLD.Makefile", "r+");  // w+ erases the file and starts in read-write mode with a fresh one

コメントには正しいモードがありますが、fopen通話にはありません。

モードを変更する以外に、セグメンテーション違反を起こさないようにするにはどうすればよいですか?常に戻り値を確認してください!失敗した場合fopenは戻りNULLます。

于 2012-08-31T05:49:14.440 に答える
1

ここに作業バージョンがあります。ここには注意すべき微妙な点がいくつかあるので、変更を切り替えて 1 つずつ調べるようにしておきます。呼び出された関数の man ページは、注意深く読めばおそらく十分です。

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

void rewind(FILE *f)
{
    long start = 0;
    fseek(f, start, SEEK_SET);
}


int main(int argc, char *argv[])
{
    if(argc != 2)
    {
        printf("arguments too many or too few. use: setfile <filename> (minus .c extension)\n");
        exit(1);
    }
    FILE *mfile = fopen("Makefile", "r+"); // note to self: r+ is for a file that already exists
    FILE *old_mfile = fopen("OLD.Makefile", "w+");  // w+ erases the file and starts in read-write mode with a fresh one
    char line[200];
    char *fn_ptr;
    char *name = argv[1];

    while(fgets(line, 199, mfile)) // first create the backup
    {
        fputs(line , old_mfile); // before changing the line, write it to the backup
        memset(line,0x00,200);
    }
    rewind(mfile); // reset the files to position 0
    rewind(old_mfile);
    memset(line,0x00,200);
    puts("Makefile backed-up as 'OLD.Makefile'");

    fclose(mfile);
    mfile = fopen("Makefile", "w");
    while(fgets(line, 199, old_mfile)) // now lets loop again and rewrite with the new FNAME
    {
        if((fn_ptr = strstr(line, "FNAME=")) != NULL)
        {
            fn_ptr += strlen("FNAME=");
            int i;
            for(i = 0; i < strlen(name); i++)
            {
                *(fn_ptr+i) = *(name+i);
            }
            *(fn_ptr+i) = '\0';

        }
        // printf("%s", line); // for debugging
        fputs(line , mfile);
        fputs("\n" , mfile);
        memset(line,0x00,200);
    }
    printf("FNAME is now: '%s'\n", argv[1]);
    fclose(mfile);
    fclose(old_mfile);
    return 0;
}
于 2012-08-31T09:52:35.320 に答える