以下のようなプログラムを書いたのですが、うまく実行することができません。
データを複数個入力し、いつでも変更できる状態で調べたいもののみを抽出させた一覧も作りたいです。どのようにすれば実行できるのでしょうか。分かる方教えて頂きたいです。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Data{
char *namae;
char *sei;
long bangou;
}DATE;
int main(void){
DATE *x;
int menu;
menu=1;
int a;
a=1;
int y,z;
y=1;
while(a!=9){
if(menu==1){
printf("\n1.データを入力又は、変更\n");
printf("2.名前一覧\n");
printf("3.性別一覧\n");
printf("4.電話番号一覧\n");
printf("9.終了\n");
printf(">");
scanf("%d",&a);
}
switch(a){
case 1:
printf("何番目のデータを入力したいですか:");
scanf("%d",&y);
printf("名前を入力:");
scanf("%s",&x[y].namae);
x[y].namae=(char*)malloc(sizeof(char)*(strlen(&x[y].namae)+1));
printf("性別を入力:");
scanf("%s",&x[y].sei);
x[y].sei=(char*)malloc(sizeof(char)*(strlen(&x[y].sei)+1));
printf("電話番号を入力:");
scanf("%ld",&x[y].bangou);
x[y].bangou=(char*)malloc(sizeof(char)*(strlen(&x[y].bangou)+1));
break;
case 2:
for(z=1;z<=y;z++){
printf("%s",x[z].namae);
}
break;
case 3:
for(z=1;z<=y;z++){
printf("%s",x[z].sei);
}
break;
case 4:
for(z=1;z<=y;z++){
printf("%ld",x[z].bangou);
}
break;
case 9:
printf("\n終了します\n");
break;
}
}
}
A 回答 (7件)
- 最新から表示
- 回答順に表示
No.7
- 回答日時:
> 修正したあと、以下のようなエラーがでたのですがこれはlong r[12]を何かに変更しなければイコールにはならないということですか?
あああああ、そこは
> long r[12]
だとlongの配列になってるじゃない。
だからそこを
> char r[12]
にしておけば大丈夫でしょ。すっかり見落としてました。
long r[12]のままだと、文字列読み込んでるのに、対象がlongの配列なんで文句言われてるのです。
あとね、ぶっちゃけ、そこで配列3つも用意しておくのは無駄なんで、1つ
char s[12]
だけ用意しておいて、「使い回し」して大丈夫です。scanfで読み込む度に中身は書き換わりますから。
No.6
- 回答日時:
そこで出てる警告は
strlen(r)
や
atol(r)
の実引数 r が関数の期待する型じゃないよってこと. リファレンスなんかで確認しよう.
ちなみに C の場合ポインタと整数は互いに変換できるので
int x = (int *)malloc(何とやら)
はエラーにならない>#5. 「エラーにならない」だけで, それが本当に期待する動作なのかどうかは知らない.
ありがとうございます。rの型のせいでイコールが成立たないということですかね。
電話番号はポインタを使っていないはずなのですが、どこかでポインタになっているみたいなエラーでよく分かりません。
リファレンスという言葉を浅学で申し訳ないのですが知りませんでした。
直訳が「参考資料」だったのですがネット等の参考資料に例があるということでしょうか。
互いに交換できるのも知りませんでした。おかしな操作が内部で行われていてもエラーにはならないということですね。
今後気をつけたいです。
No.5
- 回答日時:
> 以下のようなエラーはどう修正すれば良いのでしょうか…
いやいや、だから・・・。
元々、構造体DATEは次のような定義でしょ?
typedef struct Data{
char *namae;
char *sei;
long bangou;
}DATE;
名前も性もポインタだけど、番号は違うじゃない。「フツーにlongの整数」として宣言してますよね?
こいつがポインタ変数じゃなく、単なる変数である以上、メモリアロケーションは必要ないんですよ。
例えば構造体じゃなくても、
int x = (int *)malloc(何とやら)
ってメモリアロケーションしたら似たようなエラーが出ると思いますよ。こいつ(x)はポインタ型じゃない。
だからメモリアロケーションを行わずに、
x[y].bangou = atol(r);
でそのまま代入出来ます。
int x = 1;
なんかと同じです。
詳しく説明ありがとうございます。
理解できました!
修正したあと、以下のようなエラーがでたのですがこれはlong r[12]を何かに変更しなければイコールにはならないということですか?訳したところポインタが関係しているのかと思ったのですがナンバーはポインタではないのでどのような事を言っているのかが分かりません…
Main.c:44:34: warning: incompatible pointer types passing 'long [12]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
x[y].bangou=atol(r);
^
/usr/include/stdlib.h:366:26: note: passing argument to parameter '__nptr' here
__NTH (atol (const char *__nptr))
^
1 warning generated.
No.4
- 回答日時:
> 何度も申し訳ないのですがご助言頂けないでしょうか。
あー、多分ここがダメなんじゃないかな。
> DATE *x[100];
「構造体の配列」でしょ?これじゃあポインタなんだか配列なんだか分かんない。そうじゃなくって、
DATE x[100]
で充分じゃないですか?文字通り「構造体の配列」が要り用なんで、ポインタのなんたら、が欲しいわけじゃない。
ここだけ修正すれば、まずはエラーが取れるでしょう。
それと、
x[y].bangou
はlongで宣言したまま、って事ですよね。そうすると、scanfでこの部分に入力した「文字列」はそのままだと格納出来ないんで、atolでlongに変換します。
従って、この部分「だけ」は
x[y].bangou = atol(r);
でlongに変換した文字列rを直接代入するだけ、で済みますね。
ありがとうございます。
以下のようなエラーはどう修正すれば良いのでしょうか…
訳したのですがどうすればよく分からなくて。
本当に何度もご助言ありがとうございます。
Main.c:44:63: warning: incompatible pointer types passing 'long [12]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
x[y].bangou=(long)malloc(sizeof(long)*(strlen(r)));
^
/usr/include/string.h:385:35: note: passing argument to parameter '__s' here
extern size_t strlen (const char *__s)
^
Main.c:45:34: warning: incompatible pointer types passing 'long [12]' to parameter of type 'const char *' [-Wincompatible-pointer-types]
x[y].bangou=atol(r);
^
/usr/include/stdlib.h:366:26: note: passing argument to parameter '__nptr' here
__NTH (atol (const char *__nptr))
^
2 warnings generated.
No.3
- 回答日時:
scanf("%s",&x[y].namae);
が何をするか理解できている?
scanf("%ld",&x[y].bangou);
x[y].bangou=(char*)malloc(sizeof(char)*(strlen(&x[y].bangou)+1));
がおかしいことに気づいてる?
勝手に補足しておくと
%11s: (最初の方にある空白文字を無視して) 最大 11個の「空白でない文字」を読み込み, 対応する (char * を期待する) 引数に入れる (そして最後に '\0' を追加する)
%*[^\n]: 改行以外の文字 ([^\n]) を読み込んで (* が指定されているので) 捨てる
%*c: 1文字読み込んで捨てる
ということ.
%s では空白が読み込めないので, それが問題になるときは別の方法を考えてください.
ところで, DATE でいいの? 構造体タグが Data だから, 全部大文字にするなら DATA だと思うんだ. あと構造体タグと typedef名に同じものが使えるというのも, 知っておくと便利かもしれない.
理解したいとは思っていますが、充分出来ていないと思います…
おかしくないと思っていたのですが、違いました。
scanf部分の説明とてもわかり易かったです。理解できました。
構造体タグと同じものが使えるのは知りませんでした。ご教授ありがとうございます。
No.2
- 回答日時:
> scanfで文字列を読み取っているときのscanf(%11s%*[^\n]%*c)の部分は何を表しているのでしょうか?
次のページを参考にしてください。
[迷信] scanf ではバッファオーバーランを防げない:
http://www.kijineko.co.jp/tech/superstitions/buf …
基本的に、入力を伴う時、文字列でやり取りした方が「安全」だと言う事です。
%11s%*[^\n]%*c
の部分は性器表現、もとい、正規表現、と言われるやり方で、11文字になった時点でそれ以上の入力を受け付けないようにするオマジナイです。そうすれば、指定した文字数以上のメモリへの書き込みを抑制する事が出来ます。
ちなみに、11文字、と言うのは、電話番号の入力への使い回しも考えて、巷の電話番号の「最大の長さ」を考慮した文字数です。
scanfの部分理解できました!
ありがとうございます。
教えて頂いた部分を修正したのですが、うまくいきませんでした…
longの部分は指定されていて、変更はしなかったのですが、エラーがx[y].namaeをx[y]->namaeに変えろというもので、すべて変更したところまたそこの部分がえらーになってしまい…
何度も申し訳ないのですがご助言頂けないでしょうか。
typedef struct Data{
char *namae;
char *sei;
long bangou;
}DATE;
int main(void){
DATE *x[100];
char s[12];
char t[12];
long r[12];
switch(a){
case 1:
printf("何番目のデータを入力したいですか:");
scanf("%d",&y);
printf("名前を入力:");
scanf("%11s%*[^\n]%*c",s);
x[y].namae=(char*)malloc(sizeof(char)*(strlen(s)+1));
strcpy(x[y].namae,s);
printf("性別を入力:");
scanf("%11s%*[^\n]%*c",t);
x[y].sei=(char*)malloc(sizeof(char)*(strlen(t)+1));
strcpy(x[y].sei,t);
printf("電話番号を入力:");
scanf("%11ld%*[^\n]%*c",r);
x[y].bangou=(char*)malloc(sizeof(char)*(strlen(r)+1));
strcpy(x[y].bangou,r);
break;
case 2:
for(z=1;z<=y;z++){
printf("%s",x[z].namae);
}
修正部分だけ掲載しました。
No.1
- 回答日時:
うーん、まずは・・・。
> DATE *x;
これだけ、じゃダメですね。
ポインタ宣言してますが、これだけだと複数のデータ(構造体を)格納出来るメモリを確保出来ません。
多分意図してるのは構造体の配列が欲しい、ってトコだと思いますが、残念ながらC言語だと、最初に配列の大きさを宣言しとかないとならないか、あるいはメモリアロケーション使って適当なサイズを得ておかないとなりません。
ポインタだけ宣言しておいて、「データを追加する」みたいなのは他の言語じゃ可能ですが(例えば空リストを作っておいて順次データを追加していく、みたいな)、生憎Cはそういう融通が利きません。
どれだけ大きい配列を作るのか、ってのは貴方の好みですが、いずれにせよ、サイズは明確にしておかないとならないのです。
>printf("名前を入力:");
>scanf("%s",&x[y].namae);
>x[y].namae=(char*)malloc(sizeof(char)*(strlen(&x[y].namae)+1));
>printf("性別を入力:");
>scanf("%s",&x[y].sei);
>x[y].sei=(char*)malloc(sizeof(char)*(strlen(&x[y].sei)+1));
>printf("電話番号を入力:");
>scanf("%ld",&x[y].bangou);
>x[y].bangou=(char*)malloc(sizeof(char)*(strlen(&x[y].bangou)+1));
scanfで無理矢理構造体のメンバに代入しようとしてますが、これだと上手くいかないでしょう。
個人的には最初に別に文字配列格納の為の変数を用意しておいて、
> char s[12];
scanfを使って文字列を読み込み、
> scanf("%11s%*[^\n]%*c", s);
構造体のメンバの該当項目のメモリを確保して、
> x[y].namae = malloc(strlen(s));
strcpyを使ってsを該当のメンバにコピーします。
> strcpy(x[y].namae, s);
多分これで上手く行くんじゃないかな・・・・・・?
あと、多分、電話番号はlongじゃなくって、やっぱchar*にしておいた方が良いと思いますよ。
と言うのも、電話番号は大体0から始まってるんで、intとかlongだとアタマの0が消えちゃうから、ですね。
なるほど!scanfで文字列を読み取っているときのscanf(%11s%*[^\n]%*c)の部分は何を表しているのでしょうか?
もしよろしければ教えて頂きたいです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語 プログラミング 4 2022/05/22 11:53
- C言語・C++・C# c言語配列の結合についてです。 なぜうまくいかないのでしょうか。 #include <stdio.h 4 2022/05/30 22:42
- C言語・C++・C# 宣言する関数の形が決まっている状態で、 str1とstr2の文字列をこの順に引っ付けてstrに保存し 2 2022/05/30 18:21
- C言語・C++・C# プログラミングの授業の課題です 1 2023/01/17 22:15
- C言語・C++・C# c言語でユーザ関数を利用して入力された文字列を反転させるプログラムを作りたいです。 3 2023/01/29 19:47
- C言語・C++・C# カードシャッフルのブログラムを使ってc言語でブラックジャックをしたい 2 2022/04/12 15:13
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# C言語プログラム変更 2 2022/12/21 15:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語にて構造体のメンバがNULL...
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
new charとnew char[N]の違いは?
-
SubStringの使い方について
-
カンマで区切った文字の抽出に...
-
文字列の途中から途中までを抽出
-
コマンドライン引数 *argv[]は...
-
'\\0'とはなんですか?
-
C言語の文字リテラル中の16進文...
-
strcpy関数で文字型変数へのポ...
-
関数について
-
char[]をDWORDに格納するには
-
動的メモリの初期化方法について。
-
DWORDとcharの変換
-
csvファイルをfscanfで読み込む...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
C言語のintとcharの違いってな...
-
構造体・ビットフィールドのvol...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
char*を初期化したいのですが
-
CStringからchar*への型変換に...
-
C言語のintとcharの違いってな...
-
C言語にて構造体のメンバがNULL...
-
小数点入りの文字列をfloat型に...
-
strcat関数を自作したいです
-
C言語のプログラムについてです
-
const char* s1とただのchar s1...
-
DWORDとcharの変換
-
char型にint型の数値を代入する。
-
文字列の途中から途中までを抽出
-
new charとnew char[N]の違いは?
-
文字列内の数字削除
-
csvファイルをfscanfで読み込む...
-
fgetc( )の戻り値はなぜ整数??
-
char 文字列型 の表現範囲が-12...
-
fstream型オブジェクトを関数の...
-
エクセルのMID関数は、C言語では?
-
ポインタを使って回文かどうか...
-
ポインタ配列
おすすめ情報