C言語関係掲示板

過去ログ

No672 名簿ファイルの読込み(領域の確保についても)

[戻る] [ホームページ]
No.7491

構造体は難しい(^^;)
投稿者---疾風(2003/06/18 11:11:57)


はじめまして。

次のことがよくわかりません。
*漢字氏名、ローマ字氏名、IDなどが書かれたCSV形式の名簿ファイルを標準入力からscanf()関数を用いて一行を単位で読み込み.ファイルの入力は,リダイレクションを用いる方法をおしえて下さい。

No.7495

Re:構造体は難しい(^^;)
投稿者---もぐりん(2003/06/18 12:41:55)


題名と本文の内容が一致していないようですが、
結局CSVファイル読み込みに関する質問なのでしょうか?


No.7499

実は
投稿者---疾風(2003/06/18 12:54:24)


>題名と本文の内容が一致していないようですが、
>結局CSVファイル読み込みに関する質問なのでしょうか?

SV形式のファイルのデータを構造体で作成した配列に格納するプログラムを作成するもので、個々のレコードは構造体配列の一つの要素に記録するしプログラム中のデータ入力は,標準入力からscanf()関数を用いて一行を単位として行なわなければいけないのです。ファイルの入力は,リダイレクションを用います。

No.7537

Re:実は
投稿者---かずま(2003/06/18 18:36:28)


次のプログラムの問題点を指摘してください。
$ cat a.c
#include <stdio.h>
#include <string.h>

#define N  100

typedef struct { char *kname, *rname, *id; } Person;

int main(void)
{
    Person data[N];  int i, n;

    for (n = 0; n < N; n++) {
        char kname[256], rname[256], id[256];
        if (scanf("%255[^,\n],%255[^,\n],%255[^,\n]%*c", kname, rname, id) != 3)
            break;
        data[n].kname = strdup(kname); 
        data[n].rname = strdup(rname); 
        data[n].id    = strdup(id); 
    }
    if (n == N) return puts("too name data"), 1;
    if (!feof(stdin)) return puts("input error"), 1;
    for (i = 0; i < n; i++)
        printf("%-10s %-18s %s\n", data[i].kname, data[i].rname, data[i].id);
    return 0;
}
$ gcc a.c
$ cat 1.dat
新庄剛志,Shinjo Tsuyoshi,5
鈴木一朗,Suzuki Ichiro,51
松井秀樹,Matsui Hideki,55
$ ./a.out <1.dat
新庄剛志   Shinjo Tsuyoshi    5
鈴木一朗   Suzuki Ichiro      51
松井秀樹   Matsui Hideki      55
$ 


No.7539

すみませんよくわかりません。
投稿者---疾風(2003/06/18 18:51:10)


>次のプログラムの問題点を指摘してください。


コンパイルも通るので良さそうに見えるのですが ・・・・でも実行すると無限ループに入りますね。しかしその原因がわからないです。

No.7558

Re:すみませんよくわかりません。
投稿者---かずま(2003/06/19 09:47:56)


> コンパイルも通るので良さそうに見えるのですが ・・・・
> でも実行すると無限ループに入りますね。しかしその原因がわからないです

無限ループに入ったと言う根拠は何ですか。
同じメッセージが繰り返し表示されたとでも言うのでしょうか。

標準入力をファイルにリダイレクトしましたか?
もし、リダイレクトしていなければ、入力はキーボードのままですから、
プログラムはキー入力待ちになりますよ。

どのようにして、実行したのかをくわしく書いてください。

それから、訂正です。
    if (scanf("%255[^,\n],%255[^,\n],%255[^,\n]%*c", kname, rname, id) != 3)
--> if (scanf("%255[^,],%255[^,],%255[^\n]%*c", kname, rname, id) != 3)

    if (n == N) return puts("too name data"), 1;
--> if (n == N) return puts("too many data"), 1;

    松井秀樹,Matsui Hideki,55
--> 松井秀喜,Matsui Hideki,55


No.7711

宿題の答え
投稿者---ともじ(2003/06/23 21:03:19)


こんばんは。

実は、こちらに返信が付くのを待っていました。
どうやら、返信が無いようですので、かずまさんの最初の問い、
「次のプログラムの問題点を指摘してください。」に対しての
私の解答です。
1.
    char kname[256], rname[256], id[256];

forループの中で、kname, rname, id の宣言を行っているので、
ループのたび、256*3バイトの領域を定義することになり、処理上の
オーバヘッドが増す。

2. 
    if (scanf("%255[^,],%255[^,],%255[^\n]%*c", kname, rname, id) != 3)

の場合、入力項目が

    新庄剛志,Shinjo Tsuyoshi,5

のように、3個全て存在する場合には問題が無いが、

    鈴木一朗,,51

のように、途中の項目が存在しないレコードがあった場合、そこで
読み込み動作を終了する。その際、表示処理の前に

    if (!feof(stdin)) return puts("input error"), 1;

が記述されているので、正常に読み込まれたレコードについても表示
することができない。

3.
レコード件数がN件のときに、

    if (n == N) return puts("too many data"), 1;

の判定でエラーとなる。

他にもありますか?>かずまさん。


No.7724

Re:宿題の答え
投稿者---かずま(2003/06/24 13:44:50)


> 1.
> forループの中で、kname, rname, id の宣言を行っているので、
> ループのたび、256*3バイトの領域を定義することになり、処理上の
> オーバヘッドが増す。

どのコンパイラでも、これらの領域の確保は、関数の入り口で行われるので、
これらの宣言を forループの中に書いても、外に書いても実行速度は同じです。
規格書にそう実装しろと書いているわけではありませんが、実際問題として
そうなっています。

関数の入り口で、領域を確保するとき、256バイト確保する場合と、512バイト
確保する場合では、後者のほうが 2倍手間が掛かるでしょうか。
そんなことはありません。これらの領域の確保は、スタックポインタの値を
修正するだけなので、1回の操作ですみます。だから、関数内のどんなブロック
のローカル変数も、関数の入り口で領域を確保するように実装されているのが
普通です。

だから、このことは問題点ではありません。

> 2. 
>     鈴木一朗,,51
> 
> のように、途中の項目が存在しないレコードがあった場合、そこで
> 読み込み動作を終了する。その際、表示処理の前に
> 
>     if (!feof(stdin)) return puts("input error"), 1;
> 
> が記述されているので、正常に読み込まれたレコードについても表示
> することができない。

そうですね。

本当の CSV の規格というのがどうなっているのか知らないのですが、
たとえば、Excel は次のような CSVファイルを生成しますので、

  abc,def ghi,,"jkl,mno","pqr""stu"

という 1行からは、

  "abc"
  "def ghi"
  ""
  "jkl,mno"
  "pqr\"stu"

という文字列読み取らなければならないのです。

だから、CSVファイルを読むということは本当はたいへんなことなんです。

scanf だけで読み込もうとすること自体が無理ですし、
fgets と sscanf や、fgets と strtok でも無理でしょう。

今は、最低 1文字はデータがあり、「,」や「"」はデータに含まれず、
1行の中の項目数も固定と仮定していて、それに反するものがあれば、
すべての処理を中断することにしています。

CSV の仕様をきちんと定義せずにプログラムを書いているのが問題です。


> 3.
> レコード件数がN件のときに、
> 
>     if (n == N) return puts("too many data"), 1;
> 
> の判定でエラーとなる。

はい、これも問題点のひとつです。

他には、strdup の返却値をチェックしていなことや、strdup の
返却値をあとで free していないという指摘があることを期待して
いました。strdup が標準関数でないこともかな。


No.7728

Re:宿題の答え
投稿者---ともじ(2003/06/24 19:57:32)


返信ありがとうございます。

>> 1.
>> forループの中で、kname, rname, id の宣言を行っているので、
>> ループのたび、256*3バイトの領域を定義することになり、処理上の
>> オーバヘッドが増す。

> どのコンパイラでも、これらの領域の確保は、関数の入り口で行われるので、
> これらの宣言を forループの中に書いても、外に書いても実行速度は同じです。
> 規格書にそう実装しろと書いているわけではありませんが、実際問題として
> そうなっています。

そうなのですか。
forループのブロックの中で、
  char kname[256] = "", rname[256] = "", id[256] = "";
と配列の宣言と初期化を行うと、毎回初期化されますよね。
ですから、ループのたびに領域がスタック上に確保されたり破棄されたり
するものだと思っていました。初期化を伴わない場合には、関数
の入り口で領域が確保されると言うことになるのでしょうか。

試しに、clockを使って100万回のループの速度を計りましたが、
宣言のみの場合には、forループの中で行おうと、外で行おうと、速度は
全く同じでした。初期化を伴う場合には、両者は歴然とした差が出ますね。
この場合には当然ですが、宣言する要素数の多いほど時間がかかりました。

> 他には、strdup の返却値をチェックしていなことや、strdup の
> 返却値をあとで free していないという指摘があることを期待して
> いました。strdup が標準関数でないこともかな。

strdupは割りにどの処理系でも用意されているようですので、標準関数
でないことは、さほど問題視しませんでした。
freeも、メモリの再利用をしないままreturnしているのでなくても
大丈夫だと判断しました。でも、返却値のチェックは必要ですね。


No.7738

Re:宿題の答え
投稿者---こん!(2003/06/24 22:24:56)


ふと興味がわいたので以下のコードで確認してみました。
環境は Windows2000+sp3 VC++6.0+sp5 です。

    for(i = 0; i < 100; i++)
    {
        char    c[256] = "";

        strcpy( c, "abcdefghijklmn" );
    }
    
    return 0;


以降アセンブラ混合モードです。

8:        for(i = 0; i < 100; i++)

0040102E   mov         dword ptr [ebp-4],0                ; i = 0
00401035   jmp         main+30h (00401040)                ; i < 100へジャンプ
00401037   mov         eax,dword ptr [ebp-4]            ; i をaxレジスタに
0040103A   add         eax,1                            ; eax をインクリメント
0040103D   mov         dword ptr [ebp-4],eax            ; インクリメント結果をiの変数領域に
00401040   cmp         dword ptr [ebp-4],64h            ; i < 100
00401044   jge         main+6Ah (0040107a)                ; 100より大きかったらジャンプ

9:        {
10:           char    c[256] = "";
                        
                        こ こ か ら が み そ        
                                                
00401046   mov         cl,byte ptr [string "" (00422040)];clレジスタに文字列位置の1バイトをセット
0040104C   mov         byte ptr [c],cl                    ; c の先頭メモリにclの値をセット(ちなみに0)
00401052   mov         ecx,3Fh                            ;cxレジスタに63をセット

                            ; これはc[]のメモリがワードバンダリ(?バインダリあれ?何だっけ失語症だ。
                            ; 分かる人は分かるという事で。)で半端な部分を先程のclで1バイトセットし、
                            ; 残りを後のrep命令でeaxを使い32ビット単位でメモリにセットする。為に結果
                            ; 256/4-1=63となったようです。

00401057   xor         eax,eax                            ; axレジスタをクリア
00401059   lea         edi,[ebp-103h]                    ; c[1]のアドレスをediレジスタにセット
0040105F   rep stos    dword ptr [edi]                    ; eaxを32ビット単位でc[252]までのエリアにセット
                                                        ; NULLクリア
00401061   stos        word ptr [edi]                    ; 残りの3バイトをwordとbyteに分けてeaxの値をセット
00401063   stos        byte ptr [edi]

11:
12:           strcpy( c, "abcdefghijklmn" );               ; 以下strcpy処理

00401064   push        offset string "abcdefghijklmn" (0042201c)
00401069   lea         edx,[c]
0040106F   push        edx
00401070   call        strcpy (00403720)
00401075   add         esp,8

13:       }

00401078   jmp         main+27h (00401037)
14:
15:       return 0;

結果、ループで回るたびに『既に確保されているc[256]の配列メモリ』をクリアしているということらしいです。

No.7739

Re:宿題の答え
投稿者---こん!(2003/06/24 22:41:09)


; これはc[]のメモリがワードバンダリ(?バインダリあれ?何だっけ失語症だ。

これワードじゃないな。DWORDだな。失敬。

No.7741

Re:宿題の答え
投稿者---ともじ(2003/06/25 00:05:15)


>結果、ループで回るたびに『既に確保されているc[256]の配列メモリ』をクリアしているということらしいです。

BCCとLSICでもアセンブラコードを確認しましたが、同じですね。

JISの「6.1.2.4 オブジェクトの記憶域期間」では、「それが宣言されて
いるブロックへ正常に入るごとに、又は外側のブロックからそのブロック
若しくはそのブロックの内側のブロックの中の名札付き文へ分岐するごとに、
自動記憶域期間をもつオブジェクトの新しい出現のために記憶域を確保する
ことを保障する。(中略)オブジェクトの記憶域は、何らかの方法で
ブロックの実行を終了した場合には、もはや確保されている保証がない。」
とあるので、毎回記憶域が確保されると思っていました。

実装はそうではないということですね。でも、まあ、ループの回数分、
領域を確保するなんて無駄以外の何者でもないですから、そう実装
されるのは当たり前ですね。


No.7747

Re:宿題の答え
投稿者---こん!(2003/06/25 02:02:06)


>JISの「6.1.2.4 オブジェクトの記憶域期間」では、「それが宣言されて
>いるブロックへ正常に入るごとに、又は外側のブロックからそのブロック
>若しくはそのブロックの内側のブロックの中の名札付き文へ分岐するごとに、
>自動記憶域期間をもつオブジェクトの新しい出現のために記憶域を確保する
>ことを保障する。(中略)オブジェクトの記憶域は、何らかの方法で
>ブロックの実行を終了した場合には、もはや確保されている保証がない。」
・・・
>実装はそうではないということですね。でも、まあ、ループの回数分、

いや、解説通りなのでは?for文のブロックの中に入った時点で確保されブロック
の終了になるまでは保証されるわけですから。for文のループを回ってもブロック
から抜けているのではないですよね?

for文の判定条件でスコープから抜けた時点で初めて終了したことになるのですよ
ね。

No.7750

Re:宿題の答え
投稿者---ともじ(2003/06/25 08:59:32)


おはようございます。

>for文の判定条件でスコープから抜けた時点で初めて終了したことになるのですよ
>ね。

こん!さんがNo.7738で提示したコードでも
13:       }

00401078   jmp         main+27h (00401037)
ですから、ループのたびに抜けているんですよね。

仮に、判定条件で偽になった時点で抜けるとしても、
    int i;
    for(i = 0; i < 100; i++)
    { 
       char c[5];
    }
    int i;
    char c[5];
    for(i = 0; i < 100; i++)
    { 
    }
が同じコードを作るのは規格と実装が異なるということではないでしょうか。
もちろん、上記に実装上の区別が無いのは当然だと思いますが。

#宿題はちゃんとやるとためになりますね。


No.7752

Re:宿題の答え
投稿者---こん!(2003/06/25 09:40:40)


>おはようございます。

おはようございます。

>こん!さんがNo.7738で提示したコードでも
13:       }

00401078   jmp         main+27h (00401037)
ですから、ループのたびに抜けているんですよね。

あ、そう見たんですか。ん〜、どうなんでしょうね。確かに混合モードの記述を
見ると判定文に飛ぶ為のjmp命令先のアドレスは'{'の前と見えますね。ただこ
の"{}"の対というのはアセンブルのコード上には現れていませんよね。私の意識
としては'}'が今言っているjmp命令のあるところで'{'はjmp先のアドレスという
意識があるのですが・・・

つまりはfor文の判定文=='{'のつもりで話していました。さらにそういう意味で
はiのインクリメントは'{'の中という理屈になりますかね。

>仮に、判定条件で偽になった時点で抜けるとしても、
    int i;
    for(i = 0; i < 100; i++)
    { 
       char c[5];
    }
    int i;
    char c[5];
    for(i = 0; i < 100; i++)
    { 
    }
が同じコードを作るのは規格と実装が異なるということではないでしょうか。
>もちろん、上記に実装上の区別が無いのは当然だと思いますが。

この例にしても実際同じコードとも言いがたいかなと・・・
例えば
    int    i;

    char    c[256] ;
    for(i = 0; i < 100; i++)
    {
        memset( c, 0xff , 256 );

    }
これも
    int    i;

    for(i = 0; i < 100; i++)
    {
        char    c[256] ;
        memset( c, 0xff , 256 );

    }
これもコンパイルは問題なく通りますが
    int    i;

    for(i = 0; i < 100; i++)
    {
        char    c[256] ;
        memset( c, 0xff , 256 );

    }
    memset( c, 0xff , 256 );
これは通りませんよね。でも
    int    i;

    char    c[256] ;
    for(i = 0; i < 100; i++)
    {
        memset( c, 0xff , 256 );

    }
    memset( c, 0xff , 256 );
こうすると通すことは出来ます。そうして考えると先のともじさんのあげられた
2例は同じものといえるのでしょうか?

ここまでは、あくまでも私の推測ですので規格書等で確証を持たれている方はそ
ちらを尊重下さい。取り敢えず私自身はこのあたりの動作で困った事はないの
で。
((((((^_^;)


No.7753

Re:宿題の答え
投稿者---こん!(2003/06/25 09:43:25)


>つまりはfor文の判定文=='{'のつもりで話していました。さらにそういう意味で
>はiのインクリメントは'{'の中という理屈になりますかね。

これ違うね。順番でいうとインクリメントが'{'にならないといけないか?(^^ゞ


No.7758

Re:宿題の答え
投稿者---YuO(2003/06/25 10:33:58)


>いや、解説通りなのでは?for文のブロックの中に入った時点で確保されブロック
>の終了になるまでは保証されるわけですから。for文のループを回ってもブロック
>から抜けているのではないですよね?
>for文の判定条件でスコープから抜けた時点で初めて終了したことになるのですよ
>ね。

違います。for文の第三式が評価されるときにはすでに複文(ブロック)のスコープから外れています。

forは,
for ( 第一式 ; 第二式 ; 第三式 ) 文
という形を取ります。
これより明らかに,ループ本体は第二式・第三式の評価とは独立となります。
また,第三式や第二式がループ本体のスコープだとすると,ループ本体が式文であった場合の扱いに困ります。


最初に一気にメモリを確保するのは,複文の真ん中にgotoやswitchで入ってきた場合に対する予防策でしょう。
毎回メモリを確保する場合,特にswitchの最適化に影響が出ます。
#ジャンプテーブルが直接適用できなくなる。

No.7759

Re:宿題の答え
投稿者---こん!(2003/06/25 10:47:52)


>違います。for文の第三式が評価されるときにはすでに複文(ブロック)のスコープから外れています。
>
>forは,
for ( 第一式 ; 第二式 ; 第三式 ) 文
という形を取ります。
>これより明らかに,ループ本体は第二式・第三式の評価とは独立となります。

ごめんなさい。あまりに一足飛びで何がこれにより明らかになのか分かりませ
ん。もう少し段階を踏んでお教え願えませんか?
ちなみにループ本体とは何を指している言葉でしょう?

>また,第三式や第二式がループ本体のスコープだとすると,ループ本体が式文であった場合の扱いに困ります。

例えば?

>最初に一気にメモリを確保するのは,複文の真ん中にgotoやswitchで入ってきた場合に対する予防策でしょう。

gotoは分かりますがswitchでfor文のブロックに入ってくるとは?


No.7760

Re:宿題の答え
投稿者---こん!(2003/06/25 11:00:50)


そういえば、流れがここのスレッドからかなり趣旨が離れてしまった様です。
終わりにしましょう。

別に私がこの件で困っているわけではないので。
気がついたらだらだらとスレッドを伸ばしてしまいました。

こんなのだらだら話すならおしゃべり掲示板ですかね?

でもそれも変か?

失礼しました。m(__)m

No.7763

Re:宿題の答え
投稿者---YuO(2003/06/25 12:03:58)


>>違います。for文の第三式が評価されるときにはすでに複文(ブロック)のスコープから外れています。
>>forは,
for ( 第一式 ; 第二式 ; 第三式 ) 文
という形を取ります。
>>これより明らかに,ループ本体は第二式・第三式の評価とは独立となります。
>ごめんなさい。あまりに一足飛びで何がこれにより明らかになのか分かりませ
>ん。もう少し段階を踏んでお教え願えませんか?
>ちなみにループ本体とは何を指している言葉でしょう?

ループ本体とは,forの定義の「文」のことです。
そして,forの制御に関わる式(第一式〜第三式)は,ループ本体の中に書かれていません。
それ故,評価は独立ですし,スコープから外れているのです。

複文に関わる識別子のスコープは,
  • C90/C95ではその識別子の宣言
  • C99ではその複文の開始
から始まって}で終わります。
これはfor文でも変わりません。


簡単な実験としては,
#include <stdio.h>
int main (void)
{ /* scope 1 */
    int i, n = 10;
    for (i = 0; i < n; ++i) { /* scope 2 */
        int n = 0;
        printf("%i\n", i);
    }
    return 0;
}
というプログラムを実行して,iがいくつまで処理されるかを調べればよいです。
第二式がscope 2に存在するなら,このプログラムは構文エラーとなるはずです。
#C90/C95の場合。C99だとi < nのnが不定値なので動作は不定。

実際には,第二式はscope 1に存在しますから,0から9までの数字が表示されるはずです。


>>また,第三式や第二式がループ本体のスコープだとすると,ループ本体が式文であった場合の扱いに困ります。
>例えば?

式文だと,ループ本体にスコープが存在しません。
その場合,第三式・第二式はどこのスコープとして扱われるのでしょう。


>>最初に一気にメモリを確保するのは,複文の真ん中にgotoやswitchで入ってきた場合に対する予防策でしょう。
>gotoは分かりますがswitchでfor文のブロックに入ってくるとは?

私が書いたことは,for文のみならず,すべての複文に関してです。
#まぁ,forのループ本体にswitchで入り込むこともできますが。
例えば,
switch (i) {
case 1:
case 2:
    {
        int n = 0;
        if (i == 1) goto label;
    case 3:
        n = 1;
    label:
        printf("%i\n", n);
    }
    break;
}
のような場合に,i == 3だと定義の行をすっ飛ばしてcase 2ラベルに制御が移動します。
しかし,nは有効ですから,その為のオブジェクトを生成しなければいけません。
#初期化はしないです。
そして,i == 2の時はfall throughしてn = 1;が実行されます。
#で,switchの最適化が阻害される,と。


No.7765

Re:宿題の答え
投稿者---こん!(2003/06/25 12:38:52)


>簡単な実験としては,
#include <stdio.h>
int main (void)
{ /* scope 1 */
    int i, n = 10;
    for (i = 0; i < n; ++i) { /* scope 2 */
        int n = 0;
        printf("%i\n", i);
    }
    return 0;
}
というプログラムを実行して,iがいくつまで処理されるかを調べればよいです。
>第二式がscope 2に存在するなら,このプログラムは構文エラーとなるはずです。

お、そうか。そりゃそうですね。それなら分かる・・・

>式文だと,ループ本体にスコープが存在しません。
>その場合,第三式・第二式はどこのスコープとして扱われるのでしょう。

前例で解決。

>私が書いたことは,for文のみならず,すべての複文に関してです。

いや、今話していたのはfor文のスコープの事なのですからご自分の中で勝手にス
コープを広げられて話されても聞き手は分かりません。

>#まぁ,forのループ本体にswitchで入り込むこともできますが。

ので、別にむりやり例を上げて頂かなくても結構です。

投げっぱなしで勝手に抜けて失礼しました。

以上で私は閉めさせて頂きます。
参考になりました。
どうもありがとうございます。
m(__)m

No.7497

Re:構造体は難しい(^^;)
投稿者--- (2003/06/18 12:47:35)


>次のことがよくわかりません。
> *漢字氏名、ローマ字氏名、IDなどが書かれたCSV形式の名簿ファイルを標準入力からscanf()関数を用いて一行を単位で読み込み.ファイルの入力は,リダイレクションを用いる方法をおしえて下さい。

CSV 形式を1行単位なら、fgets()で1行分読み込み、
strtok() でトークン分割すべきでは?
scanf() だとエラー対応が難しいのでおすすめ出来ませんな。


No.7498

実は
投稿者---疾風(2003/06/18 12:51:24)


>CSV 形式を1行単位なら、fgets()で1行分読み込み、
>strtok() でトークン分割すべきでは?
>scanf() だとエラー対応が難しいのでおすすめ出来ませんな。

fgets()を使いたかったのですが、学校の課題なのでscanf()でないといけないのです。

No.7500

Re:実は
投稿者--- (2003/06/18 12:58:00)


>fgets()を使いたかったのですが、学校の課題なのでscanf()でないといけないのです。

scanf()なら素直に

char buf1[BUFSIZE],buf2[BUFSIZE],buf3[BUFSIZE];

scanf( "%s,%s,%s", buf1, buf2, buf3 );

と言う感じでいいのでは?

で、実行ファイルを作ったらリダイレクトを利用し

〜〜.exe < inputfile

でOK。

No.7505

Re:実は
投稿者---ちぇっこり(2003/06/18 13:18:50)


わかる範囲で、ソース化してみて下さい。
断片化してても可です。

それに、肉付けされ、解説が入ると思います。


No.7518

こんな感じで作ってみました。
投稿者---疾風(2003/06/18 14:51:18)


>それに、肉付けされ、解説が入ると思います。


こんな感じで作ってみたのですが・・・
実行すると文字化けする上に、同じ文書が延々と繰り返されてしまいます。

#include <stdio.h>

struct psrce{
char *romazi;
char *suzi;
struct psrce *next;
};

main()
{
struct psrce fw;

scanf("%s,%s",&fw.romazi,&fw.suzi);

printf("%s,%s",fw.romazi,fw.suzi);

}

実行ファイルはとりあえず以下のものを入れてやってみました。

abc,123,

No.7522

Re:こんな感じで作ってみました。
投稿者---ちぇっこり(2003/06/18 15:36:25)


これでは、、駄目!?

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

struct    psrce{
    char    *romazi;
    char    *suzi;
};

void    main()
{
    struct     psrce    fw;
    char    *tp;
    char    buf[1024];

    scanf("%s",buf);

    fw.romazi = strtok(buf,",");
    fw.suzi   = strtok(NULL,","); /*実際は、ココをうまくLOOPで・・*/

    printf("%s,%s",fw.romazi,fw.suzi);
}




No.7525

Re:こんな感じで作ってみました。
投稿者---ちぇっこり(2003/06/18 16:14:51)


char *tp;

いりません。。



No.7535

お答えいただきありがとうございますm(_ _)m
投稿者---疾風(2003/06/18 18:34:16)


>これでは、、駄目!?
>

おしえていただいたものを参考に、もう一度考えてみます。
またわからないところがありましたら手ほどきをお願い致します。

No.7524

Re:こんな感じで作ってみました。
投稿者--- (2003/06/18 15:42:20)


> scanf("%s,%s",&fw.romazi,&fw.suzi);

末恐ろしいコードですね…。
どこに書き込んでいるのかわかってるの?


No.7534

どういうことでしょう・・・
投稿者---疾風(2003/06/18 18:29:11)


>どこに書き込んでいるのかわかってるの?

どういう意味ですか?おっしゃってることがよくわからないのですが・・・

No.7536

Re:どういうことでしょう・・・
投稿者---あかま(2003/06/18 18:36:08)


とりあえず、このHPの文字列とscanfの部分を読んで、書き直してみてください。
ポインタを触り始めると良くあるミスですので、お気になさらず。
http://www9.plala.or.jp/sgwr-t/c/sec02.html#s2-4
http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-3

No.7540

勉強不足ですみません
投稿者---疾風(2003/06/18 18:55:40)


>とりあえず、このHPの文字列とscanfの部分を読んで、書き直してみてください。
>ポインタを触り始めると良くあるミスですので、お気になさらず。

アドバイスありがとうございます。まだ知識が曖昧なもので(^_^;)
もう一度練り直してきます。

No.7543

Re:どういうことでしょう・・・
投稿者---こん!(2003/06/18 20:12:08)


>ポインタを触り始めると良くあるミスですので、お気になさらず。
>http://www9.plala.or.jp/sgwr-t/c/sec02.html#s2-4
>http://www9.plala.or.jp/sgwr-t/c/sec05.html#s5-3

ついでですからこの辺もいかがでしょう。


No.7683

返事をくれた皆さまありがとうございました。
投稿者---疾風(2003/06/23 10:49:09)


ヒントやアドバイスをくれた皆さま、ありがとうございましたm(_ _)m
おかげで、課題ができあがりました。
感謝しています。本当にありがとうございました。

No.7684

Re:返事をくれた皆さまありがとうございました。
投稿者---こん!(2003/06/23 11:04:29)


>ヒントやアドバイスをくれた皆さま、ありがとうございましたm(_ _)m
>おかげで、課題ができあがりました。
>感謝しています。本当にありがとうございました。

またか・・・
お礼だけではなくどのようにして解決したのかの報告もしましょうよ。
(最終リストアップ等)

そうしないとこれまでレスを付けて下さった方々がはたして自分のレスで役に立
ったのかどうかがわからないでしょう。

No.7690

Re:返事をくれた皆さまありがとうございました。
投稿者---ゲンゴロウ(2003/06/23 14:47:19)


>またか・・・
>お礼だけではなくどのようにして解決したのかの報告もしましょうよ。

私は初心者なんですが、思ったことがあるので言わせてもらいたいんで
すけど、教えていただいた事を参考にして出来た結果をお礼として掲示
板に書き込むのは、当然だと思いますが、もう少しやわらかく言って
いただいた方が初心者の身としてはありがたいです。
書き込もうとしても、これは駄目かもしれないと思って書き込みしづら
いので・・・・。突然すみませんでした。

No.7693

Re:返事をくれた皆さまありがとうございました。
投稿者---ちぇっこり(2003/06/23 16:30:34)


>>もう少しやわらかく言っていただいた方が初心者の
>>身としてはありがたいです。


大丈夫ですよ!
 「丸投げ」とか・・
 「ご利用上の注意」に沿ってる方でしたら、
完成ソースに批判なんてしませんよ!

間違ってたり、代替案があったら、「こうした方がいい・・」
と教えてくれます。
  (私は、初心者なんで・・ちょっと難しくなると
      アドバイス出来なくなりますが・・・・・)

やっぱり、アドバイスした手前・・・
本当に出来たのかな? って思いはありますよ!


No.7699

Re:返事をくれた皆さまありがとうございました。
投稿者---とおりかかり(2003/06/23 17:22:52)


はじめまして

>私は初心者なんですが、思ったことがあるので言わせてもらいたいんで
>すけど、教えていただいた事を参考にして出来た結果をお礼として掲示
>板に書き込むのは、当然だと思いますが、もう少しやわらかく言って
>いただいた方が初心者の身としてはありがたいです。

ここのスレッドでなく、個人的に厳しいことを書かれた経験が
あるのですね。。
中には、「初心者なんですが、、」と始める投稿者に必要以上に
きつくあたる回答者もいます。。その背景には「初心者ですが、、」
といった言葉を振りかざしてマナーを無視した投稿者がいることに
あります。
以下のリンクが参考になります。
やさしく説明
http://www.hyuki.com/writing/techask.html
辛らつ説明(注意:心当たりの人には耳が痛いかもしれません)
http://www.geocities.co.jp/SiliconValley/5656/


>書き込もうとしても、これは駄目かもしれないと思って書き込みしづら
>いので・・・・。突然すみませんでした。

いや、あなたがマナーを意識していらしたら、ぜんぜん臆することは
ありません。どんどん書き込みましょう!

こんさんが最終的なレポートを出すように勧めているのは
こうした掲示板の目的が利用者の相互扶助にあることです。
個別の質問者の問題が解決したのが最終目的ではなく、
その解決に至るプロセスを残して他の利用者にも利用させる
ことにあります。
以下のリンクを見ると理解できるかと思います。
http://www.ed.kagawa-u.ac.jp/~akiyama/mac/News/tf/tf-manner.html