出産前後の痔にはご注意!

単語を昇順でソートするプログラミングでエラーが出て困っている者です。
エラーが出てる箇所のみ抜粋して、あとは省略したものが下記です。
下記の2つの関数の下の方の関数で

間接参照のレベルが'char **'と'char[10][20]'で異なっています

read_wordsの型が2の仮引数および実引数と異なります

と言うエラーが現れます。main関数内のsortword関数、display_words関数でも同様にエラーが現れます。
これらの原因は何でしょう。また、僕は何がわかってないですか?
ここどこを勉強しろ、等のアドバイスでも結構ですのでぜひご指導ください。お願いします。


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

#define LINE_SIZE 20
#define MAX_LINES 10


char line[MAX_LINES][LINE_SIZE];


int num;
int read_words(char *fname,char **line,int num)//用意した構造に文字列を格納
{
FILE *fp;//ファイルポインタの宣言

int i = 0;//繰り返し変数の初期化

if((fp = fopen(fname,"r")) == NULL)//ファイルがあるかの確認
{
printf("ファイルを開けません\n");//ファイルが無い時はエラーメッセージを出す
exit(1);//エラー時は強制終了
}

fp=fopen(fname,"r");
fscan(fp,"%d",&line);
for(i=0;i<MAX_LINES;i++)//1列ずつ文字列を入れる制御構造
{
fscanf(fp,"%s",&line[i]);//ファイルから文字列を変数に入力
i++;//繰り返し変数の増加
}
num=line[0];//単語数を戻り値とする
fclose(fp);//ファイルのクローズ
}




int main(int argc,char *argv[])
{
read_words(argv[1],line,int num);
sortword(line,num);
display_words(line,num);
}

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

A 回答 (6件)

開発環境が書かれていませんが、書いた方が回答者が回答しやすいと思います。



> int read_words(char *fname,char **line,int num)
この関数の第2引数はchar **型なのに、

> char line[MAX_LINES][LINE_SIZE];
> read_words(argv[1],line,int num);
呼び出すときの型が char[MAX_LINES][LINE_SIZE]型になってしまっています。

関数の引数を以下のどれかに変更すればとりあえずそのエラーは出なくなると思います。
int read_words(char *fname,char line[MAX_LINES][LINE_SIZE] ,int num)
int read_words(char *fname,char line[][LINE_SIZE] ,int num)
int read_words(char *fname,char *line[LINE_SIZE] ,int num)

なお、このことに関する詳しいことは下記のページを見てください。
http://www.st.rim.or.jp/~phinloda/cqa/cqa17.html


あと気になったところとして、
> char line[MAX_LINES][LINE_SIZE];
グローバル変数にする必要がないので、main関数内で宣言した方がよい。

> fscan(fp,"%d",&line);
・fscanになっている。
・%dなのに&lineが整数型でない。(&lineはchar *型)
・仮に%sの間違いの場合、
&lineは間違いではないけど、意味的にline[0]にした方が分かりやすそう。
(後ろでline[0]で使ってますし。)

> fscanf(fp,"%s",&line[i]);//ファイルから文字列を変数に入力
・lineがchar **型でもchar[MAX_LINES][LINE_SIZE]型でも
&line[i]の型はchar型になる。
ここに要求されるのはchar *型なのでline[i]とするべき。

> num=line[0];//単語数を戻り値とする
・戻り値と書いてあるのにreturnで返していない。(コメントが嘘)
ここはグローバル変数numを作らなくてもコメント通りreturnで返せばよいと思いますよ。
そうすればnumをグローバル変数にする必要もなくなります。
・int型のnumにchar *型のline[0]を代入するのは変。(ポインタが代入されるけどそれでいいの?)

> read_words(argv[1],line,int num);
・int numはおかしい(intはいらない)。


> また、僕は何がわかってないですか?
あえて言えば、ポインタ・配列が絡んだ"型"がよく分かっていないなという感じがしました。
    • good
    • 0

#include<stdio.h>


#include<errno.h>
#include<stdlib.h>
#include<string.h>

#define LINE_SIZE 20
#define MAX_LINES 10

void
read_words(char *fname, char line[][LINE_SIZE], int *num)
{
FILE *fp;
int i;
if ((fp = fopen(fname, "r")) == NULL) {
printf("ファイル%sを開けません\n", fname);
exit(errno);
}
for (i = 0; i < MAX_LINES; i++) {
if (fgets(line[i], LINE_SIZE, fp) == 0) {
break;
}
line[i][strlen(line[i]) - 1] = 0;
}
fclose(fp);
*num = i;
}

void
display_words(char line[][LINE_SIZE], int num)
{
int i;
for (i = 0; i < num; i++) {
printf("%d: %s\n", i + 1, line[i]);
}
}

int
strsort(const void *p, const void *q)
{
return (strcmp(p, q));
}

void
sortword(char line[][LINE_SIZE], int num)
{
qsort(line, num, LINE_SIZE, strsort);
}

int
main(int argc, char *argv[])
{
char line[MAX_LINES][LINE_SIZE];
int num;

read_words(argv[1], line, &num);
sortword(line, num);
display_words(line, num);
return 0;
}
    • good
    • 0

もうだいぶはなれてしまったので気の付いた点だけ。


for(i=0;i<MAX_LINES;i++)//
でカウントアップしてるのに
i++;//繰り返し変数の増加
とは?
    • good
    • 0

すみません。

一部不正確なところがありました。
>> fscan(fp,"%d",&line);
>・%dなのに&lineが整数型でない。(&lineはchar *型)
%dの時は続く引数はint型へのポインタ(int*)である必要があるので間違いです。
(整数型である必要があるというのは間違いです。)
    • good
    • 0

とりあえず、気の付いた点


char **line で受けた場合、一行の大きさはどのようにしてわかるのでしょうか?
この時 line[i] は、何を指していますか
>fscan(fp,"%d",&line);
は、何を取り込もうとしているのでしょうか?
    • good
    • 0

char line[MAX_LINES][LINE_SIZE]


と char** とが異なる型だからです.

int read_words(char *fname,char **line,int num)

int read_words(char *fname,charline[MAX_LINES][LINE_SIZE],int num)
に変えればとりあえずエラーはなくなると思いますよ.
    • good
    • 0

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

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

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

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

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

QC言語の課題について

C言語の会員名簿処理問題の課題をしています。

次の条件でC言語で会員番号を入力するとその会員番号を持つ会員名を表示する
プログラミングを組んでいますが、コンパイルに失敗してしまいます。
何度も見直して修正を施してみたのですが、うまくいきません。
是非お力添えをお願いします。

<条件>
(1)会員番号と会員名は構造型でグローバル変数として宣言する。

(2)データ件数は10件とする。

(3)サブ関数で線形探索するプログラムを組み(my_search関数とする)、メイン関数で呼び出す。

(4)my_search関数の型はchar*とする。

(5)探索に成功したらmy_search関数の戻り値は該当会員の氏名とする。

(6)探索に失敗したらmy_search関数の戻り値はNULLとする。

(7)main関数では,関数my_searchの戻り値がNULLなら該当データがないことを
伝えるメッセージを出力して終了させる.
そうでなければ,該当の氏名を出力して終了させる.


下に組んだプログラムとコンパイル結果を貼り付けます。

/*
z:\情報システム論_2013>cl js010703_a106906.c
Microsoft(R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.

js010703_a106906.c
js010703_a106906.c(48) : warning C4047: '==' : 間接参照のレベルが 'int' と 'void
*' で異なっています。
js010703_a106906.c(58) : error C2040: 'my_search' : 'char *(int)' は 'int ()' と
間接操作のレベルが異なります。

z:\情報システム論_2013>
*/

#include <stdio.h>

#defineN10
#defineMAX20

struct Mystruct{
intnumber;
charname[MAX];
};

struct Mystruct meibo[N] = {
{10, "asaoka"},
{20, "ito"},
{23, "kawano"},
{25, "shimizu"},
{31, "setoguchi"},
{34, "tomiyama"},
{37, "murakami"},
{38, "yasuda"},
{46, "yoshino"},
{49, "yoshikawa"}
};

int main()
{
intx;
charp;

printf("会員番号を入力してください。\n");
printf("会員番号:");
scanf("%d", &x);
printf("入力された会員番号の会員は");

p = my_search(x);

if(p==NULL){
printf("存在しません。");
}else{
printf("%s", p);
}

return0;
}

char * my_search(int a)
{
intj = 0;

while(j<N){
if(a==meibo[j].number){
returnmeibo[j].name;
break;
}else{
++j;
}
returnNULL;
}
}


どうしても、この2つのエラーが消えません。
修正点を詳しく教えていただけないでしょうか。
よろしくお願いします。

C言語の会員名簿処理問題の課題をしています。

次の条件でC言語で会員番号を入力するとその会員番号を持つ会員名を表示する
プログラミングを組んでいますが、コンパイルに失敗してしまいます。
何度も見直して修正を施してみたのですが、うまくいきません。
是非お力添えをお願いします。

<条件>
(1)会員番号と会員名は構造型でグローバル変数として宣言する。

(2)データ件数は10件とする。

(3)サブ関数で線形探索するプログラムを組み(my_search関数とする)、メイン関数で呼び出す。

(4)...続きを読む

Aベストアンサー

C言語の大原則は「使う前に宣言/定義」です。
他の言語だと、この順番でも問題無い場合がありますが、C言語の場合は
> p = my_search(x);
ここで使うものを、この後で
> char * my_search(int a)
と宣言/定義してはいけません。

この場合、 int my_search() (引数任意、戻り値intの関数my_search) が宣言されているとして、コンパイルが進みます。
その結果、実際の char * my_search(int a) とは引数や戻り値違う、ということになり、エラーになります。
それが
「js010703_a106906.c(58) : error C2040: 'my_search' : 'char *(int)' は 'int ()' と間接操作のレベルが異なります。」
のメッセージの意味です。
明示的に宣言しようとしている 'char *(int)' と 暗黙に宣言された 'int ()' が違う、と言っているのです。

修正方法は2とおり。
・定義自体を使う前(この場合、main関数の前)に記述する。
・使う前のプロトタイプ宣言で引数と戻り値を明示しておく。

プロトタイプ宣言については、参考書等で調べてください。
「おまじない」と言われる #include <stdio.h> の役割りの一つが、「プロトタイプ宣言を他のファイルから読みこんで、定義済みの関数を正しく使えるようにする」というものです。


> js010703_a106906.c(48) : warning C4047: '==' : 間接参照のレベルが 'int' と 'void*' で異なっています。

こちらは正確には「警告(warning)」です。
「間違い」ではありません。コンパイルも終了します。
内容を理解し、問題無い場合は無視してもかまいません。
ただし、警告が出る箇所は、問題がある場所がほとんどです。警告を出さないプログラムを目指しましょう。

この場合も == の左右で型が違う、と言っています。
p と NULL です。
char 型は、演算するとき intに自動で変換されます。そのため、 片方が int になっています。
NULLはポインタです。汎用のポインタとして void*型になっていることがあります。
整数とポインタは通常比較したりしません。
よって「間違い」の可能性が高いです。

その前を見ると
p = my_search(x);
です。今は警告は出ませんが、上の関数宣言を修正すると、こんどはここで警告になるはずです。
p と my_searchの戻り値の型を考えれば、どこが間違いかわかるのでは。

C言語の大原則は「使う前に宣言/定義」です。
他の言語だと、この順番でも問題無い場合がありますが、C言語の場合は
> p = my_search(x);
ここで使うものを、この後で
> char * my_search(int a)
と宣言/定義してはいけません。

この場合、 int my_search() (引数任意、戻り値intの関数my_search) が宣言されているとして、コンパイルが進みます。
その結果、実際の char * my_search(int a) とは引数や戻り値違う、ということになり、エラーになります。
それが
「js010703_a106906.c(58) : error C2040: 'my_se...続きを読む

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) {
// ここに処理を書く
}
という関数が必要なようです。

Qfatal error LNK1120: 外部参照 1 が未解決です

またわからないことが・・・
教えて下さい。
以下をVC++2005でコンパイルすると、

MSVCRTD.lib(crtexew.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。
C:\Documents and Settings\tomato\My Documents\Visual Studio 2005\Projects\a\Debug\a.exe : fatal error LNK1120: 外部参照 1 が未解決です。

と警告がでて通りません。
何のことでしょうか。

#include<stdio.h>
#include<process.h>

struct meibo{
  char name[20];
  char tel[20];
  char address[20];
};

void message( void );
void input( FILE *fp, int cnt , struct meibo *a, int *end );

void main( void )
{
  struct meibo a[20];
  FILE *fp;
  int cnt, end;

  if( (fp=fopen( "meibo.dat", "w" ) ) == NULL ){
    printf( "Can not open the meibo.dat.\n" );
    exit( 1 );
  }

  message();

  fprintf( fp, "番号, 名前, TEL, 住所\n" );
  fflush( fp );

  cnt = 0;
  end = 0;
  while( end == 0 ){
    input( fp, cnt, &a[cnt], &end );
    cnt++;
    fflush( fp );
    if( cnt == 20 ){
      printf( "人数が一杯です.終了します.\n" );
      end = 1;
    }
  }
  fclose( fp );
}

void message( void )
{
  printf( "名前, TEL, 住所, endを入力してください.\n" );
  printf( "継続の時はend=0," );
  printf( "中止の時は,end=1と入力してください.\n" );
}

void input( FILE *fp, int cnt, struct meibo *a, int *end )
{
  printf( "名前-->" );
  scanf( "%s", a->name );
  printf( "TEL -->" );
  scanf( "%s", a->tel );
  printf( "住所-->" );
  scanf( "%s", a->address );
  printf( "Exit? Continue:0 Exit:1 -->" );
  scanf( "%d", end );
  printf( "\n" );
  fprintf( fp, "%2d, %s, %s, %s\n",
    cnt+1, a->name, a->tel, a->address );
}

またわからないことが・・・
教えて下さい。
以下をVC++2005でコンパイルすると、

MSVCRTD.lib(crtexew.obj) : error LNK2019: 未解決の外部シンボル _WinMain@16 が関数 ___tmainCRTStartup で参照されました。
C:\Documents and Settings\tomato\My Documents\Visual Studio 2005\Projects\a\Debug\a.exe : fatal error LNK1120: 外部参照 1 が未解決です。

と警告がでて通りません。
何のことでしょうか。

#include<stdio.h>
#include<process.h>

struct meibo{
  char name[20];
...続きを読む

Aベストアンサー

http://www.a.math.ryukoku.ac.jp/~hig/course/compsci2_2005/man/faq.html
にある現象と同じではないでしょうか、一度お試しください。

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

Q複数桁10進数の*桁目だけを抽出したい

タイトルがすべてと言えてしまうのですが、
例えば、int宣言された"4287"(この値は変動します)という数値があったとして、1桁目の"7"だけを別の変数へ引き抜きたいのですが、その場合にはANDによるマスク処理による演算で処理可能なのでしょうか?
また、他に良い方法などありましたら教えていただけますでしょうか?

Aベストアンサー

★10進数ですので AND は使えませんね。
・簡単なサンプルを載せますので読み取って下さい。

サンプル1:
int value = 4287;
int a[ 4 ];

a[0] = (value % 10); value /= 10; // 1桁目を取り出す
a[1] = (value % 10); value /= 10; // 2桁目を取り出す
a[2] = (value % 10); value /= 10; // 3桁目を取り出す
a[3] = (value % 10); value /= 10; // 4桁目を取り出す

サンプル2:
int value = 4287;
int a;

a = (value % 10);
value -= a;

value → 4280
a → 7
になります。

QEnterキーを押されたら次の処理に移るという事をしたい。

コンソールアプリケーション上で文字列を表示させた後、ユーザーがエンターキーを押したら次の文字列を表示するという仕様にしたいのですが、エンターキーだけ入力待ちにするっていうのはどのように書けばいいんでしょうか?

Aベストアンサー

#include <stdio.h>

int main(void)
{
char *str[] = {"abc", "def", "ghi", "jkl"};
int i;

for(i = 0; i < 4; i ++){
while(getchar() != '\n') ;
puts(str[i]);
}
return 0;
}

QC言語で文字列をかえす正しい書き方が知りたいです?

C言語で次の警告が表示されます。
文字列を返したいのですが、正しい書き方はどのようにすれば良いのでしょうか?


jci.h(20) : warning C4172; ローカル変数またはテンポラリのアドレスを返します。


char *test(char *a, int b)
{
char str[BUFSIZ];
return str; <------

}

Aベストアンサー

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び出し元でちゃんとfreeしましょう。

B-2.呼び出し元でメモリを確保するケース
(注意:同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{

...

return str;
}
これは#1の方の回答と同じです。

B-3.B-1/B-2の複合
(注意:NULL以外の同じアドレスを指定して複数回呼び出すと、メモリ内容は当然破壊されます)
char *test(char *str, ...)
{
if(str == NULL)
{
str = malloc(BUFSIZ);
if(str == NULL) return NULL; //エラー
}

...

return str;
}

こんなところですかね。

再入可能にするかどうかで、回答は変わります。

A.2度呼び出した場合に前のデータを破壊してもよいケース(再入不可能)

char *test(...)
{
static char str[BUFSIZ]; // static指定でメモリは静的に確保されます。

...

return str;
}

B.2度呼び出した場合に前のデータを破壊しないケース(再入可能)
B-1.mallocを使ってもいいケース
char *test(...)
{
char *str;
str = malloc(BUFSIZ);
if(str == NULL) return NULL; // エラー

...

return str;
}
この場合は、呼び...続きを読む

Q配列の要素数に変数を入れたいときには

よろしくお願いします。
配列の要素数には定数しか入れられないのですが,どうしても変数を入れたいときは,それを引数として関数を呼び出すしか方法はないでしょうか。
具体的には,scanfで手に入れたint型の変数を要素数とする配列を宣言したいのですが,どうすれば良いでしょうか。
ご教授ください。

Aベストアンサー

c99と呼ばれる最近の規格では、配列の大きさに変数を使用できます。
bccはc99に対応していないようです。

それ以前の規格では、動的領域確保関数 malloc や callocを使って領域を確保するか、効率等を無視してバカデカい配列を用意しておくかです。
「それを引数として関数を呼び出す」っていうのは、malloc/callocのことですか?

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' );
}

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


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

人気Q&Aランキング