ページ 11

無題

Posted: 2008年12月09日(火) 14:20
by 化学系
さっぱりわからないのでどうかお助けください

実行例
入力された整数の各桁の和が0の倍数になるように1桁の数を付け加えます。
6桁の数を入力してください:071501
各桁の和:14
付け加える数字:6
得られた数:0715016

どうかお願いします

Re:無題

Posted: 2008年12月09日(火) 14:25
by Dixq (管理人)
C言語についてどの位現在理解されていますか?
情報系は習った事が無く、単に実験データを計算したいだけということでしょうか?
あと、時間のあるとき規約読んでもらえるとありがたいです。

Re:無題

Posted: 2008年12月09日(火) 15:13
by non
スレッド「C言語の因数分解」のioioさんとは別の学校の方でしょうか。
なぜかと言いますと、
桁数が指定してあって、桁数を揃えるために、先頭に0がついてます。
例として使われている数値も似通ってるし・・・
こんなのが流行っているのですか?
別に、他意はありませんけど。

Re:無題

Posted: 2008年12月09日(火) 17:15
by non
例外処理はこんな使い方でいいでしょうか?
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;

class Num{
	int n[7];
public:
	void set(string);
	void disp(void);
};

void Num::set(string str)
{
	int i,q=0;
	for(i=0;i<6;i++){
		n=str-'0';
		q+=n;
	}
	q%=10;
	n[6]=(q)?10-q:0;
}
void Num::disp(void)
{
	int i;
	for(i=0;i<7;i++)
		cout << n;
	cout << endl;

}	
string cinStr(void)
{
	string str;
	try{
		cout << "6桁の数を入力してください:";
		cin >> str;
		if(str.size()!=6)
			throw "ERROR";
		for(int i=0;i<6;i++)
			if(!isdigit(str))
				throw i;
	}
	catch(char *){
		cout << "6桁入力のこと" << endl;
		throw "";
	}
	catch(int){
		cout << "数字以外が入力されてます" << endl;
		throw "";
	}
	return str;
}
int main(void)
{
	Num num;
	string str;
	try{ str=cinStr();}
	catch(char *){
		cout << "入力エラー" << endl;
		return 0;
	}

	num.set(str);
	num.disp();
	return 0;
}

Re:無題

Posted: 2008年12月09日(火) 19:00
by s-rush
さっぱりわからないではなく、せめてどのように処理をすれば
自分の望む結果が得られるかくらいは考えましょう。

考え方の一例
3桁の数で考えてみましょう。
たとえば入力された数が987だった場合、
 987=9×100+8×10+7×1
になりますよね?

入力された値から、上記の式の右辺の係数に当たる数値を計算でそれぞれ取り出すこと処理を考えます。
計算例
987÷10の余り:7   商:98
98÷10の余り :8   商:9
9÷10の余り:9   商:0

一応この計算で係数に当たる数値を求めることができます。
(少し考えてもらうために説明を多少省略していますが、分かりますよね?)

あとは入れる数値ですが、これは自分で考えてみてください。
上の計算法でも入れる数値を求めることができるので、
この求め方を関数化してしまってもいいかもしれませんね。



P.S Dixq さんへ
新入りなのに出しゃばったマネをしてすいません。
まだまだ未熟者ですが、できる範囲でお手伝いしていきます。

Re:無題

Posted: 2008年12月09日(火) 19:12
by Dixq (管理人)
>s-rushさん

いえいえ、とんでもないです。ご回答くださりありがとうございます。

>化学系さん

どうもioioさんと同じ問題のようです。

Re:無題

Posted: 2008年12月09日(火) 22:46
by 組木紙織
No:25405 nonさんへ返信

例外処理を使う場所は良いと思いますが実装法にちょっと問題があるのかな。
以下私が気になる部分です。


配列を即値で扱っているのが気になります。enumでもつかったらどうでしょうか。
例外は例外クラスを利用して投げるようにしてください。
変数の定義位置は定義と同時に初期化できるのが理想です。(実際にはなかなか難しいですが。)
変数が必要になったら宣言してください。 

Re:無題

Posted: 2008年12月09日(火) 22:57
by conio
「さっぱり分からない、全然分からない、全く分からない」
「どうかお願いします」

んー最近このようなコメントが多いような。
"さっぱり分からない"のはこちらの方です。

とりあえず、考え方としてはs-rushさんの通り、割った余りを利用すればいいでしょう。

-------------------------------------------------------------------
①余りを順次、適当な変数(sumなど)に足して行く。
②足したもの(sum)の下位桁を求める。(54なら4、15なら5、123なら3,)
③"● - 下位桁"で、付け加える値を求める。
④最初の整数にある処理を行い、最後に付け加える値を足す。
(071501にある処理を施したもの)+ 6 = 715016
-------------------------------------------------------------------

回答はあえて抽象的にしました。虫食いのところは考えて埋めてください。

Re:無題

Posted: 2008年12月10日(水) 00:06
by たかぎ
> 0の倍数になるように

確かにさっぱり分かりません。

Re:無題

Posted: 2008年12月10日(水) 00:13
by たかぎ
> nonさん
> 例外処理はこんな使い方でいいでしょうか?

入力された数値の整合性判定の結果として例外を送出するのは、あまり望ましくないと思います。
C++の例外は非常に重いので、普通は発生しないような事象に限定して用いた方がよいでしょう。

Re:無題

Posted: 2008年12月10日(水) 00:25
by s-rush
>たかぎさん
確かにおかしいですよね。
もう少し書きようがあると思います。
まぁたぶんこれは各桁の値を合計して、その値が10の倍数になるように、
ではないでしょうか?
私の勝手な解釈で計算法を示したんですけど、
意味のとり違いであれば、元も子もないですけど。

>化学系さん
少し補足しておきます。
nonさんのおっしゃる通り、例外処理も考えておいた方がいいと思います。
私はC++は勉強中なので、コードの意味はよくわかりませんが、
・入力した値が6桁出ない場合
・入力した値が数字でない場合(例えば文字や記号)
少なくともこの2つの例外くらいは実装しておいた方がいいでしょう。

ifやcaseを使えばできると思います。

Re:無題

Posted: 2008年12月10日(水) 01:14
by たかぎ
10の倍数になるように、という解釈で作ってみました。
処理系不明なので、可能な限り規格厳密合致プログラムを目指しましたが、古い規格に準拠した処理系は無視しています。
%:include <ctype.h>
%:include <stdio.h>
%:include <stdlib.h>

int main(void)
<%
  fputs("6??/u6841??/u306e??/u6570??/u3092??/u5165??/u529b??/u3057??/u3066??/u304f??/u3060??/u3055??/u3044:", stdout);
  fflush(stdout);

  char s<:6+1:>, lf;
  if (scanf("%6??(0123456789??)%c", s, &lf) != 2 ??!??! lf != '??/n')
    goto error;

  int sum = 0;
  for (int i = 0; i < 6; i++)
  <%
    if (!isdigit((unsigned char)s<:i:>))
      goto error;
    sum += s<:i:> - '0';
  %>
  printf("??/u5404??/u6841??/u306e??/u548c:%d??/n", sum);
  int mod = sum % 10;
  int d = mod == 0 ? 0 : 10 - mod;
  printf("??/u4ed8??/u3051??/u52a0??/u3048??/u308b??/u6570??/u5b57:%d??/n", d);
  printf("??/u5f97??/u3089??/u308c??/u305f??/u6570:%s%d??/n", s, d);

  return EXIT_SUCCESS;

error:
  fputs("??/u30c0??/u30e1??/uff01??/n", stderr);
  return EXIT_FAILURE;
%>
[/url]や{}が入力できない環境のことも考慮しています。

Re:無題

Posted: 2008年12月10日(水) 12:37
by non
組木紙織さん

>配列を即値で扱っているのが気になります。enumでもつかったらどうでしょうか。

#defineでなくenumですか?具体的にどうすればいいのでしょうか。ご面倒でしょうが
お教えください。
exceptionクラスについては、もう少し勉強します。

たかぎさん

>入力された数値の整合性判定の結果として例外を送出するのは、あまり望ましくないと思います。
>C++の例外は非常に重いので、普通は発生しないような事象に限定して用いた方がよいでしょう。

了解しました。
いろいろ調べると、重たいと書いてありますね。本当に必要な機能なのか、まだ理解出来ておりません。
上のたかぎさんのプログラムはさっぱりわかりません。まだまだ、道遠しですね。

Re:無題

Posted: 2008年12月10日(水) 13:07
by toyo
>>nonさん
??/
みたいなのをtrigraphといいます
??/は\(バックスラッシュ)と同じ意味になります
キーボードから打ち込めない記号があるときに使えます

%:や<%は始めて見ました
調べてみたらdigraphですか
いろいろありますね

Re:無題

Posted: 2008年12月10日(水) 13:20
by non
toyoさん
まだ、中身を調べるところまで到ってません。
それより、コンパイルするのにパラメータが必要なのかと思いますが、どうすればいいんでしょ。
普通にやるとエラーがでるし。

Re:無題

Posted: 2008年12月10日(水) 14:01
by たかぎ
> 上のたかぎさんのプログラムはさっぱりわかりません。まだまだ、道遠しですね。

なぜこんな変なことをしているかというと、処理系を明確にすることが如何に大切かを分かってもらうためです。

> それより、コンパイルするのにパラメータが必要なのかと思いますが、どうすればいいんでしょ。

例えばGCCであれば、-std=c99または-std=gnu99オプションを付ければコンパイルできます。
文字コード不明ですので文字列は国際文字名表記になっています。環境がUTF-8でなければ-fexec-charsetオプションも併用してください。
具体的には、CygwinやMinGWであれば-fexec-charset=cp932を指定してください。

Re:無題

Posted: 2008年12月10日(水) 14:35
by non
gccで無事にコンパイルできました。

Re:無題

Posted: 2008年12月10日(水) 23:57
by 組木紙織
nonさん
>#defineでなくenumですか?具体的にどうすればいいのでしょうか。ご面倒でしょうが
お教えください。

#defineだと色々問題が多いからね。
C++だと以下のほうがよいかな。
class Num{
	enum{arraySize=7};//こっちか
//	const static unsigned int arraySize =7;こっちでもよい
	int n[arraySize];
public:
	void set(string);
	void disp(void);
};
例外は欲しいクラスを例外クラスの階層に入れてあげればよいだけです。

Re:無題

Posted: 2008年12月11日(木) 08:20
by Dixq (管理人)
トライグラフ
http://www.ncos.co.jp/products/cgi-bin/e000.cgi?64

コメントアウトした行でも、文字列の中でも通用するので

#include <stdio.h>

int main(){
	int i=0; //0が入る
	i++; // ++って何??/
	i++; 
	printf("答えは??=%d",i);
	return 0;
}

実行結果

答えは#1

安易に使うと危ない(知らない人が読んだら誤解する可能性がある)のと、
知らないうちに書いてしまってることがあるので、
(上の例でいうと、書いた人はiは2であり、#なんか書いた覚えが無いとか)
バグ回避の為、私はクエッションマーク2連続は意識してかかないようにしています。

昔Justyさんにこのバグで苦労したと話をお聞きしたことがありました。
ただ、VisualC++2008でコンパイルしてみたところ
「warning C4010: 単一行コメント (//) に、行連結文字があります。」
と警告してくれましたからコンパイラによっては簡単に見つけられるかもしれませんね。

Re:無題

Posted: 2008年12月11日(木) 09:40
by non
組木紙織さん

enumの件ありがとうございます。
>enum{arraySize=7};
のarraySizeをメンバー関数内で使うのはいいのですが、外で使いたい場合、
これをpublicにしてもいいのでしょうか?
それとも、その数を出力するようなメンバー関数を作って使うようにすべきでしょうか?
たぶん後者だとは思うのですが、どうされてますか?

Re:無題

Posted: 2008年12月11日(木) 10:41
by たかぎ
> これをpublicにしてもいいのでしょうか?
> それとも、その数を出力するようなメンバー関数を作って使うようにすべきでしょうか?

これはpublicでかまいません。
もちろん、クラスの中でしか使う必要がないなら、privateやprotectedにしてもよいでしょう。

Re:無題

Posted: 2008年12月11日(木) 11:00
by non
たかぎさん

>これはpublicでかまいません。

そうですか。了解です。