72946


提示コードのコメント部の内部のコードですがなぜfscanf_s()関数の戻り値が **EOF** なのになぜ **EOF** が返ってこないのでしょうか？
**公式リファレンスを見ましたがおかしいです** 。

マイクロソフト公式リファレンス: <https://docs.microsoft.com/ja-jp/cpp/c-runtime-
library/reference/fscanf-s-fscanf-s-l-fwscanf-s-fwscanf-s-l?view=msvc-160>

[code]

    #include "../Header/Model.hpp"
    
    //数学ライブラリ
    #include "../Library/glm/ext.hpp"
    
    //標準ヘッダー
    #include "stdio.h"
    #include <string>
    
    
    //コンストラクタ
    Model::Model(const char* file)
    {
        FILE* fp = nullptr;
        fopen_s(&fp,file,"r");  //読み込み専用でファイルを開く
    
        if (fp != NULL)
        {
            while (true)
            {
                // #############################################################################
                printf("あああ\n");
                char lineHeader[128] = { 0 };
                int res = fscanf_s(fp,"%s",lineHeader);
                printf("%d\n",&res);
                if (res == EOF)
                {
                    break;
                }
                // ##############################################################################
                else
                {   
                    //ファイル抽出
    
    
                    //頂点を抽出
                    if (strcmp(lineHeader, "v") == 0)
                    {
                        glm::vec3 vertex;
                        fscanf_s(fp, "%f %f %f", &vertex.x, &vertex.y, &vertex.z);
                        out_vertices.push_back(vertex);
                    }
    
                    //UV座標を抽出
                    else if (strcmp(lineHeader, "vt") == 0)
                    {
                        glm::vec2 uv = glm::vec2(0,0);
                        fscanf_s(fp,"%f %fn",uv.x,uv.y);
                        out_uvs.push_back(uv);
                    }
    
                    //法線を抽出
                    else if (strcmp(lineHeader, "vn") == 0)
                    {
                        glm::vec3 normalize = glm::vec3(0, 0, 0 );
                        fscanf_s(fp, "%f %f %fn",normalize.x, normalize.y, normalize.z);
                        out_normals.push_back(normalize);
                    }
    
                    //面法線
                    else if (strcmp(lineHeader, "f") == 0)
                    {
                        std::string vertex1, vertex2, vertex3;
                        unsigned int vertexIndex[3], uvIndex[3],normalIndex[3];
    
                        int matches = fscanf_s(fp, "%d/%d/%d %d/%d/%d %d/%d/%dn",
                            & vertexIndex[0], &vertexIndex[1], &vertexIndex[2],
                            &uvIndex[0], &uvIndex[1], &uvIndex[2],
                            &normalIndex[0], &normalIndex[1], &normalIndex[2]);
    
                            if (matches != 9)
                            {
                                printf("エラー\n");    
                            }
    
                        out_vertexIndices.push_back(vertexIndex[0]);
                        vertexIndices.push_back(vertexIndex[1]);
                        vertexIndices.push_back(vertexIndex[2]);
                        uvIndices.push_back(uvIndex[0]);
                        uvIndices.push_back(uvIndex[1]);
                        uvIndices.push_back(uvIndex[2]);
                        normalIndices.push_back(normalIndex[0]);
                        normalIndices.push_back(normalIndex[1]);
                        normalIndices.push_back(normalIndex[2]);
                    }
                }
            }
    
    
            for (unsigned int i = 0; i < out_vertexIndices.size(); i++)
            {
                unsigned int vertexIndex = vertexIndices[i];
                glm::vec3 vertex = out_vertices[vertexIndex - 1];
                out_vertices.push_back(vertex);
            }
    
            printf(".objファイル読み込み完了!\n");
        }
        else
        {
            printf("ファイルが読めませんでした。\n");
        }
    }
    
    
    
    //デストラクタ
    Model::~Model()
    {
    
    }
    
[/code]


CC BY-SA 4.0
2020-12-28T09:16:38.583
72945
2020-12-29T01:22:54.810
2020-12-28T09:39:19.890
3060
question
c++
fscanf_s() 関数でEOFを認識できない理由と対処方法が知りたい。


>
[code]

>     int res = fscanf_s(fp,"%s",lineHeader);
>  
[/code]

この部分ですが引数が誤っています。引用されたドキュメントにも

> より安全な関数 ( _s サフィックスを持つ) とその他のバージョンの主な違いは、セキュリティが強化された関数では、各 c、 c、 s、 s、および [
> 型フィールドの文字数を、変数の直後の引数として渡す必要があることです。

と説明されているように通常の`fscanf`と異なりセキュリティ強化された`fscanf_s`では`lineHeader`のサイズ情報が必要です。正しくは

[code]

    int res = fscanf_s(fp, "%s", lineHeader, _countof(lineHeader));
    
[/code]

です。コンパイラも警告してくれるはずですが、無視しているのでしょうか？

警告メッセージ：

[code]

    warning C4473: 'fscanf_s' : not enough arguments passed for format string
    message : placeholders and their parameters expect 2 variadic arguments, but 1 were provided
    message : the missing variadic argument 2 is required by format string '%s'
    message : this argument is used as a buffer size
    
[/code]

* * *

>
[code]

>     printf("%d\n",&res);
>  
[/code]

このコードは変数`res`のアドレスを出力するだけで何の意味もありません。正しくは

[code]

    printf("%d\n", res);
    
[/code]

のはずです。ここもコンパイラが警告してくれるはずですが、無視しているのでしょうか？

警告メッセージ：

[code]

    warning C4477: 'printf' : format string '%d' requires an argument of type 'int', but variadic argument 1 has type 'int *'
    
[/code]

* * *

>
[code]

>     fscanf_s(fp,"%f %fn",uv.x,uv.y);
>  
[/code]

これでは読み込めません。コンパイラも警告してくれるはずですが、無視しているのでしょうか？

警告メッセージ：

[code]

    warning C4477: 'fscanf_s' : format string '%f' requires an argument of type 'float *', but variadic argument 1 has type 'double'
    warning C4477: 'fscanf_s' : format string '%f' requires an argument of type 'float *', but variadic argument 2 has type 'double'
    
[/code]

* * *

他にも多数の問題を抱えていると思われます。 **無理やり実行する前に、コンパイラの警告に真摯に向き合うことをお勧めします。**

補足：

`printf`系や`scanf`系などの可変引数関数の場合、コンパイラーは与えられた引数を忠実に受け渡しします。しかしそれは正常動作することを意味するわけではありません。（可変引数に限らず）関数仕様に則り、正しい引数を与えるのはプログラマの責務です。


CC BY-SA 4.0
2020-12-28T09:37:12.263
72946
2020-12-29T01:22:54.810
2020-12-29T01:22:54.810
4236
4236
72945
answer