ネットが遅くてイライラしてない!?

C言語にて

構造体をポインタで繋いだ住所録等のサンプルプログラムは、本などで良く見かけますが、データの入力や検索のコードはあるのですが、”データ削除”のコードは載っていません。

データ削除は少し難しくなるのでしょうか?

データ削除が載っているサイトや本をご存知の方がみえましたら紹介ください。

よろしくお願いいたします。

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

A 回答 (2件)

    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

目次には有りますが、DLしたサンプルコードには
ないと思われます。

出来たら削除のサンプルコードが見たいのですが。

お礼日時:2003/08/28 08:47

ポインタのリンクの流れから削除したい構造体が外れるようにポインタの参照先を変更して、構造体のメモリを開放するだけでできると思いますが。



参考URL:http://www.wakhok.ac.jp/~kanayama/C/01/node140.h …

この回答への補足

ようやく見つけました。

http://www9.plala.or.jp/sgwr-t/c/A/rei15-5.html

補足日時:2003/08/28 12:40
    • good
    • 0
この回答へのお礼

回答ありがとう御座います。

特にやり方が判らない訳ではないのですが、
残念ながら当方、経験不足なため出来れば
コードの一部でなくちゃんと動く全コードを
いじって勉強したいと思いました。

それと疑問の一つとして、データ追加のサンプルは
いくらでもあるのに、削除のサンプルはありません。

追加の場合は、データの最後に追加する例が多く、
一方削除の場合は、どうしても途中のデータを削除しないと不自然であり、そうするとコードがやや難しくなるのかな?っと言ったあたりのことを知りたかったのですが。。。

お礼日時:2003/08/28 09:58

このQ&Aに関連する人気のQ&A

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

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

このQ&Aを見た人が検索しているワード

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

Q構造体のリスト削除

かれこれ1時間くらい悩んでいて
問題として

関数delete()を作成し、プログラムを完成させよ(~yabuki/p7.c)。
関数delete()は、与えられたデータをリストから削除するものである。
ただし、データが先頭であっても動作しなければならない。
次のように出力されるはずである。

NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> END
PREV jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END

NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> END
PREV hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END

NEXT sunyon[23] -> END
PREV sunyon[23] -> END

list ha nakunarimasita

/*******/の間に5行のプログラムを入れる。それ以外にmain()関数を
変更してはならない。

.........;の部分に構造体のメンバーを定義せよ。

というもので、Deleteしていくプログラムをつくりたいのですが
NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> END
PREV jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END

セグメントエラー

となり、続きができていません。
delete関数のif(p->next != NULL){ のところだけやると
最後まで出るみたいですが、うまくいってません
よろしくおねがいします。

↓ソースです・・・
#include <stdio.h>
#include <string.h>

struct kara {
char name[16];
int age;
struct kara *next;
struct kara *prev;
};

struct kara * delete(struct kara *,struct kara *);
struct kara * findend(struct kara *);
void* printforw(struct kara *);
void* printback(struct kara *);

int
main()
{
struct kara a, x, f, m, c, *start, *end, *p;
char name[128];

strcpy(a.name, "gyuri");
a.age = 23;
strcpy(x.name, "sunyon");
x.age = 23;
strcpy(f.name, "nicole");
f.age = 20;
strcpy(m.name, "hara");
m.age = 20;
strcpy(c.name, "jiyon");
c.age = 17;
a.next = &x;
x.next = &f;
f.next = &m;
m.next = &c;
c.next = NULL;
/********************* 5 lines */
a.prev = NULL;
x.prev = &a;
f.prev = &x;
m.prev = &f;
c.prev = &m;
/*********************/

start = &a;
end = findend(start);
printforw(start);
printback(end);
printf("\n");

p = &c;
start = delete(start, p);
if (start == NULL) {
printf("list ha nakunarimasita\n");
return 0;
} else {
end = findend(start);
printforw(start);
printback(end);
}
printf("\n");

x.next = NULL;
p = &a;
start = delete(start, p);
if (start == NULL) {
printf("list ha nakunarimasita\n");
return 0;
} else {
end = findend(start);
printforw(start);
printback(end);
}
printf("\n");

p = start;
start = delete(start, p);
//de senntou wo kaesu
if (start == NULL) {
printf("list ha nakunarimasita\n");
return 0;
} else {
end = findend(start);
printforw(start);
printback(end);
}

return 0;
}
struct kara *
delete (struct kara *start,struct kara *p)
{
/*if(p->next->next->next->next)
{
start = p->next->next->next->next;
}
*/
for(p = start;p != NULL;p = p->next)
{
start = p->next->next->next;
p = start;
}
/*
if(p->next)
{
start = p->next;
}
if(p->prev)
{
start = p->prev;
}

if(p->next != NULL){
p->next->prev = p->prev;
}
}
*/
return p;
}

struct kara *
findend(struct kara *start)
{
struct kara *pl;
for(pl = start;pl != NULL; pl = pl->next){
start = pl;
}
return start;
}

void*
printforw(struct kara *aa)
{
struct kara *pl;
printf("NEXT ");
for ( pl = aa; pl != NULL; pl = pl->next) {
printf("%s[%d] -> ", pl->name, pl->age);
}
printf("END\n");
}

void*
printback(struct kara *cc)
{
struct kara *pl;
printf("PREV ");
//for( ; cc != NULL;cc = cc->prev){
for (pl = cc; pl != NULL; pl = pl->prev) {
printf("%s[%d] ->", pl->name,pl->age);
}
printf("END\n");
}

かれこれ1時間くらい悩んでいて
問題として

関数delete()を作成し、プログラムを完成させよ(~yabuki/p7.c)。
関数delete()は、与えられたデータをリストから削除するものである。
ただし、データが先頭であっても動作しなければならない。
次のように出力されるはずである。

NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> jiyon[17] -> END
PREV jiyon[17] -> hara[20] -> nicole[20] -> sunyon[23] -> gyuri[23] -> END

NEXT gyuri[23] -> sunyon[23] -> nicole[20] -> hara[20] -> END ...続きを読む

Aベストアンサー

これを前提知識なしで出されたら、出題者が悪いと思いますが、そうでなかったらちゃんと授業を聞いていたかと問いただしたくなります。リストの削除の方法って授業で説明しませんでしたか?
他の人が書いたプログラムというのも勉強になると思いますので一応説明します。

deleteという操作は、リストから該当する要素を発見し、その要素を取り除くという操作で行います。
言い換えると、発見するというプログラムと取り除くというプログラムの組み合わせです。

まず、リストから所定の要素を探しだすというプログラムを書きましょう。
それは、こういうコードになるはずです。
struct kara *
find(struct kara *start, struct kara *to_find)
{
struct kara* cur;
for(cur = start;cur != NULL;cur = cur->next)
{
if (cur == to_find) {
printf("found %s %d\n", cur->name, cur->age);
return cur;
}
}
return NULL;
}
このプログラムはto_findに探したい要素のポインターを入れると、それを探しだして、printfで内容を表示した上でそれを返します。

次に、リストからの要素の削除です。
リストから要素を削除するという操作は、自分がいなかったかのようにポインターを付け替えるという操作です。
例えば、次のよなリストでbを消すことを考えます。
a -> b -> c

この場合、bが消えたあとの状態はこうなります。
a -> c

これは、bの指している先であるcをaの指し先に変更するということです。
言い換えると、bのprevのnextをbのnextにするということです。
よって、プログラムでやると b->prev->next = b->nextとなります。
また、prevについても同じ事をするのでb->next->prev = b->prevとなります。
ただし、リストの一番最後の要素に対して削除をする場合、b->nextは存在しないのでb->next->prev = b->prevの動作をする必要はありません。

まとめると、
if (b->prev != NULL) {
b->prev->next = b->next;
}
if (b->next != NULL) {
b->next->prev = b->prev;
}
となります。ただ、削除対象がstartだったとき b->prev == NULLのだけちょっとしたトリックが必要です。
この部分を実際のプログラムに起こすと書くとこんなかんじです。
struct kara *
delete (struct kara *start,struct kara *p)
{
struct kara* to_delete = find(start, p);
if (to_delete != NULL) {
if (to_delete->prev != NULL)
to_delete->prev->next = to_delete->next;
else /* head of the list. */
start = to_delete->next;

if (to_delete->next != NULL)
to_delete->next->prev = to_delete->prev;
}
return start;
}

以上でdelete関数が出来上がりました。


余談ですが、最後の要素を毎回手繰るというのは無駄な操作なので、こういうことをしたい場合は普通はtailqというtailを指すポインタを持つ両方向リンクリストを使うのが普通だと思います。

ついでに余談ですが、リスト操作はコンピュータサイエンスの基礎知識ではありますが、基本的にやることは決まっているので、queue.hなどを使って書くのが普通だと思います。
ちょろっと調べたら、そのtailqの内部構造を解説したページを見つけたので参考までに。
http://d.hatena.ne.jp/koseki2/20120105/tailq

もう一つ余談を言うと、セグメントエラーが出るようなプログラムで動きを確かめるにはgdbを使うと良いです。gdbを使うと、どこでセグメントエラーが出ているか一瞬でわかるので、とりあえず治すのは格段に早くなります。
今回の場合、gdbを使うとstart = p->next->next->next;で出ていると一発でわかります。まぁ、わかったところで上記のようなコードを書かないと動かないのですが。

では、頑張って。

これを前提知識なしで出されたら、出題者が悪いと思いますが、そうでなかったらちゃんと授業を聞いていたかと問いただしたくなります。リストの削除の方法って授業で説明しませんでしたか?
他の人が書いたプログラムというのも勉強になると思いますので一応説明します。

deleteという操作は、リストから該当する要素を発見し、その要素を取り除くという操作で行います。
言い換えると、発見するというプログラムと取り除くというプログラムの組み合わせです。

まず、リストから所定の要素を探しだすというプロ...続きを読む

Qファイルから読み込んだデータを構造体に格納できますか?

1レコード19バイトのファイルを
読み込む処理を行っています。

地区名10バイト
県名8バイト
改行1バイト

このデータをdouken(構造体)に格納したいのですが
>while (fgets(dou,19,fp) != NULL){
で、エラーになってしまいます。

どのようにしたら
ファイルから読み込んだデータを
構造体に格納できますか?


#include<stdio.h>
#include <stdlib.h>

struct douken {
char tiku[10];
char ken[8];
}

main(void){

FILE *fp;
struct douken dou[100];
int i;

fp = fopen("ex3.fil","rb");

if ( fp == 0 ){
printf("can't open\n");
exit(1);
}

while (fgets(dou,19,fp) != NULL){



1レコード19バイトのファイルを
読み込む処理を行っています。

地区名10バイト
県名8バイト
改行1バイト

このデータをdouken(構造体)に格納したいのですが
>while (fgets(dou,19,fp) != NULL){
で、エラーになってしまいます。

どのようにしたら
ファイルから読み込んだデータを
構造体に格納できますか?


#include<stdio.h>
#include <stdlib.h>

struct douken {
char tiku[10];
char ken[8];
}

main(void){

FILE *fp;
struct douken dou[100];
int i;

...続きを読む

Aベストアンサー

>>while (fgets(buffer,20,fp) != NULL){
>と、するということですか?
>その場合、
>ここのサイズは必ず4の倍数になるということですよね?
構造体を直接扱うと、アーキテクスチャやコンパイラ依存してしまいます。
32bit機なら4byteですし、16bit機なら2byte。64bit機なら8byteです。
また、コンパイラの設定によってもどのように確保されるかまったく分からないのです。
一度バッファに蓄えてからmemcpyでコピーする方が安全ですし、可搬性があります。
C言語では\0を文字列の終端文字として使用しているので、10文字格納したいなら11byte確保する必要もあります。
簡単に修正してみました。

#include <stdio.h>
#include <stdlib.h>
#include <memory.h>

typedef struct douken_ {
char tiku[11];
char ken[9];
} douken;

int main(void){
FILE *fp;
douken dou [100];
char buff [18 /* douken */ + 1 /* LF(\n) */ + 1 /* \0 */];
int i;
i = 0;

fp = fopen("ex3.fil","rb");

if ( fp == 0 ){
printf("can't open\n");
exit(1);
}

// douを\0で埋める
memset (dou , '\0' , sizeof dou);

// 一度バッファに格納
while (fgets(buff,sizeof buff,fp) != NULL){
// memcpy関数でコピー
memcpy(&dou[i],buff,10);
memcpy(&dou[i],buff+10,8);

// 構造体配列より大きなファイルを開いたときの配慮
if (i == 99) break;
i++;
}

return 0;
}

>>while (fgets(buffer,20,fp) != NULL){
>と、するということですか?
>その場合、
>ここのサイズは必ず4の倍数になるということですよね?
構造体を直接扱うと、アーキテクスチャやコンパイラ依存してしまいます。
32bit機なら4byteですし、16bit機なら2byte。64bit機なら8byteです。
また、コンパイラの設定によってもどのように確保されるかまったく分からないのです。
一度バッファに蓄えてからmemcpyでコピーする方が安全ですし、可搬性があります。
C言語では\0を文字列の終端文字として使用して...続きを読む

QLNK2019: 未解決の外部シンボルのエラーが出る

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自キャラのデータ
Point2D g_jikipos = {40, 400};//自キャラの座標

//画像ハンドル
int g_jikiimage[11];

//色々なファイルの読み込み
int LoadFiles(){
//画像ファイル読み込み
if(LoadDivGraph("media\\player01.bmp",
11,11,1,64,64,g_jikiimage) == -1) return -1;

return 1;
}


 mymain.h
//他から呼び出させるMyMainの関数
void MyMain();
int LoadFiles();


 myhelper.h(サンプルなので打ちミスはない)
#include "DxLib.h"
#include <limits.h>
#include <math.h>

//構造体宣言
//座標またはベクトルを記録する構造体
struct Vector{
float x,y;
};
typedef Vector Point2D;
//線を記録する構造体
struct Line2D{
Point2D startpos, endpos;
float katamuki;//傾きをラジアン値で記録
Vector speed;//移動している場合は速度をセット
};
//球体を記録する構造体
struct Ball2D{
Point2D position;
float hankei;//半径
};
//四角形を記録する構造体
struct Rect2D{
Point2D lefttop;
Point2D rightbottom;
float width;
float height;
};


//ライブラリ関数
Point2D PosInView(Point2D in);
int XInView(float inx);
int YInView(float iny);
void ScrollToLeft(float jikiposx);
void ScrollToRight(float jikiposx);
void ScrollToUp(float jikiposy);
void ScrollToDown(float jikiposy);
void DrawLineInView(float x1, float y1, float x2, float y2, int Color, int Thickness);
void DrawCircleInView(float x, float y, float r, int Color, int FillFlag);
void DrawAnimation(float x, float y, double ExtRate, double Angle,int TurnFlag,
int *imgarray, int allframe, float fps);
//ベクトル関数
Vector CreateVector(Vector in, float veclen);
Vector AddVector(Vector v1, Vector v2);
Vector SubVector(Vector v1, Vector v2);
Vector AddVectorInFrameTime(Vector pos, Vector speed);
Vector AddVectorInFrameTime2(Vector pos, Vector speed, Vector accel);
Vector Normalize(Vector in);
Vector RotateVector(Vector in, float radian);
float VectorLengthSquare(Vector in);
float DotProduct(Vector v1, Vector v2);
float CrossProduct(Vector v1, Vector v2);
void SetLine2DKatamuki(Line2D *in);
void DrawLine2D(Line2D in, int Color, int Thickness);
void DrawBall2D(Ball2D in, int Color, int Fill);
//当たり判定関数
bool HitTestLineAndBall(Line2D linein, Ball2D ballin);
bool IsPointAtLineFace(Line2D linein, Point2D ptin);
bool HitTestLineAndLine(Line2D line1, Line2D line2);
bool HitTestBallAndBall(Ball2D a, Ball2D b);
bool HitTestPointAndBox(Rect2D rect, Point2D pt);
//タイマー関数
void SetSimpleTimer(int idx, int time);
int GetPassedTime(int idx);


//グローバル変数
extern float g_frametime;
extern Rect2D g_framerect;//画面領域(当たり判定)
extern Point2D g_current_field_pos;//現在の左上座標
extern Rect2D g_stagesize;//ステージサイズ

//定数宣言
const float ZEROVALUE = 1e-10f;
const float PIE = 3.1415926f;
const int SCROLL_LIMIT = 200;
----------------------------------------------------------------
 エラー内容
1>myhelper.obj : error LNK2019: 未解決の外部シンボル "void __cdecl MyMain(void)" (?MyMain@@YAXXZ) が関数 _WinMain@16 で参照されました
1>C:\Documents and Settings\Owner\My Documents\Visual Studio 2008\Projects\my\Debug\my.exe : fatal error LNK1120: 外部参照 1 が未解決です
1>my - エラー 2、警告 0
ビルド: 0 正常終了、1 失敗、0 更新不要、0 スキップ
----------------------------------------------------------------
画像を貼り付けときます
(見えにくい場合→http://www.dotup.org/uploda/www.dotup.org154142.jpg.html)
初心者なのでわかりやすくお願いします

Microsoft Visual Studio 2008
Version 9.0.21022.8 RTM
Microsoft .NET Framework
Version 3.5 SP1
----------------------------------------------------------------
新しいプリジェクト→Win32 コンソール アプリケーション(ソリューションのディレクトリを作成 チェック外す)→Windows アプリケーション(空のプロジェクト チェック外す)
----------------------------------------------------------------
 プログラム

 mymain.cpp
#include "myhelper.h"
#include "mymain.h"

//自...続きを読む

Aベストアンサー

ファイル構成から推測するに
mymain.cpp というファイルに
void MyMain(void) {
// ここに処理を書く
}
という関数が必要なようです。

Q構造体配列内の文字列検索のよい方法を教えてください

struct S_Data
{
----char ID[16];
----char PW[16];
};
とし、
S_Data Data[100];
とします。

IDとPWを入力すると、100個のID・PW群からその組み合わせがあるかを検索し、その結果を返したいのですが、いい方法が思いつきません。

単純にやるとすれば、入力されたID、PWをそれぞれid、pwとすると
for( int i=0 ; i<100 ; i++ )
{
----if( strcmp(Data[i].ID,id) == 0 )
----{
--------if( strcmp(Data[i].PW,pw) == 0 )
--------{
------------return 1;
--------} else {
------------return -1;
--------}
----}
}
return 0;
とすればいいのですが、もっと簡単にやる(実行速度が速い)方法はないでしょうか?

Aベストアンサー

検索が一回きりなら、提示の方法が一番早いでしょう。
相当回数検索するなら、ソートしてバイナリサーチとか。
使用される文字に制限があるなら、先頭文字の種類ごとに配列を分けるとか。
たとえば、IDがすべて数値なら、配列を10に分割できますよね。
ハッシュを使うという方法もありますが、100件くらいだと、効果はあまりないかもしれません。

Qint型からchar型への変換

タイトル通り、int型からchar型への変換の仕方がわかりません!><
どうしたらいいのでしょうか?

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

no = 10;
sprintf(buf, "%d", no);

Qfgetsで拾われる改行文字を削除したい

お世話になります

 C言語初心者のものです。今課題でC言語を用いたプログラミングを
Fedora上でやっています。問題は、fgetsでテキストファイルから、取得
した文字列の中から改行文字を削除できないことです。文字変数のアド
レスはわかっているのですが、終端文字に置換しようとすると、セグメ
ントエラーになってしまいます。これは如何にして解決すべきでしょう
か。よろしくお願いします。

Aベストアンサー

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが最大文字数に達したり、ファイルの最後になったりで、strに改行文字が含まれない場合には、このループは止まりません(Segmentension Falutになって止まる)

・そのような状態になってないか、予めチェックする
・ループを終了させる仕組みを用意しておく
: forの終了条件を記述する、for中で if(*(str+i)=='\0') { break;} 等としておく、等
といった対策が必要です。


あと細かいところを言えば
・strを配列で用意したなら *(s+i)じゃなくてs[i]でいいんじゃないかな
・あるいは char *pみたいにしておいて、 iのループでなく pでループを組む( for(p=str;*p!='\0';p++) )とか。

ポインタとかアドレスとか、C言語の用語としてあるものを別の意味に使うとまぎらわしいです。

「ポインタ」「アドレス」と言われたら、 この例なら str, str+i が思い浮びます。
「文字変数のアドレス」だと
char c ;
に対しての
&c
が思い浮びます。

配列なら「添字」、意味的には「x文字目」ですね。

> for(i=0;;i++){
> if(*(str+i)=='/n') {
> *(str+i)='\0';
> break;
> }
> }
/nが\nの間違いなら、この方法で半分正解です。もう少し広い範囲(可能なら全体)で見ないことにはなんとも言えません。
fgetsが...続きを読む

Qscanf("%s", buf);でスペースを含んだ文字

コンソールプログラムで
scanf("%s", buf);
を使用してユーザに入力された文字によって処理を行いたいのですが、このままではスペースを含む文字列がスペースの手前で切られてしまいます。
C:\Program Filesなどを入力可能にさせたい場合にはどのようにするのがベターですか?

Aベストアンサー

お任せください!
そもそもscanfを使うというのはお勧めでは
ありません。scanfは文字+改行文字が入力
されないと完了しないためです。
が、それは良しとしましょう。
scanfの書式ですが、

int n = scanf("%[^\r\n]",buf);

という便利な書式があります。
perlでもおなじみの書式ですね。
上記の山文字"^"より前が読み込ませたい文字の集まりで、ハイフン指定が出来ます。
"^"より後ろが読込みを停止させたい文字の集まりです。上記の指定は復帰改行以外の文字が現れるまで読み込みます、という書式です。
下記のような指定も出来ます。

int n = scanf("%[a-zA-Z0-9\\: \t^\r\n]",buf);

なお、戻り値は読み込んだ項目数ですので、
if(n >= 1)
{
}
で判断できますね。

Q構造体の初期化方法について

こんばんわ。
何度も申し訳ありません。

VC++.NET 2003を用いてコンソールプログラミングを行っています。前回この掲示板を利用して複数回実行するプログラムを作成し、そこに構造体を用いたプログラムを作成しました。以下に概要を示します。

グローバルで構造体を宣言しているため、複数回実行を行うプログラムでは前回の値が格納されたままであると思い、毎回実行時に構造体の初期化を行いたいと思っています。

そこで、以下に示します構造体の初期化はどのように記述すればよいのでしょうか?0で初期化したいと思っています。

よろしくお願い致します。

#define MAX 2000
//グローバル
struct tag{
int Npkt;
int gettime;
int rPkt;
int lossPkt;
}rdata[MAX];

main(){
  //for文で複数回実行処理
  for(i=0;i<=5;i++){
  //ここで構造体の初期化を記述する
//例として、5回プログラムを実行する
  }
}

こんばんわ。
何度も申し訳ありません。

VC++.NET 2003を用いてコンソールプログラミングを行っています。前回この掲示板を利用して複数回実行するプログラムを作成し、そこに構造体を用いたプログラムを作成しました。以下に概要を示します。

グローバルで構造体を宣言しているため、複数回実行を行うプログラムでは前回の値が格納されたままであると思い、毎回実行時に構造体の初期化を行いたいと思っています。

そこで、以下に示します構造体の初期化はどのように記述すればよいのでしょうか?0で初...続きを読む

Aベストアンサー

★まとめ
・既に『memset』関数や、『ZeroMemory』関数の回答があるので構造体の全体、1部の
 初期化の記述例を紹介します。
・それと『#include <memory.h>』を記述しないとメモリ関係の関数が利用できません。
 『ZeroMemory』関数の場合は『#include <windows.h>』があればそのまま利用できます。

●構造体全体を初期化
ZeroMemory( rdata, sizeof(rdata) ); または、
memset( rdata, 0, sizeof(rdata) ); です。

●構造体一部を初期化
ZeroMemory( &rdata[i], sizeof(struct tag) ); または、
memset( &rdata[i], 0, sizeof(struct tag) ); です。
※rdata[i]の1データだけ初期化します。

余談:
・『ZeroMemory』関数は Win32 API と分類されていますが、実体は『memset』関数に
 『#define』されているだけです。でも、戻り値を『VOID』型にキャストされているので
 『memset』関数のリターン値を取得できません。→第一引数のアドレスが『memset』関数
 ではリターンします。
・以上。おわり。

参考URL:http://taka.no32.tk/tips/Win32/ZeroMemory.html

★まとめ
・既に『memset』関数や、『ZeroMemory』関数の回答があるので構造体の全体、1部の
 初期化の記述例を紹介します。
・それと『#include <memory.h>』を記述しないとメモリ関係の関数が利用できません。
 『ZeroMemory』関数の場合は『#include <windows.h>』があればそのまま利用できます。

●構造体全体を初期化
ZeroMemory( rdata, sizeof(rdata) ); または、
memset( rdata, 0, sizeof(rdata) ); です。

●構造体一部を初期化
ZeroMemory( &rdata[i], sizeof(struct tag) ); または、
m...続きを読む

Qファイルの中身検索と表示

Cでの作成についてなんですが、
fopenでテキストファイルを開き、テキストの中身の
特定文字が含まれている行を新に作ったファイルの中に
書き込みたいんですが、テキストの中身の検索と
抽出方法がいろいろ試してみましたがわかりません。
よろしくお願いします。

Aベストアンサー

★文字列の検索関数を使えば良い。
・テキストの中身の検索は、行単位で文字列を取得(fgets)してから、この文字列内に
 検索文字列の有無をチェックします。この有無は文字列から文字列を検索する関数
 『strstr』関数を使うのが便利です。また、文字列から1文字の検索を行う場合は
 『strchr』関数を使います。質問では、特定の文字が含まれている行となっていますが
・検索するのは1文字、文字群、文字列のどれですか?
 これによっていろいろと代わりますよ。処理が…。
・とりあえず文字列から特定の文字列を含まれた行を抽出するサンプルを下に載せます。

サンプル:
char buff[ 256 ];
char *find = "検索文字列";
FILE *fp; ←読み込み用
FILE *fo; ←抽出用

省略(fopen×2つ)

while ( fgets(buff,sizeof(buff),fp) != NULL ){
 if ( strstr(buff,find) != NULL ){
  fputs( buff, fo );
 }
}

省略(fclose×2つ)

解説:
・上記のサンプルでは、行単位でテキストの中身を取得して、この文字列から検索文字列(find)が
 含まれるか『strstr()』関数でチェックしています。見つかると『NULL』以外を返します。
・そして、見つかったらば行単位で『fputs』関数で出力しています。
 これで見つかった行だけが、新たに作ったファイルに書き込まれていきます。→抽出です。
・また『strstr()』関数の部分を
 『if ( strchr(buff,'a') != NULL ){ … }』とすると『a』の文字が含まれる行のみを抽出します。
 『if ( strspn(buff,"+-*/") != 0 ){ … }』とすると『+-*/』の文字群が含まれる行のみを抽出します。
 検索する文字とは、1文字、文字群、文字列のどれですか?
・以上。おわり。→上記のを参考にして下さい。

参考URL:http://www9.plala.or.jp/sgwr-t/lib/strspn.html,http://www9.plala.or.jp/sgwr-t/c/sec17.html

★文字列の検索関数を使えば良い。
・テキストの中身の検索は、行単位で文字列を取得(fgets)してから、この文字列内に
 検索文字列の有無をチェックします。この有無は文字列から文字列を検索する関数
 『strstr』関数を使うのが便利です。また、文字列から1文字の検索を行う場合は
 『strchr』関数を使います。質問では、特定の文字が含まれている行となっていますが
・検索するのは1文字、文字群、文字列のどれですか?
 これによっていろいろと代わりますよ。処理が…。
・とりあえず文字列から特定...続きを読む

QC言語で構造体のメンバを簡単に出力する方法ありますか?

いつもお世話になっています。

C言語の質問です。
単体テストログを取るために、
“関数Aをコールする前後で、関数Aに引数として渡す構造体のメンバをすべて”printf(もしくはfprintf)で出力して比較確認しなければならないのですが、

構造体のメンバが250とか、150とかあり、メンバ名もxxx_01,xxx_02などのようにエクセルなどで簡単に加工して作れるものではないので、いちいちメンバ名を指定しなければならないのでとても大変です。

オブジェクト指向言語なら、for each文とかでオブジェクトのメンバを簡単に取り出せるのでしょうが(間違っているかもしれません・・・)、C言語で構造体のメンバを、for文などのループを使って簡単に出力できる方法はないでしょうか?

メンバの型は、一定ではなく、char、int、double、別の構造体のポインタ型(これは出力しなくて良い)と混在しています。メンバが全て同一の型ならポインタで構造体の先頭アドレスからsizeof(メンバの型)の分インクリメントしていけば出力できそうな気もしますが、メモリ上に連続して確保されるのかも私にはわからないので困っています。

enumで列挙して・・・というのも調べてみましたが、応用は出来ないようでした。

どなたか、地道にメンバ名を書いて出力する以外の方法をご存知の方、いらっしゃいましたらお知恵をお貸しください。
よろしくお願いいたします。
※説明不足の点がありましたら補足いたします。

いつもお世話になっています。

C言語の質問です。
単体テストログを取るために、
“関数Aをコールする前後で、関数Aに引数として渡す構造体のメンバをすべて”printf(もしくはfprintf)で出力して比較確認しなければならないのですが、

構造体のメンバが250とか、150とかあり、メンバ名もxxx_01,xxx_02などのようにエクセルなどで簡単に加工して作れるものではないので、いちいちメンバ名を指定しなければならないのでとても大変です。

オブジェクト指向言語なら、for each文とかでオブジェクトのメンバを...続きを読む

Aベストアンサー

コードを書かないという方向性の提案を一つ。
デバッガに構造体の内容を出力させるというのはどうでしょうか。

struct {
int a;
char *b;
double c;
}
という型を持つ変数xがあったとして、gdbでは下記のような出力が得られます。
(gdb) print x
$1 = {
a = 123,
b = 0x2fd0 "ABC",
c = -9876.5
}


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング