AIと戦って、あなたの人生のリスク診断 >>

現在C言語で簡単なプログラミングを書いているのですが、
構造体(1)(下記参照)から、構造体(2)(下記参照)への代入の方法がわからず悩んでいます。もしよければ手を貸してください!!
標準関数などがないということはわかったので、
地道に代入を行いたいです。

イメージ・・・(data[n].b = moji[n].d;)

(1)struct list_kouzou{
int a;
char b[30];
char c[8];
}data[100];

(2)struct list_tai{
char d[30];
}moji[15];

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

A 回答 (4件)

★アドバイス


>標準関数などがないということはわかったので、
 ↑
 memcpy() 関数が利用できます。→回答者 No.2 さんを参考に。
 strcpy() 関数も利用できるかも。→回答者 No.1 さんを参考に。
 ※char b[]、char d[] が文字列ならば strcpy() 関数が利用できますが、何かのデータ
  ならば安全のために memcpy() で配列全体をコピーします。データ内容によって決める。
>地道に代入を行いたいです。
 ↑
 ループを組んで代入したいのですか。
 それなら下のサンプル関数などを作ってコピーしてみる。

サンプル関数:
void listcopy( struct list_kouzou *data, struct list_tai *moji )
{
 char *pdata = data->b; ←list_kouzou 構造体の char b[30] へのポインタ
 char *pmoji = moji->d; ←list_tai 構造体の char d[30] へのポインタ
 int i;
 
 for ( i = 0 ; i < sizeof(data->b) ; i++ ){
  *pdata++ = *pmoji++; ←地道にコピー
 }
}

// 使い方
int main( void )
{
 struct list_kouzou data[ 100 ];
 struct list_tai moji[ 15 ];
 int n;
 
 /*
 構造体 data、moji への代入処理
 */
 for ( n = 0 ; n < 15 ; n++ ){
  listcopy( data[n], moji[n] ); ←イメージに近い処理(data[n].b = moji[n].d)
 }
 /*
 その他の処理
 */
 return 0;
}
    • good
    • 0
この回答へのお礼

大変にわかりやすい回答をありがとうございます。
これを参考に、がんばろうと思います!!!

お礼日時:2007/06/21 17:25

代入に関数を使わない場合は、



#include <stdio.h>

typedef struct list_kouzou{
int a;
char b[30];
char c[8];
}data[100];

typedef struct list_tai{
char d[30];
}moji[15];

void main (void)
{
data a;
moji b;
unsigned int i,maxA,maxB,indexA=0,indexB=0;

for (i=0,maxA=(maxA=sizeof(a[indexA].b)/sizeof(a[indexA].b[0]))<(maxB=sizeof(b[indexB].d)/sizeof(b[indexB].d[0]))?maxA:maxB;i-maxA;i++) a[indexA].b[i]=i+1;

i^=i;while (i-maxA) b[indexB].d[i++]=a[indexA].b[i];

for (i=0;i<maxA;i++) printf("%d ",b[indexB].d[i]);
printf("\r\n");
return;
}

のようにします。
    • good
    • 0
この回答へのお礼

回答ありがとうございます。大変に参考になりました。
少々難易度が高く感じられた(簡単であればすみません)ので、今後の参考にさせていただきたいと思います。

お礼日時:2007/06/21 17:34

.bと.dが文字列とは限らないので...



memcpy(data[n].b, moji[n].d, 30);
    • good
    • 0
この回答へのお礼

memcpyという関数があるのですね。
すみません、勉強不足でした。

'\0'がつかないというのは、大変に便利な関数を教えてくださいまして、ありがとうございます!

お礼日時:2007/06/21 17:18

「イメージ」として書かれたとおりのことであれば、


strcpy(data[n].b, moji[n].d);
で可能な気がします。
    • good
    • 0
この回答へのお礼

strcpyでは、あまり、うまく行かなかったのです。strcpyでも、構造体同士の代入が出来るのですね?

どうも、ありがとうございます!

お礼日時:2007/06/21 17:14

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

このQ&Aを見た人はこんなQ&Aも見ています

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

QC言語 ファイルの指定された行を表示

こんにちは。
回答お願いします。
今私は作業の高効率化を目指すためプログラムを考えています。
まだぜんぜんできていませんが・・
ファイルの指定された行を表示する関数がないだろうか?
もしくは似たような方法はないだろうかと考えています。

できれば例題とともに教えていただければ幸いです。
具体的にどういう風にしたいのかというと
----test.txt-------
aaaa
bbbbb
cccccc
dddd
eeeeeeee
ffffff
-------------------
というファイルがあったとしたらgetsで4と入れてやったら
四行目のddddが表示されるようにしたいのです。
まだまだ初心者ですのでさっと考えることができません。
どうかご教授お願いします。

Aベストアンサー

★高効率を目指しているの?
・固定長データなら高効率で1行を取得できたりします。
 例えば
 ----test.txt-------
 aaaaa
 bbbbb
 ccccc
 ddddd
 eeeee
 fffff
 -------------------
 という固定長データ(5文字×6行)の場合は
 int no = 4; ←4行目を取得したい時
 fseek( fp, ((no - 1) * 7), SEEK_SET ); ←5文字+\r+\n=『7』
 fgets( buff, sizeof(buff), fp );
 ↑
 これなら行番号で指定した1行を fgets() 関数で取得可能です。
 ※なおバイナリモードでオープンして下さい。
・可変長データの場合は行の先頭のオフセット位置を最初の読み込みで管理します。
 例えば
 ----test.txt-------
 aaaa
 bbbbb
 cccccc
 dddd
 eeeeeeee
 ffffff
 -------------------
 という可変長データ(4,5,6,4,8,6文字)の場合は
 オフセット位置の配列を行数分用意します。→事前に分かれば楽ですね。行数。
 long offset[ 100 ]; ←100行だと仮定
 int max;
 
 for ( max = 0 ; !feof(fp) ; max++ ){
  if ( max >= 100 ){ ←安全対策
   break;
  }
  offset[ max ] = ftell( fp );
  fgets( buff, sizeof(buff), fp );
 }
 ↑
 ここまでがオフセット位置の読み込みです。次は読み出しです。
 int no = 4; ←4行目を取得したい時
 fseek( fp, offset[no - 1], SEEK_SET );
 fgets( buff, sizeof(buff), fp );
 ↑
 これで行番号で指定した1行を fgets() 関数で取得可能です。
 ※やっぱりバイナリモードでオープンして下さい。
・あと行数の指定時に 1~max の範囲になるように補正処理も入れたほうが良いかも。
 例えば
 if ( no < 1 ){
  no = 1;
 }
 else if ( no >= max ){
  no = max;
 }
 ↑
 こんな感じで。
・以上を参考にして下さい。
 下の『参考URL』もどうぞ。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/fseek.html

★高効率を目指しているの?
・固定長データなら高効率で1行を取得できたりします。
 例えば
 ----test.txt-------
 aaaaa
 bbbbb
 ccccc
 ddddd
 eeeee
 fffff
 -------------------
 という固定長データ(5文字×6行)の場合は
 int no = 4; ←4行目を取得したい時
 fseek( fp, ((no - 1) * 7), SEEK_SET ); ←5文字+\r+\n=『7』
 fgets( buff, sizeof(buff), fp );
 ↑
 これなら行番号で指定した1行を fgets() 関数で取得可能です。
 ※なおバイナリモードでオープンして下さ...続きを読む

Q戻り値で構造体を返すことは可能でしょうか?

perlでは以下のように2つの戻り値が可能ですが、C言語では
それができるのでしょうか?
my (ret1, ret2) = test1();

よくやるのは、引数にポインタを渡して、内容を書き換える手を使っていますが、戻り値を複数返せたら、直感的にわかりやすいかなと思いまして・・・

Aベストアンサー

C言語から遠く離れた者ですが、

>>> よくやるのは、引数にポインタを渡して、内容を書き換える手を使っています

これが常識でしょう。これが直感的に理解できるようにC言語を身に付ける必要があるのではないでしょうか。

Qスレッドの終了はどうやるんですか?

VCでスレッドの終了をしたいと考えてます。
自分自身のスレッドを終了するときは、AfxEndThread関数を使うようですが、動作中のスレッドを外から命令して終了させるときはどうすれば良いのか分からないです。教えていただけないでしょうか?

Aベストアンサー

こんにちは。itohhといいます。

スレッドを終了させる方法は結構難しいですよ。

TerminateThread 関数を使用すれば、とりあえず強制終了させることは出来ます。
ただし、MSDNライブラリーにも記載されていますが、危険な方法です。
この関数で終了させられたスレッドは、終了処理が出来ません、ということは、
メモリリークを起こす可能性が大です。

一番まともな方法は、WM_CLOSEを対象スレッドにPostMessageすることです。
この場合は、メッセージループを内蔵するユーザーインターフェイススレッド
にする必要があります。
またこの場合でも、デッドロックしているスレッドでは、終了できないと思います。

わたしが、良く行う方法は、
ワーカースレッドの場合:
  ・シグナルを使用して、適時チェックする。(それなりに遅くなるのが難点)
  ・自然に終わるのを待つ。
ユーザーインターフェイススレッドの場合:
  ・WM_CLOSEを対象スレッドにPostMessageする。(デッドロックしないようなロジックにする)

こんにちは。itohhといいます。

スレッドを終了させる方法は結構難しいですよ。

TerminateThread 関数を使用すれば、とりあえず強制終了させることは出来ます。
ただし、MSDNライブラリーにも記載されていますが、危険な方法です。
この関数で終了させられたスレッドは、終了処理が出来ません、ということは、
メモリリークを起こす可能性が大です。

一番まともな方法は、WM_CLOSEを対象スレッドにPostMessageすることです。
この場合は、メッセージループを内蔵するユーザーインターフェイススレッ...続きを読む

Qfgets( ) の返り値は何?

fgets( ) はファイル終端に行くと0を返すらしいけど
それ以外の場合は何を返すんですか?

if( fgets( buf, 10, fp ) == 0 ) break;

のように、fgets( ) の返り値をそのまま使うことはできたけど
試しに、

char ret[255];
ret = fgets(buf, 10, fp);

とするとコンパイルエラーでした。

Aベストアンサー

すみません、根本的な回答ではありませんでしたね。
バッファを読み込めた時は、読み込んだバッファの先頭ポインタを返します。
ファイルの終わり(EOF)や失敗した時はNULLを返します。

Q「memcpy」と「strcpy」について

C言語の初心者です。
先日、課題として以下のようなことを言われました。

「memcpyとstrcpyについて、メモリ破壊が起こるとしたら
どんな場合が考えられるか、簡単にまとめて報告してみて下さい。」
と言われました。

私にはメモリ破壊というニュアンスが分からないのですが、
どちらの関数も必要以上にコピーを行ったときに
起こるメモリ破壊ということなのでしょうか?
それとも、何か特別な意味があるのでしょうか?

C言語に詳しい方がいましたら、是非、教えて下さい。
宜しくお願いします。

Aベストアンサー

 メモリ破壊とは、「当然そこに入っているべき値」を、不用意に上書きしてしまうことです。

 たとえば、char a[100]; という宣言をしたとします。

 memcpy( a, 0, 200 );

 すると、このような実行を行った場合、変数 a の後ろにどんなメモリが存在しているのかプログラマは知ることができないのに、変数 a の後ろの未定メモリ100バイトを上書きしてしまいます。

 この未定メモリには、もしかしたら別の変数があるかもしれませんし、プログラムの一部があるかもしれません。あるいはOSのシステム領域かもしれません。
 どのみちプログラムは正常に動かなくなります。
 通常はメモリエラーが出て停止しますが、最悪の場合、メモリ上のOSを破壊してリセットするしかなくなったりもします。

 これがメモリ破壊です。

Q ポインタを使って関数の値のやり取り

c言語の問題なのですが、2つの異なる1次元配列の積をseki関数を使って計算してもうひとつの配列に入れてmain関数で表示するのですが、うまく走りません原因がわかる人がいた教えてください。
作った実行文は、
#include<stdio.h>
int seki(int *pa,int *pb,int *pc);
main(){
int a[]={5,2,3,5,3,2,4,8,9,9,7},b[]={4,3,8,4,6,2,8,9,1,6,4},c[11]={0};
int i,*pa,*pb,*pc;

pa=&a;
pb=&b;
pc=&c;

seki(pa,pb,pc);
for(i=0;i<11;i++)
printf("%d,",*(pc+i));

}
int seki(int *pa,int *pb,int *pc){
int j;
for(j=0;j<11;j++)
*(pc+j)=*(pa+j) * *(pb+j);
}
こんな表示が出てきます。
toi2.c: In function `main':
toi2.c:7: warning: assignment from incompatible pointer type
toi2.c:8: warning: assignment from incompatible pointer type
toi2.c:9: warning: assignment from incompatible pointer type
たぶんmain関数内で書いたseki関数の引数の型に問題があると思うのですが。

c言語の問題なのですが、2つの異なる1次元配列の積をseki関数を使って計算してもうひとつの配列に入れてmain関数で表示するのですが、うまく走りません原因がわかる人がいた教えてください。
作った実行文は、
#include<stdio.h>
int seki(int *pa,int *pb,int *pc);
main(){
int a[]={5,2,3,5,3,2,4,8,9,9,7},b[]={4,3,8,4,6,2,8,9,1,6,4},c[11]={0};
int i,*pa,*pb,*pc;

pa=&a;
pb=&b;
pc=&c;

seki(pa,pb,pc);
for(i=0;i<11;i++)
printf("%d,",*(pc+i));

}
int seki(int *pa,int *pb,i...続きを読む

Aベストアンサー

質問の下に書かれているコンパイルエラーと思われる表示から
そのエラーの原因が読み取ることが出来ます。
ここでの原因は、プログラム中次の3行がエラーであると指摘されています。
7行目:pa=&a;
8行目:pb=&b;
9行目:pc=&c;
それぞれ、どういう状況かというと、
エラーをそのまま訳せば
『ポインタとしての割り当て方がおかしいですよ』
という風に捉えられます。
まず、整数型配列として宣言してあるaという変数があります。
これは、これ自身がポインタであるので
&aという表記では、『ポインタ変数aのポインタ』ということになり、
純粋なポインタ変数paには代入する事ができません。
よって、上のエラーを解消するには、
pa = a;
とすればよいでしょう。
(8,9行目も同様)

Qchar*を初期化したいのですが

Cの標準関数だけで
char*を初期化したいのですが
どの様にすればいいのでしょうか?

char* a = "aaaa";
char* b = "bbbb";
strcat( a, b );//"aaaabbbb"?
とし使いまた後で
aにまた値を入れ直したいので
初期化して再利用したいのですが

どのようにすればいいのでしょうか?

ポインタとかもうっすら(ほとんどわかりません)
よろしくお願いいたします

Aベストアンサー

> char* a = "aaaa";
> char* b = "bbbb";
> strcat( a, b );//"aaaabbbb"?
この上のコードは間違っていますよ。
変数a、bに入っているのはあくまでも文字列の"ポインタ"です。
従いまして、strcat( a, b );とすると、aがさしているメモリは5バイトしかないのでメモリを破壊してしまいます。
static char sza[] = "aaaa";
static char szb[] = "bbbb";
char szBuffer[256];
char* a = szBuffer;
strcpy (a, sza);
strcat (a, szb);
としないとだめです。

またポインタ変数はNULLで初期化可能です。

Q文字列を後ろから1文字ずつ表示する

初歩的なプログラミングです。
C言語の勉強中で、タイトルの通りの
プログラムを作りたいのですが、
何かヒントを頂けないでしょうか。

自分で書いてみて失敗したのは下記の
通りです。

char s[11];
int i=0;

printf("文字列入力(10文字以内-->)");
gets(s);
printf("s=%s",s);

while(s[i]!='\0'){
i++;
}

while(i=0){
printf("%c\n",s[i-1]);
i--;
}

宜しくお願いします。

Aベストアンサー

最後の表示部分のwhileの条件がおかしいですね。

while(i=0){
printf("%c\n",s[i-1]);
i--;
}

では、iに0を代入した真偽を見て、真ならループする様になっています。

while(i>0){
printf("%c\n",s[i-1]);
i--;
}

でうまくいくでしょう。

Qファイル出力で改行を入れたい!

data.txtにファイル出力を行うのですが、gets(c)で入力した一語一語に改行を入れてdata.txtに出力したいのですがどうすればよいでしょうか。
返答のほどよろしくお願いいたします。
include<stdio.h>
#define SIZE 20
void main(void)
{
char c[SIZE], *p;
FILE *fp;

fp = fopen("data.txt","w+");
p = c;
while(gets(c) != NULL){
fputs(p,fp);
}

fclose(fp);
printf("data.txtへ出力しました\n");

}

Aベストアンサー

一語一語ってのは、1回の入力毎って事でしょうか?
とするならば、これでどうでしょうか?

#include <stdio.h>
#define SIZE 20
void main(void)
{
  char c[SIZE], *p;
  FILE *fp;
  
  fp = fopen("data.txt","w+");
  p = c;
  while(gets(c) != NULL){
    fputs(p,fp);
    fputc('\n', fp);
  }
  
  fclose(fp);
  printf("data.txtへ出力しました\n");
  
}

Q戻り値の意味がわかりません…

戻り値とはどういう値なのか簡単な例文で教えて頂けますか?

Aベストアンサー

バカくさいかもしれませんが簡単な例えをだしてみます。
2人の子供がいて、名前をそれぞれ太郎・花子にしましょう。この2人の子にある役割を決めます。
・花子は飴をもらうと、それをチョコにする役割。(できるかは別として)
・太郎は花子を呼んで飴をあげる役割。

さてこの例では太郎の飴が引数(ひきすう)になり
花子のチョコが戻り値になります。

このイメージを元に次の文を読んでみてください。

「プログラム中の関数やサブルーチンが処理を終了し
呼び出し元に処理の結果として返す値。」

これが戻り値の正しい定義です。
そのほかにはNo1さんのような役割指すときも、それを「戻り値」と呼んだりします。


人気Q&Aランキング