質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

3回答

841閲覧

リストの値が多く抜き出される

Beginnerman

総合スコア19

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2019/07/04 08:17

編集2019/07/04 08:26

曜日を英語と日本語で表すリストから、その日の曜日を抜き出す際になぜか余計なものまで抜き出されてしまいます。

#include<stdio.h> #include<time.h> int main(int argc, char *rgv[]) { struct tm yed; struct tm *pt; time_t unix_time; char str_time[256]; time( &unix_time ); printf("現在時刻のUNIX時間は%ld秒です. \n\n", unix_time); pt = localtime( &unix_time ); yed = *pt; printf("***構造体tmのメンバを参照***\n"); printf("tm_sec : %d 秒\n", yed.tm_sec); printf("tm_min : %d 分\n", yed.tm_min); printf("tm_hour : %d 時\n", yed.tm_hour); printf("tm_mday : %d 日\n", yed.tm_mday); printf("tm_mon : %d 月(-1)\n", yed.tm_mon); printf(">>>tm_mon補正 : %d 月\n", yed.tm_mon + 1); printf("tm_year : %d 年(-1900)\n", yed.tm_year); printf(">>>tm_year補正 : %d 年\n", yed.tm_year + 1900); printf("tm_wday : %d (曜日コード)\n", yed.tm_wday); char e[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; char j[7][3] = {"日", "月", "火", "水", "木", "金", "土"}; if(yed.tm_wday == 0){ printf(">>>tm_wday英語 : %s\n", e[0]); printf(">>>tm_wday日本語 : %s\n",j[0]); } if(yed.tm_wday == 1){ printf(">>>tm_wday英語 : %s\n", e[1]); printf(">>>tm_wday日本語 : %s\n",j[1]); } if(yed.tm_wday == 2){ printf(">>>tm_wday英語 : %s\n", e[2]); printf(">>>tm_wday日本語 : %s\n",j[2]); } if(yed.tm_wday == 3){ printf(">>>tm_wday英語 : %s\n", e[3]); printf(">>>tm_wday日本語 : %s\n",j[3]); } if(yed.tm_wday == 4){ printf(">>>tm_wday英語 : %s\n", e[4]); printf(">>>tm_wday日本語 : %s\n",j[4]); } if(yed.tm_wday == 5){ printf(">>>tm_wday英語 : %s\n", e[5]); printf(">>>tm_wday日本語 : %s\n",j[5]); } if(yed.tm_wday == 6){ printf(">>>tm_wday英語 : %s\n", e[6]); printf(">>>tm_wday日本語 : %s\n",j[6]); } return 0; }

出力

現在時刻のUNIX時間は1562227997秒です. ***構造体tmのメンバを参照*** tm_sec : 17 秒 tm_min : 13 分 tm_hour : 17 時 tm_mday : 4 日 tm_mon : 6 月(-1) >>>tm_mon補正 : 7 月 tm_year : 119 年(-1900) >>>tm_year補正 : 2019 年 tm_wday : 4 (曜日コード) >>>tm_wday英語 : ThuFriSat >>>tm_wday日本語 : 木金土

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fiveHundred

2019/07/04 08:21

どう考えてもC#のコードではないので、タグをC#以外に変更してください。 (CとC++はある程度互換性がありますが、C#はこれらとは別の言語です)
y_waiwai

2019/07/04 08:22

タグにはC#とありますが、C言語のはなしでしょうか
退会済みユーザー

退会済みユーザー

2019/07/04 08:22

C# のタグが付いてますが C または C++ では? そうであれば訂正願います。
guest

回答3

0

曜日を格納する領域を十分大きくとってください。
char e[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char j[7][3] = {"日", "月", "火", "水", "木", "金", "土"};

char e[7][16] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};
char j[7][16] = {"日", "月", "火", "水", "木", "金", "土"};

にしておけば、十分かと。
漢字は、使用する文字コードによって大きさが異なりますので、UTFでもOKとなるように大きくとっています。

投稿2019/07/04 08:58

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Beginnerman

2019/07/04 09:01

ありがとうございます。なぜ格納領域を狭くすると、余計な要素が取り出されるのでしょうか?
tatsu99

2019/07/04 09:09

char e[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; の場合、終端文字'\0'も含めて、格納する必要があります。 従って、 char e[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; とすれば、OKです。 終端文字がないと、printf("%s",xxx)は、xxxの終端文字の直前まで、印字します。 従って、例えば、Sunを印字すると、Sunの後に'\0'がないので、Monも印字します。 結果的に、たまたま、'\0'があるところまで、印字をします。 char j[7][3] = {"日", "月", "火", "水", "木", "金", "土"}; は、文字コードがEUCかShift-JISなら漢字1文字=2バイトで、終端文字を1文字格納可能なのでOKですが、UTF-8の場合は、漢字1文字が約3バイトです。(max4バイトもありうる) したがって、UTF-8の場合は、期待した結果が得られません。
guest

0

C言語の文字列は '\0' が最後にある=ヌル文字で終端する、というルール・大原則があります。どこかで習いませんでしたか?

例えば、"Sun" という文字列は 'S', 'u', 'n', '\0' と、4文字(4バイト)で構成されています。"Sun" という文字列の長さは3ですが、メモリ上では4バイト必要なのです。ところが、

C

1char e[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

これでは '\0' (ヌル文字)を格納する場所がありません。その結果、e[7][3] とあるメモリには、'\0'を格納できずに、
"SunMonTueWedThuFriSat" のように、全部くっついた状態で文字が並んでいます。そのため "Thu" を表示しようとすれば、ThuFriSat" と表示されてしまうのです。
文字列の表示が止まるのは '\0' がある所、と言っても同じことです。

j[7][3] も同じく、各曜日文字列(漢字一文字)に続くべき '\0' が無いので、メモリには "日月火水木金土" とくっついているので同じ結果になります。

取り急ぎの対策は、'\0' が格納できるように、各曜日の長さを3から4に増やすことです。少なくとも e 配列 "Sun", "Mon" ・・・はこれで対策できます。

C

1 char e[7][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; 2 char j[7][4] = {"日", "月", "火", "水", "木", "金", "土"};

tatsu99さんが e[7][16], j[7][16] と、3から16に増やしたのも、要は '\0' を格納できるよう、場所を確保したのです。しかし16まで増やす必要はありません。メモリの無駄遣いです。特にアスキーコードを格納する配列 e は e[7][4] で十分です。

char e[7][3] と char e[7][4] の違いを図にしてみました。
配列の姿
二次元配列であっても、メモリ上では右側の図のように、一列に並んでいます。
char e[7][3] という配列なら
e[0][2] (== "Sun"の'n')の次は e[1][0] (== "Mon"の 'M')が続きます。間に '\0' が入る余地が無く、メモリ上では "SunMonTue..." とくっついています。 '\0' までが文字列ですから、"Sun" を表示しようとすると "SunMonTue..." を表示してしまうという次第。

ちなみに、私の手元で e[7][3], j[7][3] はこんな風に表示されました(コンパイラは やや古い GCC を使用)。

現在時刻のUNIX時間は1562282032秒です. ***構造体tmのメンバを参照*** tm_sec : 52 秒 tm_min : 13 分 tm_hour : 8 時 tm_mday : 5 日 tm_mon : 6 月(-1) >>>tm_mon補正 : 7 月 tm_year : 119 年(-1900) >>>tm_year補正 : 2019 年 tm_wday : 5 (曜日コード) >>>tm_wday英語 : FriSat@V,a >>>tm_wday日本語 : 金土SunMonTueWedThuFriSat@V,a
  • "Fri" を表示すべきところ、FriSat@V,a とゴミまで表示された
  • "金" を表示すべきところ、金土SunMonTueWedThuFriSat@V,a と表示された

文字列の区切り(終端)となる '\0' が無いため、'\0' が見つかるまで表示した結果です。

char e[7][4] であれば '\0' も格納できます。"Sun", "Mon" ... とそれぞれが区切られてあるので、"Sun" は "Sun" だけが表示されます。

なお、漢字で書く配列 j は4でよいのか、問題になる可能性があります。漢字の文字コードは一種類ではないからです。漢字コードが違うと漢字一文字のバイト数が違うので、常に長さ4で良いとは限りません。なので、「曜日を格納する領域を十分大きくと」ろうとする考えが出てくるわけです(でも16も必要ありません)。

こうした問題をきれいに解決する書き方があります。それは配列を単純な二次元配列ではなく、文字列のポインタ(アドレス)の配列にすることです。書き方は次の通り、わずかな違いです。

C

1 char *e[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; 2 char *j[7] = { "日", "月", "火", "水", "木", "金", "土" };

この書き方は漢字コードが違う環境でも問題無く使えます。曜日を表示する printf() 文もそのままで、修正する必要はありません。お試しあれ。

P.S.
曜日の表示に if 文を7つ続けていますが、if 文は不要です。この2行だけで全ての曜日を表示できます。

C

1 printf(">>>tm_wday英語 : %s\n", e[yed.tm_wday]); 2 printf(">>>tm_wday日本語 : %s\n", j[yed.tm_wday]);

投稿2019/07/04 10:25

編集2019/07/05 00:00
rubato6809

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

char e[7][3] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"};

char j[7][3] = {"日", "月", "火", "水", "木", "金", "土"};

C言語の文字列では、終端の'\0'が必須ですんで、これでは文字列が収まりません

投稿2019/07/04 08:24

y_waiwai

総合スコア87749

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問