0

私はCが初めてで、ポインターを理解しようとしています。

このプログラムは -i で動作しますが、数行後に segfaults が発生し、すぐに -f segfaults が発生します。

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

void search_and_print ( char pattern[], FILE* search_file );

int main ( int argc, char *argv[] ) {
        const char TOO_MANY_VARIABLES[] = "Too many arguments from the command line!";
        const char NOT_ENOUGH_VARIABLES[] = "\nUSAGE: a.out [-i] [-f filename] (Search Pattern)\n";

        if (argc < 2) { printf(NOT_ENOUGH_VARIABLES); return(1);}
        // If input
        if (strcmp(argv[1],"-i") == 0) {
                char *pattern = argv[2];
                search_and_print(pattern, stdin);
        }


        // If file
        if (strcmp(argv[1],"-f") == 0) {
                char *pattern = argv[3];
                // Check if file exists
                // Open file
                FILE *file = fopen( argv[2], "r" );
                search_and_print(pattern, file);
                fclose( file );
        }

}

void search_and_print ( char pattern[], FILE* search_file ) {
        // Read through file
        const int MAX_CHARACTERS_PER_LINE = 1000;
        char* line[MAX_CHARACTERS_PER_LINE];
        while  ( fgets(*line, MAX_CHARACTERS_PER_LINE, search_file) != NULL )
                if  ( strstr(*line, pattern) != NULL )
                    printf(*line);
}
4

3 に答える 3

2

ここにはかなりの数のバグがあります。

char* line[MAX_CHARACTERS_PER_LINE];

文字ではなく、1000 個のポインターの配列を定義します。fgets(*line, ...は、初期化されていない最初のポインタを にfgets渡します。これにより、おそらくセグビオが発生します。

printf(*line);

printf の最初の引数はフォーマットです。ユーザー入力をフォーマットとして渡さないでください。プログラムに巨大なセキュリティ ホールが開くためです

fputs(line)またはprintf("%s", line)(行の宣言を修正したら)を使用する必要があります。

int main

値を返さない (エラーの場合を除く) ... 未定義の動作が発生します。

FILE *file = fopen( argv[2], "r" );

これが成功するかどうかを確認する必要があります。ファイルを開くことができない場合 (たとえば、ファイルが存在しない場合)、そのファイルを fgets に渡すと、未定義の動作が発生します。

if (argc < 2) { printf(NOT_ENOUGH_VARIABLES); return(1);}

このテストは -f ケースには十分ではありません。

于 2012-09-25T02:15:05.017 に答える
0

今後の参考のために、動作するように見える提案された変更を含むコードを次に示します。助けてくれてありがとう!

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

void search_and_print ( char pattern[], FILE* search_file );
int usage(const char* err);

const char USAGE[] =
                "\nUSAGE: a.out [-i] [-f filename] (Search Pattern)";

int main ( int argc, char *argv[] ) {
        const char TOO_MANY_VARIABLES[] = "Too many arguments from the command line!";


        if (argc < 2) return usage("Not enough options");
        if (argc > 4) return usage("Too many arguments from the command line!");

        // If input
        if (strcmp(argv[1],"-i") == 0) {
                if (argc > 2) {
                        char *pattern = argv[2];
                        search_and_print(pattern, stdin);
                }
                else {
                        printf("Need a pattern to search by!");
                        return 1;
                }
        }

        // If file
        if (strcmp(argv[1],"-f") == 0) {
                if (argc > 3)   {
                        char *pattern = argv[3];
                        // Open file
                        FILE *file = fopen( argv[2], "r" );
                        // Check if file exists
                        if ( file != NULL) {
                                search_and_print(pattern, file);
                                fclose( file );
                        } else {
                                printf("File not found!");
                                return 1;
                        }
                } else {
                        printf("Need a pattern to search by!");
                        return 1;
                }
        }
        return 0;
}

int usage(const char* err) {
        fprintf(stderr, "%s\n%s\n", err, USAGE);
        return 1;
}

void search_and_print ( char pattern[], FILE* search_file ) {
        const int MAX_CHARACTERS_PER_LINE = 1000;
        char line[MAX_CHARACTERS_PER_LINE];
        // Read through file
        while  ( fgets(line, MAX_CHARACTERS_PER_LINE, search_file) != NULL )
                if  ( strstr(line, pattern) != NULL )
                    printf("%s", line);
}
于 2012-09-25T02:29:18.240 に答える
0

あなたは必要ありません

char* line[MAX_CHARACTERS_PER_LINE]; 

これは配列へのポインターであり (ファイルまたは入力を 1 行ずつ格納する場合に役立つ可能性があります)、最初に割り当てていません。したがって、セグフォルトは非常に明白です。

search_and_print を次のように変更します。

void search_and_print ( char pattern[], FILE* search_file ) {
        // Read through file
        const int MAX_CHARACTERS_PER_LINE = 1000;
        char line[MAX_CHARACTERS_PER_LINE];
        while  ( fgets(line, MAX_CHARACTERS_PER_LINE, search_file) != NULL )
                if  ( strstr(line, pattern) != NULL )
                    printf("%s\n", line);
}

Jim Balter の非常に優れたアドバイスに加えて、パラメーターの解析にgetoptを使用することをお勧めします。

于 2012-09-25T02:29:22.663 に答える