痔になりやすい生活習慣とは?

現在、二度目の挫折を経て再びC言語を学習しています。趣味としてやっています。
前回も教えてgoo様で質問させて頂いたのですが(https://oshiete.goo.ne.jp/qa/9256426.html)、今回も質問させて頂きたいと思い書いています。

「新・明解C言語入門編」で勉強しているのですが、どうしてもfor文多重ループが分かりません。
ネットでも検索してみたりはしたのですが、いまいち良く分かりません。
具体的に書くと、P100の演習4-20は答えを見て得心がいき解けるようになりました。演習4-21,演習4-22は解けました。
ですが、演習4-23,演習4-24,演習4-25が全く分かりません。「新・解きながら学ぶC言語」で答えを見てもどうしてそうなるのかが分かりません。
演習4-25のとあるfor文の条件式に、j <= 2 * (h - 1) + 1 と有りますが、条件式にこのような複雑(?)な式を打ち込むという発想が有りません。
答えを丸ごと自分で打ち込んでみましたが、やはり、何かしらの理解の取っ掛かりを得られる事が出来ませんでした。

ちなみに、この部分は前回つまづいた所でも有ります。今までの経験でつまづいた所で覚えているのが、多重ループ、再帰、ビット演算、ポインタです。
(ちなみに前回は同じテキストを利用して分からない所をスルーして先に進んで挫折しました。初回は「苦しんで覚えるC言語」を利用して有る程度先に進んで「ポインタ完全制覇」や「実践C言語」をやっている最中に挫折した覚えが有ります。)
前回、分からない所をスルーして先に進んで挫折した為、今回は分かるようにしてから進んだ方がいいか、と思い質問させて頂いています。

ちなみに、現在所持しているテキストは「新・明解C言語入門編」及び「新・解きながら学ぶC言語」のみです。(他の本は引越しのドタバタで紛失してしまいました、、、。

なので、現在分からない所を分かるようになる為、もしくは勉強の教本を変更する為、新しい本を買おうと思っています。
僕としては、 「やさしいC」と「12歳からはじめるゼロからのC言語ゲームプログラミング教室」がいいかな、と思っています。(Cを学んでその次にC#に進みUnityを使ってゲームを作ろうか、と考えている為です。ゲーム作りに興味が有る為です。

現在勉強している著者も、私が分からないポイント(第4章辺り)で挫折する人が多いと言っています。
僕はこの壁を突破したいと考えているのですが、何か良い本を教えて頂ければ、と思います。お願いします。

また、タイトルの「rubyに鞍替えするか」という点についてですが、「rubyは分かりやすい。C言語は教える学ぶに向いてない為、rubyでプログラミングを学習してからC言語に進んだ方が理解が早い。」という意見も聞いた為です。
ですが、前回の質問では「for文多重ループぐらいのはどこの言語でも出てくるからC言語を頑張れ。」というニュアンスの答えを頂いたのでどうしたものかと考えています。
自分としては、C言語を頑張りたいのが7で、rubyに鞍替えした方がいいのだろうかというのが3といった所です。
軽く検索した所、rubyにも再帰やビット演算などは有るみたいですし、少し迷いが有ります。
rubyをやってみた方が良いでしょうか?こちらも回答してくださると有り難いです。
個人的にはこのままC言語1本で行けたらなぁ、とは思います。

ちなみにまず母親に相談した所「ネットで聞いて。本屋に行くとしても次の水曜日ね。」と言われました。
実際に本屋で本の中身を見て買いたいという思いも有ります。(今まではAmazonで購入していました。

ご教授、何卒よろしくお願い致します。

質問者からの補足コメント

  • うーん・・・

    書いた方が良いと指摘されたので書かせて頂きます。著作権侵害の意図は有りません。(削除対象にならないかどうか、です。

    演習4-23、演習4-24は長さの関係で省略させて頂きます。

    演習4-25は、読み込んだ整数の段数を持つ下向き数字ピラミッドを表示するプログラムを作れ、第i行目にはi % 10によって得られる数字を表示することという内容です。

    まず、初期化、条件式、更新の書き方が分かりません。問題を解こうとすると頭の中が真っ白になります(分からない為)。
    分からない所が分からないと言っても近からず遠からず、と言った所です。
    変数がi,jだったり短くて意味を持ってない単語だったりするのも混乱する所です。
    1段目に1、2段目には2、、、とやるにはどうしたら良いだろう、と考え込んだりします。
    感覚的に理解しているので理解していない部分を説明して、と言われても難しい部分が有ります。

      補足日時:2017/02/27 19:53
  • どう思う?

    明日(2/28)の午前中に再度母親に相談する事になっています。
    母親はプログラミングをやった事がないですが、「数学を勉強してパターン覚えるのは、出来ない無理ダメ。回り道。」というので(僕が数学超苦手なのを知っている為)、以前から気になっていた本をまとめて買って正攻法(?)でストレートに攻めたいと思っています。以下に記します。

    「C言語ポインタ完全制覇 著者:前橋 和弥」
    「C言語による最新アルゴリズム事典 著者:奥村 晴彦」
    「C実践プログラミング 第3版 Steve Oualline (著), 望月 康司 (監訳) (翻訳), 谷口 功 (翻訳)」
    「定本 Cプログラマのためのアルゴリズムとデータ構造 著者:近藤 嘉雪」

    です。
    おそらく、明日相談が終わった後辺り(若しくは翌日)に質問を締め切らせて頂く事になるだろう、と考えています。
    (短気で焦り気味ですいません。本当に申し訳ない。

      補足日時:2017/02/27 20:06
  • うーん・・・

    僕は発想力が身につくのであればかかる期間にも寄りますが、数学を勉強するのも有りだとは思っているのですが、、、。(ですが、親のいう事に有る程度耳を貸すタイプなのです。

    例えば、
    「生き抜くための中学数学: 中学数学の全範囲の基礎が完璧にわかる本 著者:芳沢光雄」
    と言った本も有るみたいですし。数学の教養が身につきそうでは有ります。ひいてはプログラミングに役に立ちそうだなぁ、とも思います。

    ただ、現実的な問題として、予算というものが有るので、なんでもかんでも買ってる訳には行かないのも現状です。
    すいません、、、。

      補足日時:2017/02/27 20:12

このQ&Aに関連する最新のQ&A

A 回答 (9件)

>「C言語ポインタ完全制覇 著者:前橋 和弥」


>「C言語による最新アルゴリズム事典 著者:奥村 晴彦」
>「C実践プログラミング 第3版 Steve Oualline (著), 望月 康司 (監訳) (翻訳), 谷口 功 (翻訳)」

2番目はCというよりアルゴリズムの本ですね。
1、3番目は中級者向けでしょう。いきなりポインタに手を
出さない方が良いでしょう。

forの多重ループで頭が真っ白になってしまうレベルの超初心者が
読む本ではありませんね。

まず、ごくごく簡単な言語で、簡単な仕様のプログラムを
ポツポツ試してゆくしかないでしょう。

個人的にはpythonあたりをお勧めしたい。
    • good
    • 0
この回答へのお礼

回答有難うございます。
確かにおっしゃる通りの超初心者です。

アルゴリズムを勉強すれば、発想力が鍛えられるかなぁ、とか思ったのですが、、、。

tknakamuri様は(僕に対して)言語変更推奨派という事ですね。
その場合、rubyを考えていましたが、pythonも考慮に入れさせて頂きます。

重ねて回答有難うございます。

お礼日時:2017/02/27 20:42

>という事はやはり数学の勉強をするべきなのか、とも思えます。



一般的にはプログラミングに数学はあまり必要では
ありません。

ただ、この質問からだけで軽々に判断出来ませんが
今のあなたには、「算数レベル」で物事を分析的に捉える
基礎学力が不足しているのかもしれません。

私は教育者ではないので、これ以上は何とも言えない
ですね。あくまで私の感想です。
    • good
    • 0
この回答へのお礼

感想を述べて頂き有難うございます。

>一般的にはプログラミングに数学はあまり必要では
ありません。
では、今から数学を勉強する必要もあまり無いかもしれませんね。
ですが、tknakamuri様の言う通り、算数レベルで物事を分析的に捉える能力が不足しているのであれば、そこを補う必要が有るかもしれない、と理解しました。

一応、小学校、中学校、高校を経て専門学校を卒業した身ではあります。
算数までは得意でした。
ですが、中学から数学が苦手でしたので(お恥ずかしながら、高校では赤点ギリギリで赤点を取った事も有ります。)、その辺りが文章や演習問題に取り組む際に分析力の欠如という形で出ているのかもしれませんね、、、。

繰り返し対応頂き、感謝しています。
有難うございました。

お礼日時:2017/02/28 08:47

>tknakamuri様は(僕に対して)言語変更推奨派という事ですね。



配列とか文字の連結とか内容なので、この範囲であれば
Cでもなんとか。

要はi行目で
(1) スペースを幾つ出力して、
(2) 数字を幾つ出力するか

をiとhを使って数式で表すことができれば、
後はそれをコードに直すだけです。

まずは、数学の問題として(1), (2)を解くことから
始めるべきでしょうね。ここはCとは関係ないです。

>アルゴリズムを勉強すれば、発想力が鍛えられるかなぁ

基本的なコーディングを行う力は、アルゴリズムの勉強とは
別もの。

アルゴリズムの勉強は先人の卓越したアイデアそのものを
学ぶことがメインです。
    • good
    • 0
この回答へのお礼

回答有難うございます。

という事は、現段階でアルゴリズムを勉強する必要は無い、という事ですね、、、。

更に、数学の問題として、という事はやはり数学の勉強をするべきなのか、とも思えます。

やはり数学の件も含めて、この投稿を見せる事も含めて(僕が口で説明するだけでは不十分に思えるので)、母親と明日相談してみようと思います。

数度に渡りご教授頂き有難うございました。

お礼日時:2017/02/27 21:35

>著作権侵害の意図は有りません。


出典を明確にすれば、一部を引用するのは著作権違反には
なりません。

>読み込んだ整数の段数を持つ下向き数字ピラミッドを表示する
>プログラムを作れ、第i行目にはi % 10によって得られる
>数字を表示することという内容です。

これだけだとかなり足りないですね。
出力はひょっとしてこんなかんじ?

入力=5

00000
1111
222
33
4
    • good
    • 0
この回答へのお礼

回答有難うございます。

>出典を明確にすれば、一部を引用するのは著作権違反には
なりません。
教えて頂き有難うございます。

すいません、問題文が本当にそれだけです。出力例は図で表示されているのですが、、、。

出力は概ねそれで合ってます。
ですが、その左側も表示されている点と、5まで表示されている点が違います。

入力数:3だと
11111
*222
**3
(*の部分はスペースです。)

となる様です。

ちなみに本文にも書いて有るのですが、新・解きながら学ぶC言語(副読本の様な物でしょうか)に解答が掲載されているのですが、どうしてそうなるのかが分からないと言った有様です。

出典:新・明解C言語入門編P101

ちなみに回答はこう、です。

#include <stdio.h>

int main(void)
{
int i,j;
int h;

puts("下向き数字ピラミッドを作ります。");
printf("何段ですか?:");
scanf("%d",&h);

for( i = 1;i <= h;i++){
for(j = 1;j <= i - 1;j++)
putchar(' ');
for(j = 1;j <= 2 * (h - i) + 1;j++)
putchar("%d", i % 10);
putchar('¥n');
}
return 0;
}

出典:新・解きながら学ぶC言語P99問題4-29

お礼日時:2017/02/27 20:35

>入門書ってマスターしたら捨ててしまうもんなんですか、、、。


色々もってましたが石田本も含めて殆ど捨てましたね~。買ったのは
20~30年前だし(^-^;
K&Rの1EとANSI版だけリファレンスがわりにとってあります。
    • good
    • 0
この回答へのお礼

回答有難うございます。
おそらく私の父親母親と同年代の方とお見受け致しました。

そういうものなんだなぁ、という理解をしました。
見識を広めさせて頂き、有難うございます。

お礼日時:2017/02/27 20:14

>ですが、演習4-23,演習4-24,演習4-25が全く分かりません。


ここで回答するような人は入門書をもう持ってないでしょうから
この聞き方はまずいでしょうね。

面倒がらず、何がわからないか具体的に書いた方が
よいですよ。
    • good
    • 0
この回答へのお礼

回答有難うございます。

削除対象になるのを恐れて問題文を書きませんでした。
面倒臭がった訳ではないのですが、それではもう少し詳しく書いてみようと思います。
(補足機能で書けるでしょうか、、、。慣れてないので出来なかったらすいません。

というか、入門書ってマスターしたら捨ててしまうもんなんですか、、、。
なんか、目から鱗が落ちたような(誤用でしょうか。)気分です。
それでは、入門書で何が良いですか?とか、あなたはどういう入門書でどういう方法でマスターしたんですか?(気になっている部分です。今回質問はしていませんが。)という質問も余り意味を為さないかもしれませんね、、、。

重ねになりますが、ご指摘有難うございました。

お礼日時:2017/02/27 19:29

Cで続けろ、とまでは言っていないつもりでしたが



> 演習4-25のとあるfor文の条件式に、j <= 2 * (h - 1) + 1 と有りますが、条件式にこのような複雑(?)な式を打ち込むという発想が有りません。

当該書籍を持っていないので、どんな問題かわかりませんが、
同じ問題をRubyで解いたとしても、同じように「最大値が 2*(h-1)+1 になるようなループ」を書くことになるでしょう。

Rubyやっているうちに、わかるようになるかもしれませんが、必ずわかる、というものではありません。


プログラムにする前に、日本語で書く訓練をしてはどうでしょうか?


例えば、多重ループの例としてよくある
*
**
***
みたいなのは

1行目に * 1つ
2行目に * 2つ
...
i行目に * i個
...

 というのがあって、これから
「i行目に * i個」 を i=1から i<=nの間繰り返す
 がわかって
for( i=1; i<=n ; i++ ){
「i行目に * i個」
}
 と、ここまではただのforループです。

 ここで、外のforを消して
「i行目に * i個」
 だけ考えれば
「*を出力」を j=1からj<=i まで繰り返してから改行
  となって
for(j=1;j<=i;j++) {
printf("*") ;
}
printf("\n");
 になる、というのも、単純なforループですからわかりますよね?

 ここで、さっき消した外のforループを戻せば
for( i=1; i<=n ; i++ ){
 for(j=1;j<=i;j++) {
  printf("*") ;
 }
 printf("\n");
}
 と、二重ループになります。


できない問題も、上のように日本語で考えれば
「○○」を XXの間繰り返す
みたいな構造になっていて、その「○○」を分解すれば
「△△」をZZの間繰り返す
になっている、ということになるのでは。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
問題文を直接書くと削除対象となる、との事でしたので詳しく書けませんでした。
丁寧に有難うございます。
書いて頂いた文章を反芻して読んで、今後の学習に生かさせて頂こうと思います。
日本語で書く訓練、というのもしてみようと思います。

rubyの本ですと、プログラム全般に通じる話もある(知識を別の言語に置き換えて利用する事が出来る、らしいです。)という事で「プログラミング学習シリーズ Ruby 1 はじめてのプログラミング」という本が気になっています。


前回に引き続き、お世話になりました。有難うございます。

お礼日時:2017/02/27 10:53

この場合必要なのはC言語の理解ではなく、


命題を解くためのパターンを見つけ出してアルゴリズムに落とし込むための考え方でしょう。
ご提示の"演習4-25"の内容を知らないので、代わりに以下の命題で考えてみます。

命題: テキストでn段からなるピラミッドを描く

とりあえず n=5 と仮置きして、ピラミッドを構成する文字の個数を考えてみましょう。
今回はお絵かきなので、実際に書いてみると理解が早いです。
1段目: 4個の空白, 1個の文字 ____#
2段目: 3個の空白, 3個の文字 ___###
3段目: 2個の空白, 5個の文字 __#####
4段目: 1個の空白, 7個の文字 _#######
5段目: 0個の空白, 9個の文字 #########

どうやら個数は等差数列の式で計算できそうなので、以下のようにパターン化しましょう。
n段のピラミッド中でh段目の空白個数 = n - h
n段のピラミッド中でh段目の文字個数 = h + (h-1) = 2h - 1

パターンが見つかったで、アルゴリズムに落とし込みます。
h ← 1からnまで繰り返し {
_ n-h 回繰り返して、空白を表示
_ 2h-1 回繰り返して、文字を表示
_ 改行
}

ここまでくれば出来たも当然ですが、一応C言語で実装してみます。
for (h=1; h<=n; h++) {
_ for (j=1; j<=n-h; j++) { 空白を出力(); }
_ for (j=1; j<=2*h-1; j++) { 文字を出力(); }
_ 改行();
}

> 何か良い本を教えて頂ければ
パターンを見つけるには、ある程度の数学の教養が必要ですので、数学の教科書を読み返しましょう。
それに飽きたら数学パズルなどを解いてみましょう。
https://www.oreilly.co.jp/books/9784873116693/
    • good
    • 0
この回答へのお礼

回答ありがとうございます。
すいません、詳しく問題を写して書くと削除対象という事でしたので書けませんでした。
丁寧に有難うございます。
後ほど、自分でも紙に書いてみようと思います。

数学の教科書、まだ取ってあったでしょうか、、、。(1回り以上前に高校卒業済みです、、、。
等差数列という言葉も初めて聞くため、確かに勉強したほうがいい分野かもしれません。
母親に教科書が残ってるかどうか聞いてみます。
オススメの本、ありがとうございます。
今回、オススメして頂いた本に加えて、アルゴリズムが重要という事ですので、以前から気になっていた「C言語による最新アルゴリズム事典」も購入候補とさせて頂きたいと思います。

お礼日時:2017/02/27 10:40

For多重ループなんて、どの言語にも出てきますし、C言語に拘る必要はないのでは?



何でもいいから、とりあえず1つの言語をある程度使えるようになったほうが、他の言語を習得しやすいです。

ビット演算や再帰は使えると高速化、コード量を減らせますが、代替えコードはありますし、個人趣味でのプログラムならマストなスキルではありません。

まずは簡単なスクリプト言語(VBScriptやjavascript)を学んだほうが良いと思います
    • good
    • 0
この回答へのお礼

ありがとうございます。
参考にさせて頂きます。

お礼日時:2017/02/27 10:31

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!

このQ&Aと関連する良く見られている質問

Qしつこい様ですが、再度ポインタについて質問します。

下記は、*inの<title>から<と>で挟まれたtitle
を得るためのソースです。
全くの完全では有りませんが。質問の内容は、
while文の中で、コンパイラーが出すエラーメッセージの
内容が理解出来ません。

下記が出ます。
01.c: In function 'main':
01.c:12:17: warning: assignment makes pointer from integer without a cast [enabled by default]
while(strstr((p=(*out++ = *in++)),">") !=0);
^
while文の中でのエラーで、キャスト無しの整数からポインターを作っているので
strstrの最初の引数を飛ばしました(デフォルトで有効)無視しました。と言う意味ですが。

要はこれはポインターで無いのでstrstrの引数としては無効ですと言う事でしょうか。
それであれば、ここではポインターに変換しないといけませんが。

実はこれに関しては、前の質問でその方法と言うのは分かったのですが。どうしても、ここでは
将来の勉強と言う意味で理解をしたかった物ですから質問をしました。

このエラーメッセージが出ない様にするためにはソースのどこを変更
すれば良いのでしょうか。今度は、コードがどうのこうのではなくて
説明をお願いします。

よろしくお願いします。後学の為にどうしても理屈を知りたかった物ですから。
宜しくお願いします。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *in="<title>";

char work[256];
char *out=work;
char *p;

while(strstr((p=(*out++ = *in++)),">") !=0);
*out='\0';
printf("%s",work);

return 0;
}

下記は、*inの<title>から<と>で挟まれたtitle
を得るためのソースです。
全くの完全では有りませんが。質問の内容は、
while文の中で、コンパイラーが出すエラーメッセージの
内容が理解出来ません。

下記が出ます。
01.c: In function 'main':
01.c:12:17: warning: assignment makes pointer from integer without a cast [enabled by default]
while(strstr((p=(*out++ = *in++)),">") !=0);
^
while文の中でのエラーで、キャスト無しの整数からポイ...続きを読む

Aベストアンサー

No1です。
>これを作るに当ってのプログラム作成の問題は解決をしていますので。
>最後に今回の説明の回答で暴走すると言う所が気になっています。
>最後にこの暴走と言う所の質問の回答をお待ちしています。

これを以下のような部分を追加しました。
追加したしたのは、変数の内容を印字するだけなので、本来の動作には影響しません。
--------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *in="<title>";

char work[256];
char *out=work;
char *p;

printf("ascii code of(<)=%d\n",'<');
printf("in_size=%d out_sieze=%d\n",sizeof(in),sizeof(out));
printf("in=%x out=%x\n",in,out);

while(strstr((p=(char*)(int)(*out++ = *in++)),">") != 0);
*out='\0';
printf("%s",work);

return 0;
}
----------------------------------
これを実行すると、添付の図のようになります。
OSにより強制終了させられます。
このように強制終了させられる原因はいろいろありますが、今回は
ROM領域をアクセスしているのが原因と考えられます。
まず、pのあたいですが、"<"のアスキーコードの値:60が設定されます。
strstr(p,">")の意味は、60番地から">"の文字列が存在する箇所を探しなさい。
ということになります。60番地はROMの領域になるはずで、OSはこのような領域を一介のアプリプログラムが
アクセスすることを禁止しています。その為、強制終了させられます。(これが暴走の意味です)
通常、pは、アプリケーションプログラムが確保した領域のアドレスが設定されるはずで、
inのアドレスが設定されるなら、添付の図のように403064(16進数)のような値になるはずです。

No1です。
>これを作るに当ってのプログラム作成の問題は解決をしていますので。
>最後に今回の説明の回答で暴走すると言う所が気になっています。
>最後にこの暴走と言う所の質問の回答をお待ちしています。

これを以下のような部分を追加しました。
追加したしたのは、変数の内容を印字するだけなので、本来の動作には影響しません。
--------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *in="<title>";

char work[256];
char *out=wo...続きを読む

QC言語のポインターで詰まっている

下記が動かない。多分に、ポインターがおかしいと思うが。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *buf="<title>sample</title>";
char work[256];
char p;

char *out=work;
char *in=buf;

in=strstr(in,"<");
while(strcmp((p=(*out++ = *in++)),"sample") != 0);
printf("%c",p);

//while(strcmp((*out++=*in++),">") != 0);
*out='\0';
printf("%s\n",out);
return 0;
}
01.c: In function 'main':
01.c:14:2: warning: passing argument 1 of 'strcmp' makes pointer from integer without a cast [enabled by default]
while(strcmp((p=(*out++ = *in++)),"sample") != 0);
^
In file included from 01.c:3:0:
c:\mingw\include\string.h:43:37: note: expected 'const char *' but argument is of type 'char'
_CRTIMP int __cdecl __MINGW_NOTHROW strcmp (const char*, const char*) __MINGW_ATTRIB_PURE;

済みません。指摘をお願いします。

下記が動かない。多分に、ポインターがおかしいと思うが。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *buf="<title>sample</title>";
char work[256];
char p;

char *out=work;
char *in=buf;

in=strstr(in,"<");
while(strcmp((p=(*out++ = *in++)),"sample") != 0);
printf("%c",p);

//while(strcmp((*out++=*in++),">") != 0);
*out='\0';
printf("%s\n",out);
return 0;
}
01.c: In function 'main':
01.c:14:2: warning: pass...続きを読む

Aベストアンサー

No.3です。
No.4の方へのお礼を拝見しました。

まず、strcmp()というのは、第1引数のポインタから始まる文字列と第2引数のポインタから始まる文字列とを比較し、一致する場合には0を、そうでない場合には0以外を返す関数です。ちなみに、文字列は最後の'\0'までをすべて比較しますので、これでは永遠に一致しません。この場合、strncmp()という、文字数を制限した比較関数を使います。
例:if (strncmp(start, "title", 5) == 0) { ...

>それならば、ポインターに型変換をする事は出来ないのでしょうか。

Cでは他のスクリプト言語と比べ、変数の表記、とりわけポインタが絡んだ場合にちょっと違う記法になります。

宣言の時:
char *a;

ポインタ(アドレス)として利用する場合:
strncmp(a, "title", 5);

ポインタで示される値を参照する場合:
printf("%c", *a);
→printf("%c", a[0]);と同じ動きになる

質問者様はおそらくこのあたりを混乱されているのだと思います。

>while(strcmp((p=(*out++ = *in++)),"title") != 0);

雰囲気的には、1行でこれを表現しようとしているのでしょうが、こういうことをするぐらいなら普通にブロックで書いた方が分かりやすいです。
while (strncmp(in, "title", 5) != 0) {
*out ++ = *in ++;
}
CはPerlと違い、行数が計算コストになるわけではありません。コンパイラが良しなに最適化してくれます。

さらにちなみにですが、大文字小文字を区別しない場合は、strncasecmp()という関数もあります。必要に応じて活用されればよいと思います。

これでお望みの回答になるのではないでしょうか?

No.3です。
No.4の方へのお礼を拝見しました。

まず、strcmp()というのは、第1引数のポインタから始まる文字列と第2引数のポインタから始まる文字列とを比較し、一致する場合には0を、そうでない場合には0以外を返す関数です。ちなみに、文字列は最後の'\0'までをすべて比較しますので、これでは永遠に一致しません。この場合、strncmp()という、文字数を制限した比較関数を使います。
例:if (strncmp(start, "title", 5) == 0) { ...

>それならば、ポインターに型変換をする事は出来ないのでしょうか。

Cでは...続きを読む

QC言語で詰まっているので教えて下さい。

下記のソースが有ります。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
FILE *fp, *fp2;
char buf[64000];
char *p, *start ,*q ,*r;
char file_name[]="out/";
int ret;

// result.txtのopen error処理 {{{
fp=fopen("result.txt","r");
if(fp == NULL){
printf("result.txt file open err\n");
return 1;
}
// }}}
// fgetsでのエラー処理 {{{
if(fgets(buf,64000,fp) == NULL){
printf("data error\n");
return 1;
}
// }}}
// <target>が存在しない時のエラー処理 {{{
p=strstr(buf,"<target>");
if(p == NULL){
printf("target not found\n");
exit(1);
}
// }}}

// 最初のファイル名の取得{{{
p=p+strlen("<target>");
q=p;

p=strstr(p,"</target>");
if(p == NULL){
printf("</target> not found\n");
exit(1);
}
*p='\0';
strcat(file_name,q);
// }}}

// 出力ファイルのopen処理 {{{
fp2=fopen(file_name,"w");
if(fp2 == NULL){
printf("%s file open err\n",file_name);
exit(1);
}
// }}}
while(fgets(buf,64000,fp) != NULL){
p=strstr(buf,"<target>");
if(p == NULL){
fprintf(fp2,"%s",buf);
}else{
// 2回目以降のファイル名の取得{{{
p=p+strlen("<target>");
q=p;

p=strstr(p,"</target>");
if(p == NULL){
printf("</target> not found\n");
exit(1);
}
*p='\0';
strcat(file_name,q);
// }}}
// 今使っているファイルを閉じて新しいファイルを開く。{{{
fclose(fp2);

fp2=fopen(file_name,"w");
if(fp2 == NULL){
printf("%s file open err\n",file_name);
exit(1);
} // }}}
}
}
fclose(fp);
fclose(fp2);
return 0;
}

// vim:set fdm=marker:

入力は、result.txtを読んでそれをフィルターする物です。result.txt
は先頭から順に下記の内容で入力されています。

① <target>ファイル名</target>
② 内容のデータ

上記の①から②を繰り返します。フィルターは①のファイル名で続く
データをそのファイルに出力します。フィルターの数は約1万件にな
る。

処理の内容は、最初の<target>の行を読んで出力ファイルをオープンし
ます。続くデータを<target>行が来る迄出力を続行します。

新しく<target>行が来るとこれ迄使っていた出力ファイルを閉じてまた
新規のファイルを出力としてオープンします。

この処理をresult.txtを最後迄読んだら終了となります。今の問題は、
この処理の中で最初の出力ファイルに出力をしている途中で異常終了し
ます。

何処が不味いのか。検討が付きません。どうか助けて下さい。宜しくお
願いします。

下記のソースが有ります。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
FILE *fp, *fp2;
char buf[64000];
char *p, *start ,*q ,*r;
char file_name[]="out/";
int ret;

// result.txtのopen error処理 {{{
fp=fopen("result.txt","r");
if(fp == NULL){
printf("result.txt file open err\n");
return 1;
}
// }}}
// fgetsでのエラー処理 {{{
if(fgets(buf,64000,fp) == NULL){
printf("data error\n");
return 1;
}
// }}}
/...続きを読む

Aベストアンサー

以下のようにしてください。
修正した箇所と、追加した箇所に//変更、//追加のコメントを入れておきました。
-------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
FILE *fp, *fp2;
char buf[64000];
char *p, *start ,*q ,*r;
char file_name_base[]="out/"; //変更
char file_name[256]; //追加
int ret;

// result.txtのopen error処理 {{{
fp=fopen("result.txt","r");
if(fp == NULL){
printf("result.txt file open err\n");
return 1;
}
// }}}
// fgetsでのエラー処理 {{{
if(fgets(buf,64000,fp) == NULL){
printf("data error\n");
return 1;
}
// }}}
// <target>が存在しない時のエラー処理 {{{
p=strstr(buf,"<target>");
if(p == NULL){
printf("target not found\n");
exit(1);
}
// }}}

// 最初のファイル名の取得{{{
p=p+strlen("<target>");
q=p;

p=strstr(p,"</target>");
if(p == NULL){
printf("</target> not found\n");
exit(1);
}
*p='\0';
strcpy(file_name,file_name_base); //追加
strcat(file_name,q);
// }}}

// 出力ファイルのopen処理 {{{
fp2=fopen(file_name,"w");
if(fp2 == NULL){
printf("%s file open err\n",file_name);
exit(1);
}
// }}}
while(fgets(buf,64000,fp) != NULL){
p=strstr(buf,"<target>");
if(p == NULL){
fprintf(fp2,"%s",buf);
}else{
// 2回目以降のファイル名の取得{{{
p=p+strlen("<target>");
q=p;

p=strstr(p,"</target>");
if(p == NULL){
printf("</target> not found\n");
exit(1);
}
*p='\0';
strcpy(file_name,file_name_base); //追加
strcat(file_name,q);
// }}}
// 今使っているファイルを閉じて新しいファイルを開く。{{{
fclose(fp2);

fp2=fopen(file_name,"w");
if(fp2 == NULL){
printf("%s file open err\n",file_name);
exit(1);
} // }}}
}
}
fclose(fp);
fclose(fp2);
return 0;
}
----------------------------------------------------
誤りは2点です。
1)strcat(file_name,q);
file_nameは"out/"が格納できるサイズしか確保されません。
その為、これを実行すると、確保したサイズ以降の領域が破壊されます。
どこが、破壊されるかは、コンパイラの配置によってきまるので、わかりませんが、どこかが破壊されます。
2)2回目のstrcat(file_name,q);を実行すると
前に実行した残骸のあとから更に文字列が追加されます。

上記を解決するためには
char file_name_base[]="out/"; //変更
char file_name[256]; //追加
を確保し、
一旦、
①file_name_baseをfile_nameにコピーし、
②その後で、strcat(file_name,q);
を実行します。
①②は、必ずペアで実行します。
尚、file_nameは暫定的に256バイトにしましたが、もっとファイル名として大きな文字列が存在するなら
もっと大きくしてください。

以下のようにしてください。
修正した箇所と、追加した箇所に//変更、//追加のコメントを入れておきました。
-------------------------------------
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(){
FILE *fp, *fp2;
char buf[64000];
char *p, *start ,*q ,*r;
char file_name_base[]="out/"; //変更
char file_name[256]; //追加
int ret;

// result.txtのopen error処理 {{{
fp=fopen("result.txt","r");
if(fp == NULL){
printf("result.txt file open err\n...続きを読む

QCのプログラムに無性にイライラするのはおかしいですか?

CQ出版のインタフェース 2017-5 の記事のプログラム例に
for( i=0; i<256; i++){
 for( y =0; y < Y; y++ ){
  for( x = 0; x < X; x++){
   p[0] = img -> imageData[img->widthStep* y + x*3 ]; //B(青色)
   if(p[0]==i){hn[i]++;}
  }
 }
}
がありました。このリストを見て、無性にイライラするのは私だけでしょうか?

なぜ、i,y,x の3重のループで処理しないといけないのか、y,xの2重ループで十分ではないかと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  hn[ p[0] ]++;
 }
}

3重にするならせめて、y,x,i の順にしてp[0]への代入は1回で済ませればと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++){
  p[0] = img -> imageData[img->widthStep* y + x*3 ];  //B(青色)
  for( i=0; i<256; i++){
     if(p[0]==i){hn[i]++;}
  }
 }
}

最近のコンパイラの最適化では、私の書いたようなコーディング(修正?)は無意味なのでしょうか?

CQ出版のインタフェース 2017-5 の記事のプログラム例に
for( i=0; i<256; i++){
 for( y =0; y < Y; y++ ){
  for( x = 0; x < X; x++){
   p[0] = img -> imageData[img->widthStep* y + x*3 ]; //B(青色)
   if(p[0]==i){hn[i]++;}
  }
 }
}
がありました。このリストを見て、無性にイライラするのは私だけでしょうか?

なぜ、i,y,x の3重のループで処理しないといけないのか、y,xの2重ループで十分ではないかと思います。

for( y =0; y < Y; y++ ){
 for( x = 0; x < X; x++)...続きを読む

Aベストアンサー

利点を考えてみました


これを並列処理したときに
スレッド0: hn[0] に p[0] = 0 をカウント
スレッド1: hn[1] に p[0] = 1 をカウント
...
とすれば、
・img -> imageData は読み出すだけなので衝突しない
・hn[i] でアクセスする領域は、スレッド毎に i が違うので、同じ箇所に書き込まれることはない。
となり、排他処理が不要となります。
(もちろん、x,y,i,p[0]はスレッドでローカルな変数とします)

ただ、並列処理のオーバーヘッドや同時並列処理数等を考えると、こんな並列処理はしない方が効率的です。


あるいは、hn[]がシークに時間がかかる領域の場合、
hn[p[0]) で毎回違う位置を探しに行って、その時間が無視できないほどだったら、
先にhnを決めてしまった方が速くなるでしょう。

こちらも、非現実的です。

QC言語の漢字のホルダーは、chdirでは変更出来ないのだろうか。

下記のソースでは、ホルダーが漢字で無い時は成功するが。
漢字を使うと失敗する。

下記に成功する場合を示す。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

int main(){
char *dir1="C:/Users/usui/mingw";
int ret;

ret=chdir(dir1);
printf("%d\n",ret);
}
上記は、漢字を使っていないので結果は0を表示する。
然し、ホルダーに漢字を使うと-1を表示する。

漢字のホルダーを使う方法をお知えて下さい。
宜しくお願いします。

Aベストアンサー

No3です。
ちなみに私がインストールした(今使っているバージョン)のは、下記URLの
mingw-get-inst-20120426.exe です。
https://sourceforge.net/projects/mingw/files/OldFiles/mingw-get-inst/mingw-get-inst-20120426/

QC言語でのUTF-8の文字列の処理は例えば、比較とかstrtokとかはどうするのか

大量のhtmlファイルを処理をする様になってから今迄はperlを使って来
たが処理が遅いのでC言語を使って早くしようと思って要るが。肝心の
日本語コードの扱いで詰まっている。

例えば、
<!--コメントヘッダーのはじまり-->
.
.
.
<!--コメントヘッダーのおわり-->
と言った場合に、<と>に囲まれた色んなタグが現れて来る。strtokで文
字列を拾って対処をするとしても、文字コードが処理出来なければ何も
進まない。

例えば、上記の場合でhtmlファイルを読んでコメントヘッダーのはじまり
とおわり迄に関しては、出力をしない。他のは全て出力すると言う様な場
合のC言語のソースはどの様に成るのでしょうか。

済みません。未だ、始めたばかりでC言語での記述が出来ません。宜し
く回答願います。

回答はヒントでは無くて直接のC言語のソースを提示願います。宜しく
お願いします。

Aベストアンサー

>回答はヒントでは無くて直接のC言語のソースを提示願います。

これがほしければ、もうちょっと具体的な入出力についての説明が必要です。

ヒントレベルになりますが、状態変数を使って、
状態1:コメント外・・・strstr()などを使って"<!--"を探し、そこまでを出力→状態2へ
状態2:コメント内・・・strstr()などを使って"-->"を探し、その一つ右へポインタを進める→状態1へ
これをHTMLの最後まで繰り返します。

ファイルの中身をすべていったんメモリに持つなら'\0'を見つけるまで繰り返すだけです。限られたバッファでやりくりしようとするなら(ネットワークからダウンロードしながら処理する際にはこのやり方が必須)、バッファ読み込みの際のタグ文字列の泣き別れなどを考慮する必要がありちょっと凝ったテクニックが必要になります。

それとも、UTF-8で書かれたHTMLの"<!--コメントヘッダーのはじまり-->"~"<!--コメントヘッダーのおわり-->"を全削除ですか?だったら、コードをUTF-8で書いて、strstr()で"<!--コメントヘッダーのはじまり-->”を見つけて・・・でいけると思います。文字コードの処理というよりか、見る人が見れば日本語に見えるかもしれない「ただのデータの列」とみなして処理するだけです。

>回答はヒントでは無くて直接のC言語のソースを提示願います。

これがほしければ、もうちょっと具体的な入出力についての説明が必要です。

ヒントレベルになりますが、状態変数を使って、
状態1:コメント外・・・strstr()などを使って"<!--"を探し、そこまでを出力→状態2へ
状態2:コメント内・・・strstr()などを使って"-->"を探し、その一つ右へポインタを進める→状態1へ
これをHTMLの最後まで繰り返します。

ファイルの中身をすべていったんメモリに持つなら'\0'を見つけるまで繰り返すだけです。限られた...続きを読む

Qc言語です。puts関数を使って縦に 風 林 火 山 を表示したいんですけど、 風 林火山 になりま

c言語です。puts関数を使って縦に





を表示したいんですけど、

林火山
になります プログラム教えてください( ・ω・)

Aベストアンサー

林と火(と山)の後に \n (改行コード)を付けてないのでは?

QC言語のうるう年に関するプログラムの作成

C言語(閏年)の質問です。

任意の範囲の年から閏年の表示とその数をカウントして次の実行結果のように表示するプログラムの作成方法を教えてください。(ここでは2つの年をmain関数内で入力し、その範囲の西暦を引数とする関数checkYearを使用するものとする。int型の関数checkYearは、引数に西暦をとり、その西暦が閏年であれば、1を返し、閏年でない場合は0を返す。)
なお、閏年の判定方法は以下のとおりである。
条件1 西暦年が4で割り切れる年は閏年である
条件2 条件1を満たしていても、西暦年が100で割り切れるときは閏年でない
条件3 条件2を満たしていても、西暦年が400で割り切れるならば閏年である

実行例1
西暦を入力:2000
西暦を入力:2009
2000年
2004年
2008年
閏年は3回あります。

実行例2
西暦を入力:2100
西暦を入力:2000
2000年
2004年
2008年
2012年
2016年
2020年
(省略)
2096年
閏年は25回あります。

実行例3
西暦を入力:2090
西暦を入力:2110
2092年
2096年
2104年
2108年
閏年は4回あります。

C言語(閏年)の質問です。

任意の範囲の年から閏年の表示とその数をカウントして次の実行結果のように表示するプログラムの作成方法を教えてください。(ここでは2つの年をmain関数内で入力し、その範囲の西暦を引数とする関数checkYearを使用するものとする。int型の関数checkYearは、引数に西暦をとり、その西暦が閏年であれば、1を返し、閏年でない場合は0を返す。)
なお、閏年の判定方法は以下のとおりである。
条件1 西暦年が4で割り切れる年は閏年である
条件2 条件1を満たしていても、西暦年が10...続きを読む

Aベストアンサー

こんな感じでしょうか。
(体裁上、各行先頭のスペースは全角スペースにしてあるので、コピペするとコンパイルできないと思います)

#include <stdio.h>

static int
checkYear (int year)
{
 if ((year % 4) == 0)
 {
  if ((year % 100) == 0)
  {
   if ((year % 400) == 0)
    return (1);
  }
  else
   return (1);
 }

 return (0);
}

int
main (int argc, char * argv[])
{
 int count = 0;
 int year, start, end;

 printf ("西暦を入力:");
 scanf ("%d", &start);
 printf ("西暦を入力:");
 scanf ("%d", &end);

 if (start > end)
 {
  year = end;
  end = start;
  start = year;
 }

 for (year = start; year <= end; year++)
 {
  if (checkYear (year) == 1)
  {
   printf ("%d年\n", year);
   count++;
  }
 }
 if (count != 0)
  printf ("閏年は%d回あります。\n", count);
 else
  printf ("閏年はありません。\n");

 return;
}

こんな感じでしょうか。
(体裁上、各行先頭のスペースは全角スペースにしてあるので、コピペするとコンパイルできないと思います)

#include <stdio.h>

static int
checkYear (int year)
{
 if ((year % 4) == 0)
 {
  if ((year % 100) == 0)
  {
   if ((year % 400) == 0)
    return (1);
  }
  else
   return (1);
 }

 return (0);
}

int
main (int argc, char * argv[])
{
 int count = 0;
 int year, start, end;

 printf ("西暦を入力:");
 scanf ("%d", &start);
 print...続きを読む

QC言語でポインターで詰まっています。

下記は、文字化けします。
多分にポインターの定義で不味いのかなと思いますが。
指摘を願います。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
char *in="abc";
char *out;
while(*out++ = *in++);
printf("%s\n",out);
return 1;
}

Aベストアンサー

No5です。
>char *out=outbufの所を、out=outbuf
>にすると言うのは、具体的にどこが
>どう違うのでしょうか。

これは、
char *out = outbuf;・・・・①

char out = outbuf;・・・・②
としたと理解しました。
①は、 char *out なので、outはchar へのポインターです。
②は、char out なので、outはchar型の1バイトのデータです。

①は
char *data;
data = outbuf;
とおなじです。

②は
char data;
data = outbuf;・・・③
ここで、③はchar型のデータにポインター型のデータを格納しようとしているのでエラーになります。

ほかのエラーも同様にdataがchar型であることに起因したエラーです。

QC言語の簡単なプログラムの相談です

プログラミング初心者です。
getcharが使えなくて
困っています。
下記プログラムに"#define putchar(c) putc(c, stdout)"と”#define getchar( ) getc(stdin)”も加えたりしているのですが、結果"。"や"1"などがでてきます。(下はサンプルプログラムです)
どなたか、ご教授よろしくお願いします。





#include <stdio.h>

void main(void);

void main(void)
{
int c;

for (c = 'A'; c <= 'Z'; c++) /* c の値は 'A' から 'Z' まで変化 */
putchar(c); /* 1文字画面に出力 */

printf("\n");

for (c = 'Z'; c >= 'A'; c--) /* c の値は 'Z' から 'A' まで変化 */
putchar(c); /* 1文字画面に出力 */

printf("\n\n");

printf("アルファベットを入力して下さい\n");
printf("eを入力するとループからぬけます\t");

while ((c = getchar( )) != EOF) { /* 文字の入力 */
putchar(c);
if (c == 'e') /* 入力された文字が 'e' なら */
break; /* ループから抜ける */
}
}

プログラミング初心者です。
getcharが使えなくて
困っています。
下記プログラムに"#define putchar(c) putc(c, stdout)"と”#define getchar( ) getc(stdin)”も加えたりしているのですが、結果"。"や"1"などがでてきます。(下はサンプルプログラムです)
どなたか、ご教授よろしくお願いします。





#include <stdio.h>

void main(void);

void main(void)
{
int c;

for (c = 'A'; c <= 'Z'; c++) /* c の値は 'A' から 'Z' まで変化 */
putchar(c); ...続きを読む

Aベストアンサー

#Codeが
https://www.microsoft.com/ja-jp/store/p/code/9nblggh4s3mf
これだとすると

> #Code is an online compiler

ってあるから、最近流行りの paizaとかideoneとかみたいな感じなのではないでしょうか。
だとすると、入力は、通常のオフラインでの実行とは違っていても不思議ではありません。


人気Q&Aランキング