1

私はこのコードを何時間も機能させようとしてきました! 私がする必要があるのは、ファイルを開いて、それが本物で読み取り可能かどうかを確認することだけです。私はCに慣れていないので、何か愚かなものが欠けていると確信しています。コードは次のとおりです (簡略化されていますが、コピーされています)。

#include <stdio.h>

main() {
    char fpath[200];
    char file = "/test/file.this";
    sprintf(fpath,"~cs4352/projects/proj0%s",file);

    FILE *fp = fopen(fpath,"r");
    if(fp==NULL) {
        printf("There is no file on the server");
        exit(1);
    }
    fclose(fp);
    //do more stuff
}

また、読み取り権限のある実際のファイルをパスが正しく指定していることも確認しました。他のアイデアはありますか?

編集1: fpathが「〜cs4352/projects/proj0/test/file.this」になることは知っています

編集 2:絶対ファイル パスを使用してみました。どちらの場合も、ls を使用してパスが適切に構築されていることを確認できます。

編集 3: 2つありerrnoます...現在、Google でそれが何を意味するのかを追跡しようとしています。

編集 4: わかりました、errno2 の「そのようなファイルまたはディレクトリはありません」です。fopen の参照パスが「/home/courses1/cs4352/projects/proj0/index.html」であり、存在することを確認し、それに対する読み取り権がある場合に、これを取得しています。以下にリストされている C コードに関しては、セマンティック/初心者向けのエラーがいくつかある可能性がありますが、gcc はコンパイル時に警告を表示しません。コードはerrno、2 を吐き続けていることを除いて、本来のとおりに機能します。つまり、すべての文字列/文字配列が正しく機能していることはわかっていますが、問題になる可能性があるのはfopen()呼び出しだけです。

解決策: わかりました、access() プロシージャが私を最も助けてくれました (そして、それを行うためのよりエレガントな方法は言うまでもなく、コードが少ないため、私がまだ使用しているものです)。この問題は実際には、私が皆さんに説明しなかったことに起因していました (なぜなら、私は access() を使用するまでその問題に気付かなかったからです)。ファイルを取得するために、strtok() を使用して文字列を分割し、" \n" でのみ分割していましたが、これは UNIX システムであるため、"\r" も追加する必要がありました。それを修正すると、すべてがうまくいき、 fopen() 関数も同様に機能すると確信していますが、テストしていません。

皆様の有益な提案に感謝します。特に、この素​​晴らしい解決策を見つけてくれた Paul Beckingham に感謝します。

乾杯!

4

7 に答える 7

6
  1. 「〜」はシェルによって展開され、fopenによって展開されません。
  2. ファイルの存在と読みやすさをテストするには、POSIX.1の「アクセス」機能の使用を検討してください。
#include <unistd.h>

if(access( "/ path / to / file"、F_OK | R_OK)== 0)
{{
  //ファイルが存在し、読み取り可能
}
于 2009-02-07T04:24:22.053 に答える
2

他の人が同等のものを作成した可能性があります (たとえば、すべての最新のシェル) が、~ または ~user 表記でファイル名を展開するコードを次に示します。

#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif

#include <assert.h>
#include <limits.h>
#include <pwd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

char *relfname(const char *name, char *buffer, size_t bufsiz)
{
    assert(name != 0 && buffer != 0 && bufsiz != 0);
    if (name[0] != '~')
        strncpy(buffer, name, bufsiz);
    else
    {
        const char *copy;
        struct passwd *usr = 0;
        if (name[1] == '/' || name[1] == '\0')
        {
            usr = getpwuid(getuid());
            copy = &name[1];
        }
        else
        {
            char username[PATH_MAX];
            copy = strchr(name, '/');
            if (copy == 0)
                copy = name + strlen(name);
            strncpy(username, &name[1], copy - &name[1]);
            username[copy - &name[1]] = '\0';
            usr = getpwnam(username);
        }
        if (usr == 0)
            return(0);
        snprintf(buffer, bufsiz, "%s%s", usr->pw_dir, copy);
    }
    buffer[bufsiz-1] = '\0';
    return buffer;
}

#ifdef TEST
static struct { const char *name; int result; } files[] =
{
    { "/etc/passwd", 1 },
    { "~/.profile", 1 },
    { "~root/.profile", 1 },
    { "~nonexistent/.profile", 0 },
};

#define DIM(x)  (sizeof(x)/sizeof(*(x)))

int main(void)
{
    int i;
    int fail = 0;
    for (i = 0; i < DIM(files); i++)
    {
        char buffer[PATH_MAX];
        char *name = relfname(files[i].name, buffer, sizeof(buffer));
        if (name == 0 && files[i].result != 0)
        {
            fail++;
            printf("!! FAIL !! %s\n", files[i].name);
        }
        else if (name != 0 && files[i].result == 0)
        {
            fail++;
            printf("!! FAIL !! %s --> %s (unexpectedly)\n", files[i].name, name);
        }
        else if (name == 0)
            printf("** PASS ** %s (no match)\n", files[i].name);
        else
            printf("** PASS ** %s -> %s\n", files[i].name, name);
    }
    return((fail == 0) ? EXIT_SUCCESS : EXIT_FAILURE);
}

#endif
于 2009-02-07T07:05:51.760 に答える
0

総括する:

  1. char * file = / test /file.this";を使用します。
  2. fopen()が〜でシェル置換を行うことを期待しないでください。そうしないからです。フルパスまたは相対パスを使用して、現在のディレクトリが適切であることを確認してください。
  3. エラー2は、ファイルが見つからなかったことを意味します。このリストの項目#2のため、見つかりませんでした。

追加のクレジットとして、このようなsprintf()を使用して、スタックに割り当てられたバッファーに書き込むことは危険な習慣です。少なくとも、snprintf()を検索して使用します。

ここで他の誰かが述べたように、access()を使用することは、ここで試みていることを実行するためのより良い方法です。

于 2009-02-07T04:35:08.803 に答える
0

char file = "/test/file.this";

あなたはおそらくしたいです

char *file = "/test/file.this";

于 2009-02-07T03:45:48.980 に答える