gooポイントが当たる質問投稿キャンペーン>>

なかなか前に進めず、困っています。(泣)現在、構造体とファイル検索を考えてるのですが、皆様にアドバイスを頂けたらと思っています。お願い致します。
テキストファイルの内容は自分で適当に作りました。このようにしています。
→ファイル名(soccer.txt)ファイルの中身→ 例「 番号,名前,年齢 」
1 ,川口 能活,33
38,楢崎 正剛,40
20,川島 永嗣,22
10,中澤 佑二,35
51,駒野 友一,19
9 ,中村 俊輔,29
22,遠藤 保仁,17
15,鈴木 啓太,32
19,本田 圭佑,51
28,家長 昭博,25
30,高原 直泰,18
7 ,播戸 竜二,44

☆ /*記述*/ としているところへどのようにプログラムを書けばよいのかわかりません。(泣)どなたか教えて頂けないでしょうか。お願い致します。

サンプル:
// 最大のデータ数
#define MAX_LIST (100)

// 関数のプロトタイプ宣言
void read_data( FILE *fp, struct data list[], size_t size );
void print_data( struct data list[], size_t size );
void search_num( struct data list[], size_t size );
void search_name( struct data list[], size_t size );
void search_age( struct data list[], size_t size );

// メイン関数
int main( void )
{
 struct data list[ MAX_LIST ]; 
 FILE *fp;
 int menu;
 
 if ( (fp = fopen("soccer.txt","r")) != NULL ){
  read_data( fp, list, MAX_LIST ); 
  fclose( fp );
  
  do {
   printf( "条件を選択して下さい[1~4]\n" );
   printf( " 1:全部表示\n" );
   printf( " 2:番号で検索\n" );
   printf( " 3:名前で検索\n" );
   printf( " 4:年齢で検索\n" );
   printf( "99:終了\n" );
   scanf( "%d", &menu );
   
   switch ( menu ){
    case 1: print_data( list, MAX_LIST ); break;
    case 2: search_num( list, MAX_LIST ); break;
    case 3: search_name( list, MAX_LIST );break;
    case 4: search_age( list, MAX_LIST ); break;
    default: break;
   }
  } while ( menu != 99 );  
  return 0;
 }
 printf( "soccer.txt - ファイルが見つかりません。\n" );
 return 1;
}

// テキストデータを読み込む専用関数
void read_data( FILE *fp, struct data list[], size_t size )
{
 /* 記述 */
}

// 構造体の内容を表示する専用関数
void print_data( struct data list[], size_t size )
{
 /* 記述 */
}

// 番号で検索
void search_num( struct data list[], size_t size )
{
 /* 記述 */
}

// 名前で検索
void search_name( struct data list[], size_t size )
{
 /* 記述 */
}

// 年齢で検索
void search_age( struct data list[], size_t size )
{
 /* 記述 */
}

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

A 回答 (6件)

登録件数にもよりますが、


grep で検索した結果をチェックした方が楽そうですね。
そのサンプル・コードだと、機能によってファイルの読み方も違うの?
読んだ内容を識別し、どうチェックするかを、関数ポインタで機能を切り替えて実行すれば、それで済むことじゃないの?

私の場合は、Excelでオート・フィルタ? で対処します。
今使えるものを使った方が楽だから。

csvファイルの先頭に int, string,int とか、型定義な要素があると
使えるかもしれないね。
    • good
    • 0

どこかで見たコードだと思いましたが、


回答者さんの参考コードそのままですね。。。
>個人情報の掲載や誰かの書いたものをそのまま転記するなどの・・・
#とりあえず禁則事項に触れてる気がしますが。

アドバイスっていうのはあくまでも『助言』であって、
解答をそのまま教えることではありません。
あなたが何を理解していて、何が理解できないのか、
という情報が無ければ、アドバイスのしようも無いと思います。

また、検索の仕様が曖昧です。
例えば、番号は重複することは無い(そういう仕様なら)でしょうが、
年齢や名前というのは、重複する可能性があります。(今回はたまたま無い)そういったものはどうするのでしょうか?
・最初に見つかったものだけ見つかったことにする。
・全部見つかったことにして個数を数える。
・そもそも重複を許可しない。
など

できれば、あなたがここまでやって、
分からなかったという部分まで説明してください。
    • good
    • 0

★アドバイス


>書けないから投稿しました。すみませんでした。
 ↑
 本当かな。前回の質問で search_all() 関数はファイルから行単位で読み込んで処理を
 行っていますよ。これを元に読み込み専用の read_data() 関数が作れますけど。
・あと前回のサンプルの補足ですが、search_num()、search_name()、search_age() 関数の
 内部で scanf() 関数を使ってキーボードから検索番号、検索名、検索年齢を入力する部分を
 記述して下さい。main() 関数ではメニューの振り分けだけに scanf() でキーボード入力を
 行っています。
・検索番号の search_num() だけ下のサンプルに載せておきますので残りの検索名、検索年齢、
 データ読み込み、データ表示は頑張って作成してみて下さい。

サンプル:
// 番号で検索
void search_num( struct data list[], size_t size )
{
 size_t i;
 int num;
 
 // 入力部
 printf( "\n検索する番号を入力して下さい:" );
 scanf( "%d", &num );
 printf( "\n\n" );
 
 // 検索
 for ( i = 0 ; i < size ; i++ ){
  if ( list[i].no == num ){
   /*
   番号検索で見つかったときの表示
   */
   return;
  }
 }
 /*
 見つからなかったときのエラー表示
 */
}

その他:
・上記のサンプルを見れば分かると思いますが、そんなに難しくはありません。
 名前の検索、年齢の検索は上記のを参考にすれば直ぐにできると思います。
 頑張って作成してみて下さい。
・あと print_data() 関数は上記のサンプルで入力部をなくして構造体のデータを
 順番に printf() していけば出来ます。前回の質問であった search_all() に
>printf("%s %s %s \n", lis->no, lis->name, lis->age);
 ↑
 この1行がありますよね。
 上記のサンプルの『検索』の for ループに printf() の1行を記述すれば
 print_data() 関数は出来ますよ。
・以上。
    • good
    • 0

とりあえず一部コードを書いてみます。

C言語を書くのは久しぶりなので、間違っていても責めないでください(笑)。

#define MAXBUF 256
#define DELIMITER ","

// テキストデータを読み込む専用関数
int read_data( FILE *fp, struct data list[], size_t size )
{
char buf[MAXBUF], *s_st, *s_nxt;
int cnt=0;

while (fgets(buf, MAXBUF, fp) != NULL) {
s_st = buf;
s_nxt = strtok(buf, DELIMITER);
if (s_nxt != NULL) {
/* 選手の番号 */
*s_nxt = '\0';
list[cnt].no = atoi(s_st);
s_st = s_nxt + 1;
}
s_nxt = strtok(NULL, DELIMITER);
if (s_nxt != NULL) {
/* 選手の名前 */
*s_nxt = '\0';
strcpy(list[cnt].name, s_st);
s_st = s_nxt + 1;
}
s_nxt = strtok(NULL, DELIMITER);
/* 選手の年齢 */
if (s_nxt != NULL) {
*s_nxt = '\0';
}
list[cnt].age = atoi(s_st);
if (++cnt >= size) {
break;
}
}
list[cnt].no = (-1); /* データの終わり */
return cnt;
}

// 全ての構造体の内容を表示する専用関数
int print_all_data( struct data list[], size_t size )
{
int cnt;
for (cnt=0; (cnt<size) && (list[cnt].no >= 0); cnt++) {
/* 1つの構造体の内容を表示 */
print_data(&list[cnt]);
}
return cnt;
}

// 番号で検索
int search_num( struct data list[], int search_num, size_t size )
{
int cnt, scnt=0, snum_min, snum_max;
switch (search_num) {
/* 検索条件の振り分け */
case 1: snum_min = 1; snum_max = 9; break;
case 2: snum_min = 10; snum_max = 19; break;
case 3: snum_min = 20; snum_max = 29; break;
case 4: snum_min = 30; snum_max = 0x7fffffff; break;
default: snum_min = (-1); snum_max = (-1); break;
}
for (cnt=0; (cnt<size) && (list[cnt].no >= 0); cnt++) {
if ((list[cnt].no >= snum_min) && (list[cnt].no <= snum_max) ) {
/* 条件に合う構造体の内容を表示 */
print_data(&list[cnt]);
scnt++;
}
}
return scnt;
}

こんなところでしょうか。
print_data() は1つの構造体を出力するだけですから、書けますよね。
search_name() や search_age() は、上記 search_num() を基に、適宜書き換えれば良いはずです。
また、main() の中の search_~() を呼ぶ前に、条件を入力する処理を追加してください。
分からない関数があったら、linuxの man ~ とか、参考URLで調べてください。

参考URL:http://www.linux.or.jp/JM/
    • good
    • 0

http://okwave.jp/qa3114524.html

の続き。というかまるで進んでませんな。
ちょっとは自分で書こうよ。

この回答への補足

書けないから投稿しました。すみませんでした。

補足日時:2007/06/29 02:16
    • good
    • 0

で、その構造体の定義は?

    • good
    • 0

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

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

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

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

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

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件くらいだと、効果はあまりないかもしれません。

Q文字列がNULLか空文字列かの判定

Visual C++で、Cのプログラムを作成しているものです。(OS:WinNT 4.0)
文字列の扱いについて、質問します。

関数 int func(char *str) があると仮定します。
パラメータとして、strは以下のような状態あるとします。
(strは関数が呼ばれる前にcalloc()で領域確保済み)
 シンボル名 値
 str      0x00000001 ""
上記の状態で、strがNULLか空文字列("")であることを条件式にしたいのですが、str == NULL は偽となり、strcmp(str, "") を使用すると異常終了します。
どうしたらよいのでしょうか。アドバイスをお願いします。

Aベストアンサー

No1の方の回答にあるように、calloc()で取れた領域のアドレスを正しく渡せてないように思えますが...

#defineERROR(-1)

int func(char *str)
{
  if( (!str) || (!strlen(str)) ) return ERROR;
  return strlen(str);
}

void main()
{
  char *p=(char*)calloc(10,10);
  printf("%d\n",func(p));
}

Qcsvファイルのデータを構造体に

csvファイルのカンマを数えて任意の文字列を抜き出すまでは出来たのですがそこから構造体に格納するまでがこちらのサイトでも検索しましたがよくわかりません。
ご指摘のほどよろしくお願いします。
csvデータ
番号,名前,住所,電話,年齢,性別
1,佐藤,東京,1234,33,A
2,田中,,5678,22,
3,坂井,名古屋,,,B


番号,住所,電話,年齢を格納する場合
struct k_data {
char no[4];/* 出来れば番号を右詰めにしたい */
char add[20];
int tel;
int age;
} kaiin[256];
/* 文字列を抜き出す↓ */
int main(void)
{
FILE *fp1,*fp2;
char dat[256];
char *ch;
int cnt;

/* fp1 ファイルオープン */
/* fp2 ファイルクローズ */

while (fgets(dat, 256, fp1) != NULL) {
cnt = 0;
for (ch = dat; *ch != '\0'; ch++) {
if (*ch ==',') {
if (cnt == 0) {
putc(*ch, fp2);
}
if (cnt == 2) {
putc(*ch, fp2);
}
if (cnt == 3) {
putc(*ch, fp2);
}
if (cnt == 4) {
putc('\n', fp2);
}
cnt++;
} else {
if (cnt == 0) {
putc(*ch, fp2);
}
if (cnt == 2) {
putc(*ch, fp2);
}
if (cnt == 3) {
putc(*ch, fp2);
}
if (cnt == 4) {
putc(*ch, fp2);
}
}
}
putc('\0', fp2);
}
fclose(fp2);
fclose(fp1);
}

csvファイルのカンマを数えて任意の文字列を抜き出すまでは出来たのですがそこから構造体に格納するまでがこちらのサイトでも検索しましたがよくわかりません。
ご指摘のほどよろしくお願いします。
csvデータ
番号,名前,住所,電話,年齢,性別
1,佐藤,東京,1234,33,A
2,田中,,5678,22,
3,坂井,名古屋,,,B


番号,住所,電話,年齢を格納する場合
struct k_data {
char no[4];/* 出来れば番号を右詰めにしたい */
char add[20];
int tel;
int age;
} kaiin[256];
/...続きを読む

Aベストアンサー

まず、取得データをファイルに書き込むのではなく、内部に格納バッファを用意してそこに一時バッファとして格納してください。
CSV仕様上、改行('\n')が要素の終端を表しますので、まず、CSVファイルから1行づつバッファに読み込み、そのバッファデータからカンマ検索実施の上各構造体メンバにセットすればよいと思います。

QC++ 構造体の一括初期化 {0}

構造体変数に {0} を代入すると、CString は空文字、 intは0に一括で初期化されるようです。
なんでこんなことが出来るのでしょう?
{0}は何?
仕組みを教えて下さい!!

Aベストアンサー

> 一括初期化関数でも作るしかなさそうですね
static変数を初期化用に用意しておくのはいかが?
http://oshiete.goo.ne.jp/qa/2658268.htmlより
>静的記憶域期間をもつオブジェクトを明示的に初期化しない場合、
>次の規定に従う。
>a) そのオブジェクトの型がポインタ型の場合、空ポインタに初期化する。
>b) そのオブジェクトの型が算術型の場合、(正または符号なしの)0に初期化する。
>c) そのオブジェクトが集成体の場合、各メンバにa)~d)の規定を(再帰的に)
>適用し初期化する。
>d) そのオブジェクトが共用体の場合、最初の名前つきメンバにa)~d)の規定を
>(再帰的に)適用し初期化する。

なので、zero初期化されていることが、規格で保証されます。

typedef struct hoge_struct
{
 int a;
 int b;
} hoge_struct;

static hoge_struct initializer; //初期化用変数。値は変えない。

int main(void)
{
 hoge_struct hoge;
 hoge = initializer;
 return 0;
}
真っ白に何度も初期化したいなら、こんな感じでどうでしょう?
関数を用意して初期化すると、構造体のメンバが増えると関数も修正しないといけない
ですが、これだと関数を変更しなくてすむし。

> 一括初期化関数でも作るしかなさそうですね
static変数を初期化用に用意しておくのはいかが?
http://oshiete.goo.ne.jp/qa/2658268.htmlより
>静的記憶域期間をもつオブジェクトを明示的に初期化しない場合、
>次の規定に従う。
>a) そのオブジェクトの型がポインタ型の場合、空ポインタに初期化する。
>b) そのオブジェクトの型が算術型の場合、(正または符号なしの)0に初期化する。
>c) そのオブジェクトが集成体の場合、各メンバにa)~d)の規定を(再帰的に)
>適用し初期化する。
>d) そのオブジェクトが共用...続きを読む

Qfgetsなどのときのstdinのバッファを消すには?

こんにちは,今C(C++でない)を使用しています。
たとえば,
char str[20]
fgets(str,sizeof(str),stdin)
としたときに20字以上を打つと,stdinのバッファに20字以上の分が残ったままになります。

C++などでは
fflush(stdin)で,うまくいきますが,普通のCでは対応がされていないみたいでうまくいきません。

よろしくお願いします。

Aベストアンサー

あ,テキスト入力だからこんな大掛かりなことしなくてもいいんだ.
末尾に'\n'が出るまで掃出せばいいんですよね.

fgets(str, sizeof(str), stdin);
if ( str[strlen(str)-1] != '\n' ){
while( getchar() != '\n' );
}

でいいんだ.失礼しました.

Qint型からchar型への変換

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

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

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

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を文字列の終端文字として使用して...続きを読む

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...続きを読む

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が...続きを読む

Q引数 戻り値 return文について

今、C言語を初めて勉強してます。

勉強していて、引数と戻り値、return文

についてよくわかりません。

どなたか詳しく素人にもわかるように教えて

頂けないでしょうか?よろしくお願いします。

Aベストアンサー

まず、関数とは何らかの処理をして結果を返してくれるものです。わざとらしい例ですが二つの数を足してその結果を返す関数を見てみましょう。

#include <stdio.h>

int add( int hoge, int piyo ){
return hoge + piyo;
}

int main(void){
int data;

data = add( 253, 434 );
printf( "%d", data );

return 0;
}

見てわかると思いますが、引数とは関数内の処理に使うデータです。
このデータは関数を呼び出すときに与えます。

add( 253, 434 )

すると与えられたデータは関数に渡され仮引数と言うものに格納されます。
この例では hoge に 253、piyo に 434 が格納されます。

int add( int hoge, int piyo ){

この仮引数は普通の変数のように使うことが可能なのです。

hoge + piyo

そしてこの結果を戻り値として return 文で返してやります。

return hoge + piyo;

返すとは具体的にどこへ返すのかと言うと呼び出したところへです。
ここでは main 関数内の呼び出し元です。

data = add( 253, 434 );

data と言う変数へは関数によって返された戻り値(関数値とか返却値とかとも言ったりします)が格納されます。つまり 253 と 434 を足した数です。

引数も戻り値も結局はデータです。処理させたいデータが引数で、処理した結果であるデータが戻り値です。

return は呼び出し元へ結果を返すためのものです。


C言語の関数にはいろいろな種類があります。

引数も戻り値もあるもの。

int add( int hoge, int piyo ){
return hoge + piyo;
}

引数はあるが戻り値のないもの。

void add( int hoge, int piyo ){
printf( "%d", hoge + piyo );
}

戻り値はあるが引数のないもの。

#include <stdlib.h>
#include <time.h>

int getRandNum(void){
srand( time( NULL ) );
return rand() % 500;
}

戻り値も引数もないもの。

void print(void){
printf( "%d + %d = %d", 253, 434, 253 + 434 );
}

これらの使い分けはデータの内容や型、処理の内容により適宜必要なものを使ってください。

まず、関数とは何らかの処理をして結果を返してくれるものです。わざとらしい例ですが二つの数を足してその結果を返す関数を見てみましょう。

#include <stdio.h>

int add( int hoge, int piyo ){
return hoge + piyo;
}

int main(void){
int data;

data = add( 253, 434 );
printf( "%d", data );

return 0;
}

見てわかると思いますが、引数とは関数内の処理に使うデータです。
このデータは関数を呼び出すときに与えます。

add( 253, 434 )

すると与...続きを読む


人気Q&Aランキング