はじめまして.

以下の問題を解くために自分でプログラムを書きました.


【 問題 】

******************************************************

図書館の目録管理用に,cardというクラスを作成せよ.
このクラスに本のタイトルと著者,在庫数を格納します.
タイトルと著者を文字列として保存し,在庫数を整数として保存します.
store()という公開メンバ関数を使用して本情報を保存し,
show()という公開メンバ関数により保存したデータを表示せよ.

******************************************************

しかしわからない点が1つあります.
メンバ関数のstoreに文字列を渡すにはどうしたらよいでしょうか??

なお計算機環境は,VC++ver6.0をインストール済みのWin2000です.
また,VCではWin32コンソールアプリケーションを利用して
以下のコードを書いています.

ご指導お願いします.



#include <iostream>
using namespace std; // 名前空間.

// クラスcardの定義.
class card {
char title;
char author;
int num;

// 公開メンバ関数のプロトタイプ.
public:
void store(char title_name, char author_name, int zaiko_num);
void show();

};

// メンバ関数の定義.
// データ記録用.
void card::store(char title_name, char author_name, int zaiko_num)
{
title = title_name;
author = author_name;
num = zaiko_num;
}

// メンバ関数の定義.
// データ表示用.
void card::show()
{
cout << title << endl;
cout << author << endl;
cout << num << endl;
};


int main(int argc, char* argv[])
{

// クラスオブジェクトの作成.
card cd;

// メンバ関数の参照.
cd.store('C','U',20);
cd.show();

return 0;
}

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

A 回答 (3件)

> となるのですか?


そうです。

ある関数が「文字列」を受け取るにはchar *valueという形で受け取ります。
このような値の渡し型を「参照渡し(Call By Reference)」と言います。
この場合、関数内で受け取ったchar *valueに対して何かの操作すると、呼び出し元の変数の値(つまり文字列の実体の方)が変更されます。
    • good
    • 0
この回答へのお礼

ふむ,もう一度C言語の本をひっくり返して復習します.
詳しい解説どうもありがとうございました.
今後もどうぞよろしくお願いいたします.

お礼日時:2001/12/28 12:06

C++を使用しているのでしたら、stringクラスを使用されてはいかがでしょうか?


stringクラスを使用してソースを書き直すと以下のようになります。

#include <iostream>
#include <string>
using namespace std; // 名前空間.

// クラスcardの定義.
class card {
string title;
string author;
int num;

// 公開メンバ関数のプロトタイプ.
public:
void store( string& title_name, string& author_name, int zaiko_num );
void show();

};

// メンバ関数の定義.
// データ記録用.
void card::store( string& title_name, string& author_name, int zaiko_num )
{
title = title_name;
author = author_name;
num = zaiko_num;
}

// メンバ関数の定義.
// データ表示用.
void card::show()
{
cout << title << endl;
cout << author << endl;
cout << num << endl;
};


int main(int argc, char* argv[])
{

// クラスオブジェクトの作成.
card cd;

// 目録データの設定
string oTitle = "I, Robot";
string oAuther = "Asimov, Issac";
cd.store( oTitle, oAuther, 20 );

// 目録データの表示.
cd.show();

return 0;
}
    • good
    • 0
この回答へのお礼

こんにちは.C++での実装法の解説ありがとうございます.
実際コードを書いて,その挙動を確認してみます.
それでは失礼します.今後もよろしくお願いします.

お礼日時:2001/12/28 12:04

まずは、基本を。



char 変数名;
の変数には「1文字」しか格納できません。つまり「文字列」を格納することはできません。

「文字列」を格納するには「文字型の配列」または「文字型へのポインタ」を使う必要があります。

また、値の代入に関してはmemcpyやstrcpyを使います。
単純な代入では挙動不審になります。
また、コピー先の変数には、予め十分な容量が確保されている必要があります。

この回答への補足

さっそく解説していただき有り難うございます.
C++というよりはCの基本がわかっていませんでした.
つまり,引数としては, 公開メンバ関数 store()の引数で,
文字列を渡す場合は,たとえば,char *dataとすべきということで
理解してよろしいでしょうか?
すなわち,上のコードに準拠してかけば,
void store::card( char *title_name , char *author_name, int zaiko_num)
{
// 関数定義内容.
}
となるのですか?

補足日時:2001/12/27 19:48
    • good
    • 0

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

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

Qint rev_int(int num)文  関数の入門

#include<stdio.h>
/*---非負の整数を読み込んでます*/

int scan_uint(void)

//関数scan_uintは、キーボードから非負の整数値を読み込んでその値を返す関数です。
{
//この関数には受け取るべき仮引数がありません。仮引数がないことを示すためには()の中をvoidとします。

int tmp;//テンプの箱作成

do {
printf("非負の整数を入力してください:");scanf("%d",&tmp);
if(tmp< 0)
printf("\a負の数を入力しないでください");

}

while(tmp<0);

return (tmp);
}

/*非負の整数を逆転した値を返す*/

intrev_int(int num)
{


inttmp = 0;

if(num> 0){
do{
tmp = tmp * 10 + num % 10;
num /= 10;
}while (num > 0);

}

return (tmp);

}

int main(void)
{

int nx = scan_uint();

printf("反転した値は%dです。\n", rev_int(nx));

return 0;

}

教えてください!参考書に書いてあることをまとめて
プログラムを読んでるのですが、わからない部分があります。
(1)まずint scan_uint(void)からこのプログラムは読み込んでるのでしょうか? どこかのサイトを調べたら、最初にint mainからプログラムは
読み込むというのを観たのですが、コンパイルして実行した動きをみるかぎり一番最初はint scan_uint(void)から読んでるように見えます。。。

(2)int scan_uint(void)の文は理解できました。私なりに解釈したのは
ここでは正の数を入力しないと次に進まないことと
負の数を入力した場合、負の数を入力しないでくださいと注意がずっと
でるという文です。
質問ですが、このあとint rev_int(int num)文に移ると思うのですが
ここの int tmp = 0; これはこのint rev_int(int num)文のみの
tmpの箱と参考書に記載がありました。つまり int scan_uint(void)で
出てきたtmpとは別個と解釈しました。

そうなると、int rev_int(int num)文を読んでみると

tmpの箱を作成。そこは0を代入。
if文で num>0の時、 do文に入る (ここでいうnumは int numと宣言してないですけど、またscanfとか作って値はまだいれてないですけど??)

do文は
tmp = tmp*10 + num %10
num /=10
wile(num>0)

これを見る限り、numという箱が見えません。全体を見渡しても
どこかでnumに値が代入されたのち、このint rev_int(int num)
という文を読みこんでいき if num>0のときと宣言されていますが
もっと前の段階でnumの値が入力されていない限り
このif文は適用されないと思ったのですが、プログラムは動いてます

三つ目の質問です
tmp = tmp *10 + num % 10
num /=10 の部分がわかりませんでした。
tmpはまず、int scan_uint(void)で作成したtmpと
int rev_intで登場してきたtmpとは別個と参考書に書いてあるのが
正しいのであれば
tmpの値はここでは初のはずです。
一体いつ値を入力したのでしょうか?
もしも一番最初のscanfの時に入力した例えば12345が此処でも適用されるなら tmp = 12345 ×10 + num % 10を tmpに代入するって文になりますが
どうしてtmpを10かけるのですか?123450になり、
そのあとnumの値が此処でもまだ不明なのですがnum/10したものと
足すみたいですが、わかりませんでした。。。

まとめると、tmp = tmp*10+num%10がわかりません。
また、numとは何かわかりません、値もどの値がどこで代入されていて
while(num>0)が引っかかるのか不明です。
tmpはint scan_uint文内で入力した値(scanfの部分で)
12345と仮に入力したら、それは次のint rev_int(int num)でも続いて活用されてるのですか?
参考書はなぜ別個と書いてるのかわかりません。

ごめんなさい>_< とても長くなりました。
どなたか解る方、教えてください、よろしくおねがいします。

#include<stdio.h>
/*---非負の整数を読み込んでます*/

int scan_uint(void)

//関数scan_uintは、キーボードから非負の整数値を読み込んでその値を返す関数です。
{
//この関数には受け取るべき仮引数がありません。仮引数がないことを示すためには()の中をvoidとします。

int tmp;//テンプの箱作成

do {
printf("非負の整数を入力してください:");scanf("%d",&tmp);
if(tmp< 0)
printf("\a負の数を入力しないでください");

}

while(tmp<0);

return (tmp);
}

/*非負の整数を逆転...続きを読む

Aベストアンサー

(1)
C言語の場合「書いてある順番」と「実行する順番」は、まったく関連がありません。

決まっているのは「必ずmain関数から実行する」と言う事だけです。

因みに「実行を開始する場所(ポイント)」のことを「エントリポイント」と呼び、Cでは「main関数の先頭がエントリポイント」と決まっています。

(2)
>質問ですが、このあとint rev_int(int num)文に移ると思うのですが
いいえ。移りません。

これが「そもそもの誤解の始まり」です。

上記(1)で言った通り、必ずmainからプログラムが動き始めます。

main関数で

int nx = scan_uint();
printf("反転した値は%dです。\n", rev_int(nx));

と、それぞれの関数を呼んでいるので、実際の動作を実行順に羅列すると
1.必ずmainの先頭からプログラム開始。
2.mainからscan_uintが呼ばれる。
3.呼ばれたscan_uintが処理を行う(内容は理解しているようなので省略)
4.scan_uintからmainに帰ってくる。その時の戻り値がnxに入る。
5.printfの引数にrev_int(nx)があるので、nxを引数にしてrev_intを呼ぶ。
6.呼ばれたrev_intは、nxの値をnumとして受け取る。
7.rev_intは受け取ったnum(mainのnxと同じ値)を元に処理を行う。
8.rev_intはtmpに作った値を戻り値として関数を終わる。
9.rev_intからmainに帰ってくる。その時の戻り値がprintfの引数になる。
10.mainからprintfが呼ばれる。
11.呼ばれたprintfは何かを画面に表示し、関数を終わる。
12.printfからmainに帰ってくる。printfの戻り値は受け取ってないので捨てられる。
13.mainがreturn 0;で関数を終わらせ、プログラムが終了する。
となります。

>これを見る限り、numという箱が見えません。全体を見渡しても
上記の6.で「引数の実体として、mainから渡してもらってる」でしょう?

それが判らなかったのは「プログラムはmainの先頭から実行する」と言うのを理解できていないからです。

(3)
>tmp = tmp *10 + num % 10
>num /=10 の部分がわかりませんでした。
>どうしてtmpを10かけるのですか?123450になり、
123450にはなりません。

rev_intに入ってきたら
int tmp = 0;
ってやってるので、tmpは「最初は0」です。別の場所(scan_uintなど)にあるtmpは「同姓同名の赤の他人」なので忘れましょう。

scan_uintで「12345」を入力すると、12345がmainのnxに返って来て(nxが12345になって)、そのnxの値である12345がrev_intに渡され、rev_intは12345をnumに受け取ります。

つまり「最初は、numは12345、tmpは0になっている」のです。

そして、numが0かどうか調べます。

numが0でない(12345になっている)ので、次に
tmp = tmp *10 + num % 10;
を実行します。

tmp(中身が0)を10倍した値と、numを10で割った余りを足し、tmpに戻しています。

つまり0を10倍した0に、12345を10で割った余り5を足し、足した結果5をtmpに戻します。なのでtmpは5になります。

次に
num /=10;
を実行します。

これは「numを10で割って、numに戻す」です。
num = num / 10;
と同じです。

numは12345なので、10で割った商1234がnumの新しい値になります。

なお、Cでは、整数の割り算の答えは「商」だけです。小数点以下はありません。例えば、1を10で割ると0になります。

次は、while文で「numが0より大きいなら繰り返し」です。

numが0より大きい(1234になっている)ので繰り返すことになり、また
tmp = tmp *10 + num % 10;
を実行します。

tmpは5になっているので10倍して50、それにnum(1234)を10で割った余り4を足し、足した54をtmpに戻します。

次に
num /=10;
を実行します。

numは1234なので、10で割った商123がnumの新しい値になります。

これを「numが0より大きい間、繰り返し」すると

tmp=0、num=12345

tmp=5、num=1234

tmp=54、num=123

tmp=543、num=12

tmp=5432、num=1

tmp=54321、num=0

となり、numが0になって繰り返すのをやめた時、tmpは54321になっています。

そして、最後に
return tmp;
として、54321をmainに返します。

mainに帰って来ると、前述の9.~11.の処理で
反転した値は54321です。
と表示されます。

>参考書はなぜ別個と書いてるのかわかりません。

「別の場所にある、同じ名前の変数は、同姓同名の赤の他人」なので「別個」です。

(1)
C言語の場合「書いてある順番」と「実行する順番」は、まったく関連がありません。

決まっているのは「必ずmain関数から実行する」と言う事だけです。

因みに「実行を開始する場所(ポイント)」のことを「エントリポイント」と呼び、Cでは「main関数の先頭がエントリポイント」と決まっています。

(2)
>質問ですが、このあとint rev_int(int num)文に移ると思うのですが
いいえ。移りません。

これが「そもそもの誤解の始まり」です。

上記(1)で言った通り、必ずmainからプログラムが動き...続きを読む

Qchar c = 'a'; char h[1] = c; エラー

char型のものを char[]型に代入したいです。

char c = 'a';
char h[1] = c;

として、

h[0] は \x97
h[1] は \x00

にしたいです。
型変換の方法を教えてください。

Aベストアンサー

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数を確保します。
後半で、その中を初期化しています。
添え字は 0 からはじまるので、この場合、h[0] に c の内容が代入されます。
1個しか場所を確保していないので、 h[1] の位置のデータは内容が不定です。
文字列として h を扱いたいのであれば、 C の文字列には終端として 0 が必要ですから、
char c = 'a';
char h[2] = { c, '\0'};

のような書き方が必要になります。
これで、お望みのデータになると思います。

とりあえず、確認を。

C では、'a'の表す値は 0x61 = 97 であって、 \x97 ではないと思います。
(\xnnn を、十六進数の意味に取りましたが、あってますでしょうか?
この場合、C では通常 0xnnn のように書くと思います。)
ので、 これは 0x61 のことをおっしゃっていると仮定します。

> char h[1] = c;
っと、これではたぶんコンパイルが通りません。

char h[1] = {c};

のように、配列であることを明示して代入してください。
この式では、前半でh という名前の、*長さ1 の* char の配列変数...続きを読む

Qchar *str; と char* str;

char *str; と char* str;
どっちも同じことを意味しているんですか?

Aベストアンサー

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染むのでしょう。ちなみにそういう風な人たちは

char *str1, *str2;

とは、書けない体になっています。

char* str1;
char* str2;


変数の宣言だと、C に慣れていれば、char* str というのはちょっと違和感があるのは
私も分かりますが、関数のプロトタイプ宣言だと、どちらの方がすっきりしますか?

extern char *memcpy(char *, const char *);

extern char* memcpy(char*, const char*);


# まあ、どっちが正しい、っていうんじゃ無いんですよね

同じことを指している、というのは、先の回答の通りです。

また、ひとつの宣言で変数を複数宣言したときに、char* str という表記は間違い
易いじゃないか、ということが言われているのも事実です。実際、いろいろな C のソースを
見ていても、まずアスタリスクを型につけて書くのは、まずお目にかかれません。

ただ C++ では、char* str という宣言も良く使われています。

C++ に限らずオブジェクト指向の言語は、強く型を意識するので、「文字のポインタ型」と
いう意味で、まとめて書く方が馴染む...続きを読む

Q副プログラム内(void mystery(char s1[],char s2[]))の動作確認文 

お忙しい中失礼します。
下記のプログラム内の動作について質問があります。宜しければご回答願います。

void mystery(char s1[],char s2[])
{
int i=0;
while(s2[i]!='\0'){ //s2[i]内に文字が入力され、エンターキーが入力されるまで{s1[i] = s2[i]; ++i;}内の動作を行う。
s1[i] = s2[i];    //s1[i] を基準にs2[i]の文字数を++iを使い、カウントする。
++i;         //++iはただs1[i] とs2[i]の文字が合致してるか確認を行う。s1[]=”Good”なら s2[]=”Good”の各文字が合致してるかどうか。
}

s1[i] = '\0';    //s1[i]にエンターキーが入力されて、void mystery(char s1[],char s2[])内のループを抜ける。
return;       //s1[i] = '\0'で'\0'が定義されているのでreturn 0;でない?
}

↑上記動作質問://より右側の文章は文章的に正しいでしょうか?
void mystery(char s1[],char s2[])内でどんな動作をしてるのかが、イマイチよく分からないのです。




↓下記のプログラム
#include <stdio.h>
#include <stdlib.h>
void mystery(char [], char[]);

int main()
{
char m1[81],m2[81];
int i;
printf("Message?");
gets(m1);
mystery(m2,m1);
puts(m2);

system("PAUSE");
return 0;
}

void mystery(char s1[],char s2[])
{
int i=0;
while(s2[i]!='\0'){
s1[i] = s2[i];
++i;
}

s1[i] = '\0';
return;
}

お忙しい中失礼します。
下記のプログラム内の動作について質問があります。宜しければご回答願います。

void mystery(char s1[],char s2[])
{
int i=0;
while(s2[i]!='\0'){ //s2[i]内に文字が入力され、エンターキーが入力されるまで{s1[i] = s2[i]; ++i;}内の動作を行う。
s1[i] = s2[i];    //s1[i] を基準にs2[i]の文字数を++iを使い、カウントする。
++i;         //++iはただs1[i] とs2[i]の文字が合致してるか確認を行う。s1[]=”Good”なら s2[]=”Good”の...続きを読む

Aベストアンサー

うーん。。。
動作の説明としては全て間違いです。

>while(s2[i]!='\0'){
s2のi番目の要素が終端文字で無い間繰り返し処理します。
#エンターキー云々は関係ありません。

>s1[i] = s2[i];
s1のi番目の要素にs2のi番目の要素をコピーしています。
#比較ではなく代入です。

>++i;
ここでのiは文字列の要素を表す要素番号に過ぎません。
#次の文字へ進むだけで、カウントなどしていません。

>s1[i] = '\0';
s2が文字列の終わりを検出したので、
ループを抜けてs1にも文字の終端を書き込んでいます。
#ここでは既にループを抜けた後です。

>return; 
関数の戻り値はvoidつまり「無し」なので
returnで評価される式も在りません。
#疑問系でコメントを書くなら書かない方が良いです。
#混乱のもとですから。。。

短くすると・・・:-p
void mystery(char *s1, const char *s2){
  while (*s1++ = *s2++);
}

うーん。。。
動作の説明としては全て間違いです。

>while(s2[i]!='\0'){
s2のi番目の要素が終端文字で無い間繰り返し処理します。
#エンターキー云々は関係ありません。

>s1[i] = s2[i];
s1のi番目の要素にs2のi番目の要素をコピーしています。
#比較ではなく代入です。

>++i;
ここでのiは文字列の要素を表す要素番号に過ぎません。
#次の文字へ進むだけで、カウントなどしていません。

>s1[i] = '\0';
s2が文字列の終わりを検出したので、
ループを抜けてs1にも文字の終端を書き込んでいま...続きを読む

Qvoid (*signal(int signum, void (*handler)(int)))(int);

の解釈を教えてください
最後の「(int)」については詳しくお願いします

Aベストアンサー

signalが

(1)1つ目の引数の型:int
(2)2つ目の引数の型:引数がintで戻り値がvoidである関数へのポインタ
(3)戻り値の型:引数がintで戻り値がvoidである関数へのポインタ(2と同じ)

を満たす関数である事を宣言しています。最後の(int)はsignalの戻り値の
関数ポインタがint型の引数を持つ事を示しています。

「引数がintで戻り値がvoidである関数へのポインタ」の型をHANDLERと表すと

HANDLER signal(int signum, HANDLER handler);

となります。


人気Q&Aランキング

おすすめ情報