

以下のコードは入力された年月日を表示するprintdate関数と、入力された年月日の次の日を返すtomorrow関数です。このコードを実行すると間違った値（それもアドレスのような値）を返してしまいます。おそらく、構造体の使い方が間違っていると思うのですがつまってしまいました。コードを正常に動かせるよう指摘お願いします。

[code]

    #include <stdio.h>
    
    struct date{
      int year, month, day;
    };
    
    void printdate(struct date p){
      scanf("Today is %d %d %d", &(p.year), &(p.month), &(p.day));
      if(p.month<10){
        if(p.day<10){
          printf("Today is %d/%02d/%02d\n", p.year, p.month, p.day);
        }else{
          printf("Today is %d/%02d/%d\n", p.year, p.month, p.day);
        }
      }else if(p.day<10){
         printf("Today is %d/%d/%02d\n", p.year, p.month, p.day);
      }else{
        printf("Today is %d/%d/%d\n", p.year, p.month, p.day);
      }
    }
    
    struct date tomorrow(struct date p){
      if(p.month==1 || 3 || 5 || 7 || 8 || 10 || 12){
        if(p.day==31){
          p.month+=1;
          p.day=1;
        }else{
          p.day+=1;
        }
      }else if(p.month == 2){
        if((p.year%4==0 && p.day==29) || (p.year%4!=0 && p.day==28)){
          p.month+=1;
          p.day=1;
        }else{
          p.day+=1;
        }
      }else{
        if(p.day==30){
          p.month+=1;
          p.day=1;
        }else{
          p.day+=1;
        }
      }
      return p;
    }
    
    int main(){
      struct date p;
      printdate(p);
      tomorrow(p);
      printf("Tomorrow is %04d/%02d/%02d\n", p.year, p.month, p.day); 
      return 0;
    }
    
[/code]


CC BY-SA 4.0
2019-10-25T06:51:09.033
59961
2020-01-20T11:11:11.320
2019-10-25T07:23:00.000
3060
35091
question
c
C言語の構造体の使い方について　コードの指摘お願いします


>
[code]

>     struct date p;
>     printdate(p);
>  
[/code]

C言語の場合、ローカル変数はデタラメの値が入ります  
何も代入してないので、そのデタラメの値が出力されますね

それに続く、

>
[code]

>     tomorrow(p);
>     printf("Tomorrow is %04d/%02d/%02d\n", p.year, p.month, p.day);
>  
[/code]

ですが、これではpの値は変更されません  
関数の引数は、値がコピーされて関数に渡されますんで、関数の中でいくら値を変更したところで、呼び出しもとには反映されません。  
結局、このprintf文でも、pの中身はデタラメのまま出力されますね


CC BY-SA 4.0
2019-10-25T15:38:26.537
59977
2020-01-20T11:11:11.320
2020-01-20T11:11:11.320
32986
27481
59961
answer


別の質問 [以下のコードを短く実行できる形にしてください](https://ja.stackoverflow.com/q/59971/26370)
でもそうですが、コンパイラは何を使っていますか？  
質問に記述したソースをビルドした時に、警告やエラーのメッセージが提示されるはずです、VS2019では以下のように出てきます。(内容は見易くするために省略・編集しています)

[code]

    重大度  コード  説明                                                 行
    警告    C6031   戻り値が無視されました: 'scanf'                       8
    警告    C6236   (<式> || <0 でない定数>) は常に 0 でない定数です。   26
    警告    C6001   初期化されていないメモリ 'p' を使用しています。      58
    エラー  C4996   'scanf': This function or variable may be unsafe.     8
                     Consider using scanf_s instead.
                     To disable deprecation, use _CRT_SECURE_NO_WARNINGS.
                     See online help for details.
    
[/code]

質問の前に、これらの内容を調べて対処するだけでも、コメントや回答に付いたような指摘を減らせます。  
ただし、対処の方法や順番を考慮しないと、対処が完全では無いのに先に進めてしまう場合があるので注意してください。

例えば`エラー C4996`の対策に(本当は良くないですが)`#pragma warning(disable :
4996)`を入れると以下のエラーに変わります。  
**これは @Uncle-Kei さんのコメントや @わわい さんの回答と同様の内容です**

[code]

    重大度  コード  説明                                                 行
    エラー  C4700   初期化されていないローカル変数 'p' が使用されます    58
    
[/code]

そのために、以下のように`p`を初期化すると、ビルドは出来てしまいます。

[code]

    struct date p = {};
    
[/code]

以下の警告は残ったままですが、先に進めてデバッグ実行は出来てしまうので、対処が不完全になることもあり得ます。  
**2つ目の`警告 C6236`は @metropolis さんの3つ目のコメントと同じ内容です**

[code]

    重大度  コード  説明                                                 行
    警告    C6031   戻り値が無視されました: 'scanf'                       8
    警告    C6236   (<式> || <0 でない定数>) は常に 0 でない定数です。   26
    
[/code]

ここまで来て、コンパイラの警告やエラーに引っかからない問題も残っています。  
**@metropolis さんの1つ目＆2つ目のコメント内容ですね**

ということで、主要な問題は「構造体の使い方」ではなく、以下の様なものになります。

  * 変数は初期化されているか
  * 関数へのパラメータの渡し方、関数の結果の受け取り方、は正しいか
  * データの入力・発生は何時か、それらは何処の処理で使えるか(伝わっているか)の把握
  * プログラムのそれぞれの処理は意図した結果・効果を得られているか

**@int32_t さんのコメント内容なども念頭に、プログラムをチェックしてみてください**

* * *

**追記**  
質問が課題/自習どちらか不明ですし余計なお世話でもありますが、蛇足かつ後出しジャンケンみたいな感じで言えば、日付時刻に関する構造体はC言語に標準のものが存在します。

[C言語関数辞典 - tm構造体](http://www.c-tipsref.com/reference/time/tm.html)  
[C言語関数辞典 - time.h](http://www.c-tipsref.com/reference/time.html)

ちなみに、ある日付を指定すると次の日を返す関数は標準では定義されていません。  
しかし、長い間使われている言語なので、そうしたプログラム例はいっぱいあります。

[日付時刻に関する処理](http://home.a00.itscom.net/hatada/c-tips/datetime.html)

課題として1から作りなさいというならまだしも、自習ならこれらの標準をどう使うかという方向で考えた方が効率が良いように思われます。

他の言語には、C言語よりも豊富な機能が標準で付いていたりするので、余裕があればそうしたものを眺めつつ、他言語との差を埋めるような自分のライブラリを考えてみるのも良いかもしれません。  
[C++ 日付と時間のユーティリティ](https://ja.cppreference.com/w/cpp/chrono)  
[.NET DateTime Struct](https://docs.microsoft.com/ja-
jp/dotnet/api/system.datetime?view=netframework-4.8)  
[Python datetime ---
基本的な日付型および時間型](https://docs.python.org/ja/3/library/datetime.html)  
[Java SE 8 Date and
Time](https://www.oracle.com/technetwork/jp/articles/java/jf14-date-
time-2125367-ja.html)


CC BY-SA 4.0
2019-10-26T01:00:58.750
59982
2019-10-26T16:54:51.563
2019-10-26T16:54:51.563
26370
26370
59961
answer


printdate(p);ではポインターではなく、値を渡しますので、もし、printdateの中で、読み込んだ値をtomorrowに渡したいのであれば、ポインターを渡す必要があります。printdate(&p);となります。


CC BY-SA 4.0
2019-12-13T08:09:01.117
61406
2019-12-13T08:09:01.117
24490
59961
answer