🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

4回答

1277閲覧

クラス、構造体、配列で作った関数の外(while (){}の{}の中)で同じ変数を扱う方法。

R-ogiura

総合スコア60

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

1グッド

0クリップ

投稿2019/11/18 22:00

編集2019/11/21 05:29

以下の三つのプログラムはkazuma-sという方に書いていただいたクラス、構造体、配列のプログラムです。
どれも文字を一文字ずつ描画するためのプログラムです。
まず**一つ目の質問です。**クラスで書かれたプログラムについてです。
クラスで書かれたプログラムのclass Str の中にif文でposなどの変数を扱って場合はエラーはないですが、
class Strの外部で(while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())の{}の中に)class Strの変数posを扱うとエラーが出ます。調べるとアクセスする必要があるとのことなのですが、
書き方がわかりません。

**二つ目の質問です。**構造体で書かれたプログラムについてです。
こちらがクラスです。一つ目の質問と似ているのですが、構造体struct Strの中に書いてある変数posの中身を
関数DrawFormatStringを用いて描画しようとしたのですが、while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())の中にDrawFormatString(300, 300, Green, "%d", s->pos);を書いたのですが、sが定義されていないとエラーが出ます。構造体の変数から作った関数void drawStringの外部のwhile (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())の{}の中で変数posを扱うにはどのように書けばいいのでしょうか。

**最後の質問です。**配列で書かれたプログラムについてです。
関数の中以外で(while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen())の{}の中でpos[i]を使うにはどのように書けばいいでしょうか。他にも原因は同じですが、DrawFormatString(300, 300, Green, "%d", i);と書いてみたのですが、変数iが定義されていないとでてエラーになります。
こちらがクラスのプログラムです。

#include <DxLib.h> class Str { const char* str; int frame; int pos; int count; public: void setMember(int iMember) { pos = iMember; } Str(const char* str, int frame) : str(str), frame(frame), pos(0), count(0) {} void drawString(int x, int y, int color) { if (count == 0 && str[pos]) pos += 1 + IsDBCSLeadByte(str[pos]); if (++count == frame) count = 0; DrawFormatString(x, y, color, "%.*s", pos, str);//ポインタの配列としてstrを*sとして、[]の中のposは%としたのだ。 } void reset() { pos = count = 0; } }; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetFontSize(25); //サイズを64に変更 ??? SetFontThickness(10); //太さを8に変更 ??? ChangeFont("MS 明朝"); //種類をMS明朝に変更 ChangeFontType(DX_FONTTYPE_ANTIALIASING); //アンチエイリアスフォント SetGraphMode(780, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 SetWindowSizeChangeEnableFlag(FALSE, FALSE); SetGraphMode(780, 680, 32); // 画面サイズは最大の780*680にしておく SetWindowSize(780, 680); // 最初は 640x480 にしておく ??? int Green = GetColor(0, 255, 0); Str str1("あいうabc", 50); // 6文字を 50フレームごとに 1文字追加 // 全部で 300フレーム(5秒) int t = 0; while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) { str1.drawString(100, 500, Green); if (++t == 60 * 6) { t = 0; str1.reset(); } // 6秒ごとにリセット } DxLib_End(); // DXライブラリ終了処理 return 0; }

こちらが構造体です。

#include <DxLib.h> struct Str { const char *str; int frame; int pos; int count; }; void drawString(struct Str *s, int x, int y, int color) { char c = s->str[s->pos]; if (s->count == 0 && c != '\0') s->pos += IsDBCSLeadByte(c) ? 2 : 1; if (++s->count == s->frame) s->count = 0; DrawFormatString(x, y, color, "%.*s", s->pos, s->str); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetFontSize(25); //サイズを64に変更 ??? SetFontThickness(10); //太さを8に変更 ??? ChangeFont("MS 明朝"); //種類をMS明朝に変更 ChangeFontType(DX_FONTTYPE_ANTIALIASING); //アンチエイリアスフォント SetGraphMode(780, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 SetWindowSizeChangeEnableFlag(FALSE, FALSE); int Green = GetColor(0, 255, 0); struct Str str1 = { "あいうabc", 50, 0, 0 }; int t = 0; while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) { drawString(&str1, 100, 500, Green); if (++t == 60 * 6) { t = 0; str1.count = str1.pos = 0; } } DxLib_End(); // DXライブラリ終了処理 return 0; }

こちらが配列のプログラムです。

#include <DxLib.h> const char *str[3] = { "あいうabc", "0123456789", "ABCDEFG" }; int frame[3] = { 50, 30, 40 }; int pos[3]; int count[3]; void drawString(int i, int x, int y, int color) { char c = str[i][pos[i]]; if (count[i] == 0 && c != '\0') pos[i] += IsDBCSLeadByte(c) ? 2 : 1; if (++count[i] == frame[i]) count[i] = 0; DrawFormatString(x, y, color, "%.*s", pos[i], str[i]); } int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetFontSize(25); //サイズを64に変更 ??? SetFontThickness(10); //太さを8に変更 ??? ChangeFont("MS 明朝"); //種類をMS明朝に変更 ChangeFontType(DX_FONTTYPE_ANTIALIASING); //アンチエイリアスフォント SetGraphMode(780, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 SetWindowSizeChangeEnableFlag(FALSE, FALSE); int Green = GetColor(0, 255, 0); int Yellow = GetColor(255, 255, 0); int White = GetColor(255, 255, 255); int t = 0; while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) { drawString(0, 100, 500, Green); drawString(1, 100, 530, Yellow); drawString(2, 500, 530, White); if (++t == 6*60) { t = 0; for (int i = 0; i < 3; i++) pos[i] = count[i] = 0; } } DxLib_End(); // DXライブラリ終了処理 return 0; }

編集
構造体のプログラムに関してなのですが

char c = s->str[s->pos];//ポインタsに入っているstr[pos]の文字のデータが一文字ずつcに入る if (s->count == 0 && c != '\0')//その時にcountが0でかつcに入る文字が¥0(文字列の最後の部分\0)でない、すなわち文字ならば日本語一文字は2バイトなので、   s->pos += IsDBCSLeadByte(c) ? 2 : 1;//posに2バイトを足す、違う場合は¥0(\0)なので1バイト加える。(¥0(\0)は1バイトなので。) if (++s->count == s->frame) s->count = 0;//一文字ずつ出力する間隔を処理する変数countと間隔の最大値を表すframeが等しくなったら、countを0にする DrawFormatString(x, y, color, "%.*s", s->pos, s->str);//関数drawStringの引数として関数DrawFormatStringの引数を利用する

の部分に関してわからないことがあります。
最後の部分のs->pos, s->strの中身を表すために"%.*s"と書いていますが、なぜ"%.*s"のように書けるのでしょうか。

もう一つ、配列のプログラムに関して
const char* str[3] = { "あいうabc", "0123456789", "ABCDEFG" };
ポインタを使用して右の三つの文字列を配列に入れるまではわかるのですが、**なぜポインタを使用して、constを付けたのかわかりません。**どうか理由を教えてください。

編集後のクラスのプログラム

#include <DxLib.h> class Str { const char* str; int frame; int pos; int count; public: int position() const { return pos; } // コレ追加 Str(const char* str, int frame) : str(str), frame(frame), pos(0), count(0) {} void drawString(int x, int y, int color) { if (count == 0 && str[pos]) pos += 1 + IsDBCSLeadByte(str[pos]); if (++count == frame) count = 0; DrawFormatString(x, y, color, "%.*s", pos, str); } void reset() { pos = count = 0; } }; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetFontSize(25); //サイズを64に変更 ??? SetFontThickness(10); //太さを8に変更 ??? ChangeFont("MS 明朝"); //種類をMS明朝に変更 ChangeFontType(DX_FONTTYPE_ANTIALIASING); //アンチエイリアスフォント SetGraphMode(780, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 SetWindowSizeChangeEnableFlag(FALSE, FALSE); SetGraphMode(780, 680, 32); // 画面サイズは最大の780*680にしておく SetWindowSize(780, 680); // 最初は 640x480 にしておく ??? int Green = GetColor(0, 255, 0); Str str1("あいうabc", 50); // 6文字を 50フレームごとに 1文字追加 // 全部で 300フレーム(5秒) int t = 0; while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) { str1.drawString(100, 500, Green); if (++t == 60 * 6) { t = 0; str1.reset(); } // 6秒ごとにリセット DrawFormatString(300, 300, Green, "%d",pos);//これを追加した } DxLib_End(); // DXライブラリ終了処理 return 0; }

編集後の解決したクラスのプログラム

#include <DxLib.h> class Str { const char* str; int frame; int pos; int count; public: int position() const { return pos; } // コレ追加 void setMember(int iMember) { pos = iMember; } Str(const char* str, int frame) : str(str), frame(frame), pos(0), count(0) {} void drawString(int x, int y, int color) { if (count == 0 && str[pos]) pos += 1 + IsDBCSLeadByte(str[pos]); if (++count == frame) count = 0; DrawFormatString(x, y, color, "%.*s", pos, str);//ポインタの配列としてstrを*sとして、[]の中のposは%としたのだ。 } void reset() { pos = count = 0; } }; int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { SetFontSize(25); //サイズを64に変更 ??? SetFontThickness(10); //太さを8に変更 ??? ChangeFont("MS 明朝"); //種類をMS明朝に変更 ChangeFontType(DX_FONTTYPE_ANTIALIASING); //アンチエイリアスフォント SetGraphMode(780, 680, 32); // ウィンドウの大きさを指定 ChangeWindowMode(TRUE); // 全画面ではなくウインドウを使用 if (DxLib_Init() == -1) return -1; // DXライブラリ初期化処理 SetDrawScreen(DX_SCREEN_BACK); // 裏画面を使用する設定 SetWindowSizeChangeEnableFlag(FALSE, FALSE); SetGraphMode(780, 680, 32); // 画面サイズは最大の780*680にしておく SetWindowSize(780, 680); // 最初は 640x480 にしておく ??? int Green = GetColor(0, 255, 0); Str str1("あいうabc", 50); // 6文字を 50フレームごとに 1文字追加 // 全部で 300フレーム(5秒) int t = 0; while (!ScreenFlip() && !ProcessMessage() && !ClearDrawScreen()) { str1.drawString(100, 500, Green); DrawFormatString(300, 100, Green, "%d", str1.position());//Str str1("あいうabc", 50);に関しての関数position()のposについて描画できた。 if (++t == 60 * 6) { t = 0; str1.reset(); } // 6秒ごとにリセット } DxLib_End(); // DXライブラリ終了処理 return 0; }

編集後の配列の解決したプログラム
文字数制限があるのでこちらのサイトに書きました。
配列の解決したプログラム

編集後の構造体の解決したプログラム
構造体の解決したプログラム

退会済みユーザー👍を押しています

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

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

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

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

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

m.ts10806

2019/11/19 23:18

次に質問をたてる機会があるなら「雑談トピックとして使ってください」と一言いれておいてください。 あなたの質問に雑談スレッド以上の価値はないので。絡むと言うなら出ていってください。 これからプログラミングを始める人の邪魔をしているのと同じです。
m.ts10806

2019/11/20 23:03

解決済みの質問をなんで編集したんでしょ。 解決してないなら解決済みに設定しないでください。
m.ts10806

2019/11/21 05:18

どんどん更新されてますがこのコード、誰の役に立つんでしょう。 解決済みの質問を何度も編集してベストアンサーも始めにつけた本人になんの断りもなく付け替えて何事もなかったように無駄コードを更新し続けて、どこまで失礼な人なんでしょう。 (複数アカウント所持のサイト規約違反を犯していることもお忘れなく。何個やるつもりなんでしょ。マルチポストももはや癖ですね。間違ったやり方しかしてない)
guest

回答4

0

こういうことを言われるのは嫌でしょうけども,
言語文法やスコープといった範疇の話なので,一度本当に 基礎から順に 勉強することをお勧めします.
(ここって,完全に文法レベルからわからん状態におけるQに対してAするサイトなのかどうか…?)

(個人的な経験上の範疇の話ですが)全くプログラミング未経験の新人でも2週間程度の独学をやらせれば,このレベルのことにつまずくことはまずありません.
あなたの取り組み方は無意味に遠回りをしているようにしか見えません.

まぁあなたの現在のスタイルを貫くのだとしても,とりあえずclassのことは忘れることをお勧めします.


なぜ"%.*s"のように書けるのでしょうか。

「printf 書式指定 文字列 長さ」あたりでググると,そういう書式指定方法があるということがわかるかと思います.
DrawFormatString()をググるとリファレンスページで「ほぼ printf と同じ機能を提供します。」と書いてありますので,この書式指定が使えるのでしょう.


ポインタを使用して右の三つの文字列を配列に入れるまではわかるのですが、なぜポインタを使用して、constを付けたのかわかりません。

自然な記述だと思います.
単純に「文法がわかりません」という意味なら上述の通り基礎を学んでみてください.
そうではなくて「こう書けばよいハズなのに,なぜこう書いているのか?」みたいな別案との比較における「なぜ」を問うているのであれば,あなたの別案が示されないと答えられません.

投稿2019/11/19 01:53

編集2019/11/19 06:08
fana

総合スコア11985

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

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

R-ogiura

2019/11/19 04:32

そうですね。普通の人なら2週間程度で出来ますね。 スタイルを貫くというか、実際の問題に取り組みながら出ないと身に付きにくい出来の悪い頭でして。 プログラミングには破滅的に向いていませんが、それでも作りたい気持ちはあるので自分の学びやすいスタイルで勉強しています。
Zuishin

2019/11/19 04:54

それで人の数百倍の時間がかかってるんだから試しに変えてみればいいのに。自分が一番自分のことをわかっていると思うのは幻想です。だいたいそういう人は医者に「なんでもっと早く来なかったんだ」と怒られます。
fana

2019/11/19 05:06

「2週間…」というのは煽り文句とかではなく,本当の話ですよ.(と,一応誤解なきよう言っておく) 2週間独学というのは結構な時間です. 例えば1日2時間やったとしたら(単純な時間換算で)講義とかなら結構な回数分になります. 入門書を毎日10ページほど読み進めるとしても140ページ進む. 課題用の簡単仕様の電卓だとかマインスイーパみたいなお馴染みの初心者課題を与えられれば何やかんや言いながらも一人でまぁまぁそこそこに作れる頃でしょう. それと比較して,実績的な面でみたときに,今のやり方が本当に > 学びやすいスタイル と言えるのか,疑問です. 問題に取り組みながらのほうがやりやすいという話はわからなくもないですが…
fana

2019/11/19 05:16 編集

頭が良いとか悪いとかそういう領域の話じゃなくて, 何だろうなぁ,たとえるなら, 【2時間映画をあえて末尾30分くらいだけ見て「話がわからん」とか言っている】ような感じです. それに対して「最初から見たらどうでしょう」って答えている感じ.
yoorwm

2019/11/19 05:38

というか、「~という方に書いていただいた」ものに対して関係無い所で質問している辺り、色々と質問の仕方とか人としてどうなのか?という所がおかしくないですか?
fana

2019/11/19 05:45

少なくとも,質問に編集で追加された「書いてもらったコードの内容そのものへの疑問」に関しては,そのコードの出所にて書いた本人に訊くのがよいでしょうね.
Zuishin

2019/11/19 05:51

聞いて断られてるんですよ。新しく質問しろって。 この人の質問に答えてたらきりがないので無理からぬことではあるんですが、そこまで自分の手に余るものをなぜベストアンサーに選んだのかということもつっこまれてますね。
episteme

2019/11/19 06:27

しかも質問の9割は「教本/マニュアル読め(=基礎を固めろ)」がコタエなんだなー...
BluOxy

2019/11/20 02:27 編集

> 【2時間映画をあえて末尾30分くらいだけ見て「話がわからん」とか言っている】 これは思いました。 頭が良い悪いというよりも ・末尾30分を見るだけで物語を理解できると信じてしまっていること ・冒頭90分を見ても(頭が悪いからなのか、何なのか、自分で無理くり理由をつけて)物語なんて大して分からないだろうと思い込んでいること が問題に感じます。 基礎を学べと指摘するユーザーを敵と見ているのかはよくわかりませんが、目を覚まして、耳を傾けてほしいです。 (耳を傾けるということは、まずは行動を変えることです。つぎに習慣を変え、やがてあなたの考え方自体を良い方向に持っていくということです)
thkana

2019/11/19 14:43

普通の人がC言語始めて2週間で理解できているはずのことが2年(3年?まぁいいや)つまり100週間でまだ理解できていないとすれば、単純に比例させると普通の人がロックマンエグゼ風ゲームに1年かかるとして50年以上、大量殺戮兵器に10年かかるとすれば500年以上、という計算になります。これは「どうしてもやりたいです」だけで乗り切れる壁ではないと思いますが如何。
R-ogiura

2019/11/19 20:34

50年以上かかっても作れればいいじゃんと思いますが。 不毛な会話を続けてもコメント欄が長くなるだけなので解答に関係ないコメントは書かないでください。
m.ts10806

2019/11/19 20:56

関係ないと言い切れるだけの知見を持ってから言ってください。 都合の悪いところを無視して言いたいことだけ言ってるからこうなるんですよ。 というか「こいつには雑談でもしとけばいい。どうせ何言っても理解しないから」とteratail含めた全ての質問サイトの回答者全員にあしらわれてると思ったら良いです。 ご自身が原因でしょう。あなたがあなたのいう「不毛な会話」にさせています。
m.ts10806

2019/11/19 21:13

ちなみに基礎ができてるかできてないかは見れば明白でその人に対し「基礎をかためましょう」から「質問の姿勢に対する姿勢への指摘」「学習のやり方に対する指摘」をすることは無関係でも不毛な会話でもありません。むしろ前向きで成長のチャンスですらある。 それを受け入れないというのは50年後も同じ質問をしていることになります。例え500年後でもね。 何も誤解されるような書き方はどこにもないのになぜか誤解しかしてないようですが、例え赤の他人であっても時間を浪費して欲しいと思ってる人っていないんですよね。 例え嘘つきで規約違反とマナー違反を繰り返している人だとしても。初見で無視できないはずの物騒なワードも出てきて知らないはずのことをなにも疑問視しないってことはもう認めたとイコールですし。
episteme

2019/11/19 21:26

回答つけといたから解決なり質問重なるなりしといてね。
R-ogiura

2019/11/19 22:27

回答、ありがとうございます。
Zuishin

2019/11/19 22:46

関係ないどころか、この問題の一番のボトルネックは carnage0216 さんなんですよね。この人を首にして別の人が作ればすぐできる話ですが、そういうわけにはいかないので、今ある状況の中で最善の解決策を書いているんです。 で、50 年でできる保証なんか誰もしてませんよ。人は年を取れば能力が衰えます。一番伸びる時期に人の 50 倍かかってるなら、50 年後は何もできないでしょう。 ベテラン勢が口をそろえて言う解決策を反故にするほど自信があるなら好きにすればいいと思いますが、それであなたが何かを成し遂げることはないでしょう。
m.ts10806

2019/11/19 22:56

ひとまず関係ないと言い切れるだけの知見を持ってから言ってください、とだけ。 これ以上苦言を聞きたくないなら尚更ね。スルーすればするほど立場が悪くなることくらい分かるでしょう。 2年以上何も学んでないんですか?最早やる気ないのとイコールです。
thkana

2019/11/19 23:01

不毛というならいまのやり方で50年以上続けることの方が不毛と思いますが、まぁそれはあなたの人生なので。ただ、ここに質問を載せた以上は、みながそれぞれ思う解決策を提案するわけです。そういう場ですから。 > スタイルを貫くというか、実際の問題に取り組みながら出ないと身に付きにくい これまでのところ、そのスタイルでどんどん疑問を発散させていくようにしかみえないのですが。
BluOxy

2019/11/20 02:55

「不毛な会話」と思っているのはR-ogiuraさんだけです。 teratailに限らず、たくさんの人から「基礎をやってください」と言われているのであれば、それが問題の本質です。薄々気づいているのではないでしょうか。 それでも基礎をやらないというのは、本当に基礎の大切さに気づいていないからなのか、どこか意固地になっているからなのか、そのいずれかではないのでしょうか。 確かに周りがする指摘は、多少は間違った内容が含まれているかもしれません。 しかし、大半は正しいです。間違った内容は他のユーザーが指摘をしますから。 色々な質問を拝見した結果、「基礎を学んでください」という指摘が一番多いようです。 多いということは多数がそうしてほしいとR-ogiuraさんにお願いをしている訳なので、そこに間違いというのはほぼほぼ含まれることはありません。つまりほぼほぼ確実に正しい指摘です。 R-ogiuraさんはそこを「不毛」と思い込んでいるのです。まるで催眠術にかかったみたいに。 なので、目を覚ましてください。 指摘のされ方が「冷たい」と感じることもあるかもしれません。 しかし、そこだけを取り上げてはいけません。 目を向けるべきなのは「相手の感情や対応」ではなく「相手が指摘している内容」なのです。 そこに耳を傾けてみませんか? 指摘されたことを実践していけば、ほぼ確実に問題を解決することができるようになります。 知見がない人は、左も右も分からないはずですから、道を外れないためにも目の前の回答(動くコード)よりもそういった指摘に耳を傾けるべきなのです。
R-ogiura

2019/11/20 03:08 編集

では、薄いCの本を参考にして勉強しながら作りたいプログラムを作っていく方がいいでしょうか。 自分は作りたいものを作りながら学ぶ方がいいです。 ただ本を読んで書くだけではなんだかつまらなくなってしまって。 配列なら理解出来そうなのですが、構造体は難しいといか配列で表せるならそれでいいと考えています。 なのでカズマさんの配列のプログラムを理解した上で使わせて頂きます。
Zuishin

2019/11/20 03:08

厚い方がいいと思います。episteme さんが薄い本を勧められたのは、薄い本ならすぐ終わるだろうという考えだと思いますが、薄い本というのは省略が多いということなので、読むために必要な力のハードルも上がります。 細かいところまで丁寧に書いてある本を読み、疑問に思ったことは実際にコードを書いて走らせて確かめ、一通り終わった後で今までの自分のコードを読んでみてください。「なんだこれは」と穴があったら入りたくなると思います。ですが、それは成長した証なので、恥ずべき事ではなく誇るべきことです。
m.ts10806

2019/11/20 03:12

>ただ本を読んで書くだけではなんだかつまらなくなってしまって。 それは本の内容すらまともに理解できてないからです。 そして自己評価が高すぎることも起因しています。
BluOxy

2019/11/20 13:11 編集

作りたいものを作りたいと考えるのは良いことです。 でも、分からなかったら(質問することになったら)そこには前提の知識が存在するはずです。 つまらないと感じるその理由は、学ぶ意味がないのだと、そう感じているからではないでしょうか?(どうでしょうか?) 意味はあります。超あります。前提の知識は、今後あなたが作りたいものをあなた自身の手で作るために覚えるのです。それって、考え方次第では凄く楽しいことではないでしょうか。 なので、作りたいものを作るときに、何の前提知識が必要なのか、洗い出してください。 もし洗い出せたなら、薄いCの本(これはC++ではない?)でも、C++のリファレンスでも何でも見て、その前提知識を学んでください。 洗い出すことが難しければ、まずは順当にC++ではどういう機能が使えるのか? そこを教材なりリファレンスなりで学び始める必要があります。 なんていうか、上で指摘していることはほぼすべて共通して「分からないことが何かを考える」「分からないことを分からないままにしない」行動を勧めているだけなんですね。 なので、それ等を意識して行動すると良いと思います。 ※ C++で分からないことがあれば、それは質問するのではなく、教材やリファレンスにほぼ確実に載っているはずなので、それ等資料を見てくださいというのが周りの指摘でもあります。もしリファレンスにC++の機能が記載されていなかったら、それはリファレンスとして機能していないことになります。なので、通常そんなことはありません。 なので、分からないことがあったときはC++の教材やリファレンスと「どう向き合うか」がR-ogiuraさんにとって大事なのではないかと思います。
m.ts10806

2019/11/20 03:23

(素振りもせずにホームラン打てる人ってどれくらいいるかな?) →むしろバットすら持ってないんじゃ? (ウォームアップせずにフルマラソン完走できる人っているかな?) →むしろハイハイすらできてないんじゃ? 「成長できない初学者」の共通点は自分の現在地を見誤っていること、自己評価が高すぎることです。 で、大抵は「わかりました」とだけ返して結局何も省みない。 誰かさんそのままじゃないですか。
episteme

2019/11/20 03:37 編集

んー、厚いヤツは「鈍器」になるからなー。 薄っすい本で十分とは思っちゃいないけど、まずは"通読"して欲しくって、それには薄いヤツかなと。挫折する前に読了できそうやし。 # 物足りなく感じたら、それは成長のシルシ
Zuishin

2019/11/20 03:37

私もどんな本が彼に向いているかをはっきり知っているわけではないんですが、通読できるなら薄い本でもいいかもしれませんね。ただ今までの質問を見ると、「そこ今いる?」というどうでもいいところにこだわっていたり、一から十まで全部説明しないとわからない節があるので、厚い本の方が向いているのかなと思いました。
episteme

2019/11/20 03:41

大きメの本屋さんで目次だけでもパラパラするとこから始めよか。でOK?
Zuishin

2019/11/20 03:46

そうですね。興味をひいて詳しく読みたくなるかもしれませんし。
thkana

2019/11/20 13:03

> 自分は作りたいものを作りながら学ぶ方がいいです。 そのやり方でうまくいっているなら誰も文句はつけないし、あなたはすいすいとプログラムを書いているはずです。 うまくいっていないのでしょう? なら、やり方を変えなきゃいけないのでは、という疑念は出てきませんか?
R-ogiura

2019/11/20 14:10

はい、まずは薄い本で、Cの絵本とかやさしいCを読みます。
episteme

2019/11/21 05:22 編集

教本の通読を勧めたけど、不安な点を残している。「類推」ができないと、「この問題は教本にあったアレと"同じ"だ」に思いが至らない。本件の質問は類推で7割解決できたんじゃないだろうか。同類の質問が繰り返されるのも具体的にどう書くか(そのものズバリ)を欲しがるのも。 「実際の問題に取り組みながらでないと身に付きにくい」のもそこらへんが絡んでるように思われる。
m.ts10806

2019/11/20 23:05

読んだだけでコードが動くと思ってるなら幾らでも読んだらいい。 やり方と考え方をごっそり変えないと本質である問題解決には50年どころか一生かかっても生まれ変わっても辿り着けない。
fana

2019/11/21 02:58

> 自分は作りたいものを作りながら学ぶ方がいいです。 このことと基礎を学ぶことは背反しない. 【「最終的に作りたいもの」に含まれる個々の部分要素を達成するような小さいプログラム】を題材として作りながら学べばよい. で,その要素の実装は,その小さいプログラムの内容にべったりな形ではなく,その部分を他のプログラムを作る際に再利用できるように実装する. それは「最終的に作りたいもの」の部品を作る(+その部品の動作確認を行う)プロセスに他ならないではないか. 例えば今回の文章表示で言えば,何かそれなりの長さの文章を読めるというだけのプログラムを作る. 文章表示を制御する部分は,クラスなのか,「構造体+関数」なのか,「配列+関数」みたいな形なのかわからんけども,表示したい文章の内容や長さが変わっても使える形に纏められれば,最終的に作りたい物にそのまま取り込める.(とても普通の話だ) 「小さなプログラム」もまた,より小さな構成部品の組み合わせであり得る. その中のどれかに不安があるなら,それを試して使って不安を解決してみるためのより小さいプログラムから始めればよい. そうやってどんどん分解していって,理解して使いこなせるようになった小さな部品群を武器にして少しずつより大きい部品を組み上げていくわけだ.
R-ogiura

2019/11/21 05:15

fanaさんの言う 「「小さなプログラム」もまた,より小さな構成部品の組み合わせであり得る. その中のどれかに不安があるなら,それを試して使って不安を解決してみるためのより小さいプログラムから始めればよい.」 の部分からプログラミングの勉強のやり方が少しわかりました。ありがとうございます。 いきなり大きい物を作るのですはなく、まずは簡単なものをいくつか作り、次は組み合わせて、どうすれば組み合わせてもエラーがでないかを本とサイトを参考に調べます。それでもダメな時は質問します。
m.ts10806

2019/11/21 05:20

↑今まで何度も言われているはずのことをさも今初めて聞いたかのようにコメントしてる時点で先は見えてます。 特定の回答者のコメントもスルーし続けてますし、もはや自分が誰であるか宣言してるようなもんです。
fana

2019/11/21 05:54

「より小さな構成部品」とは,どんどん細かく分解していけば,最終的には,文法だとか変数の通用範囲だとか生存期間だとかいう事柄にまで行き着く. そういう基礎部品に不安がある状態で,それらによって組み上げられた大きな物をいきなり扱おうとすれば無理が出るわけですね(これがあなたの今の状態). だから,勉強して理解していく順序というのは結局「基礎から」になるわけです.
guest

0

ベストアンサー

回答順を少し並べ替えさせていただきます。

二つ目の質問および三つ目の質問

ローカル変数として宣言された変数は、宣言した{ }の外に出ると存在しません。
存在しないのでアクセスすることは出来ません。

1つ目の質問

あえて悪い方法を提示すると、public以下に対象の変数の宣言を移動させる事で
str1.posにてアクセスできます。(前述したローカル変数str1のスコープの問題はあります。)

c++

1class Str { 2// ... 3public: 4 int pos;

ただし、この方法はクラスの外部から内部の変数を書き換える事ができてしまうため、悪い方法です。
普通は、epistemeさんのようにアクセサやプロパティ等と呼ばれるメンバ変数を読み取り・書き込みするためのメンバ関数を作成した方がよいです。

なぜ"%.*s"のように書けるのでしょうか。

書式指定文字列の仕様によって
printf("%.*s", arg1, arg2);は文字列arg2を最大arg1文字表示する。 事になっているからです。

なぜポインタを使用して、constを付けたのかわかりません。

設計者じゃないので推測しかできませんが
C++における文字列リテラルはCと違い、const char[]型として扱われます。
そのため、とりうる選択肢としては

const char *str[3] = { "あいうabc", "0123456789", "ABCDEFG" }; char str[3][13] = { "あいうabc", "0123456789", "ABCDEFG" }; std::string str[3] = {"あいうabc", "0123456789", "ABCDEFG" }; const char str[3][13] = { "あいうabc", "0123456789", "ABCDEFG" }; const std::string str[3] = {"あいうabc", "0123456789", "ABCDEFG" };

となり、一番簡易なconst char*を選択したのではないかと思います。
出力途中で変に書き換えられてバグ扱いされるのも嫌でしょうし

投稿2019/11/19 22:27

asm

総合スコア15149

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

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

R-ogiura

2019/11/20 00:02

解答ありがとうございます。 なるほど、C++では文字列はCと違い、const char[]型を使わないとエラーになってしまうのですね。 ただ、const char str[3] = { "あいうabc", "0123456789", "ABCDEFG" };の場合、 3つのstrの箱に文字列あいうabc", "0123456789", "ABCDEFGが入ると思うのですが、ポインタを付けないとエラーになります。なぜでしょうか。 個人的にはバグが起きるかもしれませんがエラーになるとは思っていませんでした。
episteme

2019/11/20 00:11 編集

「...入ると思う」が間違いだから。教本読め。
R-ogiura

2019/11/20 00:15 編集

epistemeさん、お応えして頂けるのはありがたいのですが、あなたがおいくつかは知りませんが(私よりも年上だと思いますが)、命令するような言い方はやめてください。
R-ogiura

2019/11/20 00:22

#include <string>を加えることで std::string str[3] = {"あいうabc", "0123456789", "ABCDEFG" }; や const std::string str[3] = {"あいうabc", "0123456789", "ABCDEFG" };が使えるとわかりました。
episteme

2019/11/20 00:27

このくらい強く言わないと聞いてはくれんと思いましてね。
asm

2019/11/20 00:51

> 3つのstrの箱に char型の箱にはcharが1個しか入らないので const char str[3] には、3文字(NULL文字を含めれば2文字)までしか入りません。
R-ogiura

2019/11/20 01:41

なるほど、const char str[3] は一次元配列でポインタを使わないと3文字の文字が一つずつ入る箱が3つ用意されて、 const char* str[3] 一次元配列でポインタを使うと3っつのポインタが得られ、その3っつポインタに3つの文字列が一つずつ入るためエラーにならないのですね。
asm

2019/11/20 04:13

(日本語の問題ですが、最近言った言わないで何度か揉めたので)訂正しておくと > const char str[3] は一次元配列でポインタを使わないと3文字の文字が一つずつ入る箱が3つ用意されて ポインタを使わないconst char str[3] は一次元配列で~ ならば、そのとおりです。
R-ogiura

2019/11/20 11:57

返信ありがとうございます。C++のクラスに関してですが、 クラスのプログラムにint position() const { return pos; } を追加した後で、何を書き足せば変数posの値がわかるのでしょうか。
kazuma-s

2019/11/20 12:29

クラスを理解せずに答えだけがほしいのですか? str1.position() で str1 の pos が取得できます。 クラスを理解するには、構造体やポインタの理解が必要です。 構造体やポインタは型です。型の理解が必要です。 型によって変数を宣言するので、宣言の理解が必要です。 宣言した変数の使い方の理解が必要です。 変数の寿命(生存期間) や 変数名の有効範囲(スコープ) の理解も必要です。 実用的なプログラムを作りながら言語の基礎を勉強しようとするのは構いませんが、 やりたいことを実現するために何が必要かは、基礎をある程度蓄えておかないと どれとどれを組み合わせれば実現できるか考えることができません。 結局分からないから、分からないことを人に聞く。 基礎が分かっていないからその回答が理解できない。 理解できないけど、動くコードが得られたから、そのまま理解せずに使ってしまう。 そして、次に新しい機能を追加しようとすると、また分からない。 この繰り返しですね。
asm

2019/11/20 13:37

私は既に、アクセサやプロパティという自分で学習しようと思えば検索できるだけの取っ掛かりを与えたつもりですが 自分で調べようとは思わなかったんですね
R-ogiura

2019/11/20 14:09

では、クラスは勉強しないことにします。 とりあえず、構造体も難しいので配列までを勉強します。 kazuma-sさん、asmさん、ありがとうございます。
episteme

2019/11/20 21:31 編集

構造体(とポインタ)抜きだと苦労するんだがな...
R-ogiura

2019/11/20 22:21

では、構造体はわかりませんが、ポインタまでは頑張ってみます。 ちなみに、どんな部分で苦労知るのでしょうか。 仮に構造体が理解できない場合、配列やポインタで構造体を代わりというか代用できるくらいにはなりたいです。
episteme

2019/11/20 22:30 編集

変数が増える 引数が増える グローバル変数が増える しまいに収拾がつかなくなる。 kazuma-sさんの配列版を参照。
R-ogiura

2019/11/20 22:30 編集

なるほど、ですが私みたいな不向きな奴はそんなに大きなプログラムは作れないので多分大丈夫ですね。
episteme

2019/11/20 22:38

あなたが作っているゲームとやらは現時点で何行で、全体の何割できたと見積もっているだろうか。ちょっとしたゲームでも軽く千行を超える(構造体使っても)。
R-ogiura

2019/11/21 01:06

基本的な会話、バトル、結果のシステムがやっと作れたところです。3、4割できたところですかね。 まあ、もし作れなくても仕方ないです。
guest

0

関数の中で定義した変数は、その関数の中でしか有効ではありません。
また、ブロックの中で定義した変数は、同様にそのブロックの中でしか有効ではありません。
どこでも使えるようにするには、関数の外で定義してグローバル変数にすればいいです。
が、意図しないところで変更される可能性も出てくるため、使い所を考える必要があります

投稿2019/11/18 22:39

編集2019/11/18 22:41
y_waiwai

総合スコア88038

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

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

R-ogiura

2019/11/19 01:43

y_waiwaiさんありがとうございます。 ということはクラスも構造体も関数の中にある変数はそのブロックないでないと有効でないのでしょうか。
y_waiwai

2019/11/19 05:06

関数の中で定義してればすべて同じですね
guest

0

[1] たとえば

C++

1class Str { 2public: 3 int position() const { return pos; } // コレ追加 4 ... 5};

[2] DrawFormatString(300, 300, Green, "%d", str1.pos);

[3] pos[0] / pos[1] / pos[2] 好きなの選べ

[4] マニュアル参照

[5] const char* : 書き換えを許さない(const)文字(char)の列の頭を指すポインタ(*)
つまり文字列定数

投稿2019/11/19 11:21

編集2019/11/19 11:33
episteme

総合スコア16612

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

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

R-ogiura

2019/11/19 22:23

ありがとうございます。 あの int position() const { return pos; } // コレ追加をクラスのプログラムに編集に載せたように加えたのですが、なぜかposが定義されていないと出ます。 もう一つ、const char*の意味は分かったのですが、なぜ今回使用したのかの意図が知りたいです。
episteme

2019/11/19 22:29

- 編集時にうっかり削除してたり? コード見せて。 - 最適だから / 常套句だから
R-ogiura

2019/11/19 23:14

わかりにくくてすいません。 質問の下の方にあります。「編集後のクラスのプログラム」です。
episteme

2019/11/19 23:28

わかってなかったかー(苦笑 posは参照できないので、 追加したposition()を使って値を手に入れよ。
R-ogiura

2019/11/20 01:41

すいません、追加したposition()をどうやって使うのでしょうか。なにかヒントをください。
episteme

2019/11/20 01:50 編集

ヒントはあなたが提示したそのコードの中にあります。 > str1.drawString(100, 500, Green);
R-ogiura

2019/11/20 02:14 編集

なるほど、わからないです。 str1.drawString(100, 500, Green);は構造体で使ったプログラムですがクラスの方のプログラムにも使えるということでしょうか。
episteme

2019/11/20 02:21

> str1.drawString(100, 500, Green);は構造体で使ったプログラムですが 違います。
episteme

2019/11/20 02:24

基礎を固めようとしないあなたにC++は時期尚早と思われます。
R-ogiura

2019/11/20 02:28

しかし、どこまでが基礎がわからない以上、C++の深い部分は難しいとはいえ、最初の当たりくらいは勉強したいです。クラスはC++ですが、せめて今回の問題だけは解決してからCに戻りたいです。
episteme

2019/11/20 02:32

ならば教本を読みなさい。
R-ogiura

2019/11/20 02:36

教本のどこを読んだら int position() const { return pos; } // コレ追加の正しい使い方がわかるのかですね。
episteme

2019/11/20 02:40

本屋に売ってるいっちばん薄いC++入門書を通読すれば。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問