【先着1,000名様!】1,000円分をプレゼント!

C言語の配列をPush(追加)するには

タイトル通りなのですが、OPENCVにあるcvSeqPushのように
配列の末尾に新たな数値を追加する関数はあるのでしょうか??

できれば、簡単なサンプルコードもしくはそれが掲載されているページを紹介していただくと
とても助かります。よろしくお願いします。

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

A 回答 (3件)

標準関数にはありません。



作るなら、新たに現在の配列のサイズに要素1つ分のサイズを増やしたメモリ領域を新たに獲得し、そこに既存の配列をコピーしてから一番最後の要素に新しい要素を追加するしかありません。

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

void *array_push(void *ptr, int size, size_t unit_size, void *item) {
void *adr = malloc(unit_size * (size + 1));
memcpy(adr, ptr, unit_size * size);
memcpy((char *)adr + (unit_size * size), item, unit_size);
return(adr);
}

int main(void)
{
char array_one[] = {'0', '1', '2', '3', '4'};
char *array_ptr = array_one;
int array_size = sizeof(array_one) / sizeof(array_one[0]);
char additem = '5';

printf("配列の%d番目の要素は 0x%X ですよ\n",
array_size - 1, array_ptr[array_size - 1]);

array_ptr = (char *)array_push(array_ptr, array_size, sizeof(array_ptr[0]), &additem);

printf("新しい配列の%d番目の要素は 0x%X ですよ\n",
array_size - 1, array_ptr[array_size - 1]);

array_size++;

printf("新しい配列の%d番目の要素は 0x%X ですよ\n",
array_size - 1, array_ptr[array_size - 1]);

free(array_ptr);

getchar();

return(0);
}
    • good
    • 2
この回答へのお礼

ありがとうございます!
とても参考になりました。

お礼日時:2010/07/30 04:53

Cの配列は固定長なので、「新たな要素を増やす」ことは不可能です。


動的にやりたければmallocとreallocを駆使するしかありません。

なおC++では、これを隠蔽するSTLのvectorテンプレートクラスが存在します。
    • good
    • 0
この回答へのお礼

やはりできないんですね。
ありがとうございました。

お礼日時:2010/07/30 04:54

ありません。

あきらめましょう。

C言語の配列はその定義時に要素数(正確には配列が必要とするバイト数)が固定されてしまい、その要素数を後から変更することはできません。

cvSeqPushで末尾に新たな値を追加できるのは、その関数が扱う構造体CvSeqが要素の追加・削除を行える構造になっていて、関数内でいろいろと処理をやっているからです。

# opencvは知りませんでしたが、リファレンス(参考URL)を斜め読みしたところどうやら双方向リストを使用しているようです。

つまり、ただの配列に対して末尾追加を行っているわけではありません。

参考URL:http://opencv.jp/opencv-1.0.0/document/opencvref …
    • good
    • 0
この回答へのお礼

なるほど、何やらややこしいですね。
お返事ありがとうございました。

お礼日時:2010/07/30 04:55

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

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

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

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

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

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

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

Aベストアンサー

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

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

Q関数から配列を返すには?

return で配列を返すにはどうしたらよいのでしょうか。
例えば以下のような場合です。

int main (){

char Value[] = "999";
int a;

 a = test(Value);

 printf ("%d", a);
 
}


int test(char *Value)
{
int nVal[255];

ここで nVal に適当な処理をして・・・

 return Value;

}


 int a を配列とかにしてみましたけど、コンパイラが
通りません。
要は配列数値を main で受け取って表示したいのですが、
本日C言語はじめたところなので、教えていただければありががたいです。

Aベストアンサー

戻り値は1つしか戻せません。
引数で配列の先頭のポインタが渡され、それを使って関数で配列の中身を
書き換えて戻ってきて、メインで配列を参照すればいいです。

参考urlの(3)を参考にしてください。

参考URL:http://www9.plala.or.jp/sgwr-t/c/sec11-3.html

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
になります。

QC言語 配列の長さの上限

C言語で配列Array[N]の長さNの上限っていくらなんでしょうか?
もし可能なのであれば上限を2147483647にしたいのですが、方法を教えてください。

Aベストアンサー

そもそもWindowsの32bit版はアプリが仮想メモリ空間を2GBしか使えません。2GBを超えるには64bit版が必要です。
たとえ64bit版OSだとしても添え字が2147483647って、単純なintの配列だとしても4x2147483647=8GB必要ですね。実メモリ16GBとかのPCを用意しますか?
そもそも配列で2147483647個必要なアルゴリズムに問題ありだと思います。

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

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

QC言語で、メモリを解放しないで終わるプログラム

C言語の話です。

mallocなどで領域を確保したら、解放しなければいけないんですよね。
しかし、解放しないで終了すると具体的にどうなるのか、私は理解していません。

次のような、freeしないプログラムを作って何回か実行してみました。しかし、別におかしくならないですね。


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

char *cp;

int main(void)
{
unsigned int n;

printf("サイズ(2以上)を入力してください:");
scanf("%d",&n);

cp=malloc(n);
if(!cp)
{
printf("%s\n","mallocできませんでした。");
return(1);
}

strcpy(cp,"A");
printf("cpは%sです。\n", cp);

printf("それでは終わりにします\n");

return(0);
}


グローバルでcharの固定長の配列を宣言したとすれば、プログラムの終了時にその領域は解放されると思います。

このような固定長の配列の場合とmallocの場合との違いが問題なんです。

 実験的に、解放しないがために何かおかしくなってしまったり、悪影響を及ぼしたりするようなプログラムを作りたいんですが、どのようにすればよいでしょうか。

もしも私の環境ではそのようなプログラムが作れないなら、別の環境の話でもよいので具体的にこんなふうになってしまうという話をお聞きしたいんです。


過去の質問を検索してみました。
http://oshiete1.goo.ne.jp/kotaeru.php3?q=160037
ここのNo.9では、「freeしないアプリケーションの起動・終了を繰り返すと、リソースが不足する」旨が書かれていて、質問者の方もそれで納得されているようです。
しかし、私は、リソースが不足するとはどういうことで、何が起こるのか、知りません。

私のマシン
OS:Windows98SE
VC++6.0

C言語の話です。

mallocなどで領域を確保したら、解放しなければいけないんですよね。
しかし、解放しないで終了すると具体的にどうなるのか、私は理解していません。

次のような、freeしないプログラムを作って何回か実行してみました。しかし、別におかしくならないですね。


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

char *cp;

int main(void)
{
unsigned int n;

printf("サイズ(2以上)を入力してください:");
scanf("%d",&n);

cp=malloc(n);
if(!cp)
{...続きを読む

Aベストアンサー

書き忘れましたのでもう一度。

malloc/freeを1セットで考えている人がいるようですが、「プログラム終了時にすべてをfreeする」なんていう処理は愚の骨頂です。

malloc/freeはマンションの内装工事のようなものです。
mallocは次の入居者のために内装工事を行います。
freeは次の入居者のための回復工事です。
マンション自体の取り壊し(=プログラムの終了)が行われる寸前に回復工事の必要はありません。

動的メモリ領域を10000個くらい確保して、freeして終了する場合とfreeせずに終了する場合を比べてみてください。
プログラム終了寸前にfreeするのは無駄以外の何者でもありません。

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;
}
この場合は、呼び...続きを読む

Qint型からchar型への変換

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

Aベストアンサー

#include <stdio.h>


char buf[5];
int no;

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

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'const char *' 型は 'char *' 型に変換できない ??

Case 1
Text9.Text = "AB";
Text10.Text = "A"; // 1文字目
Text11.Text = "B"; // 2文字目
case 2;
Text9.Text = "Ab";
Text10.Text = "A";
Text11.Text = "b";
case 3;
Text9.Text = "aB";
Text10.Text = "a";
Text11.Text = "B";
case 4;
Text9.Text = "ab";
Text10.Text = "a";
Text11.Text = "b";

上記のようなCase 文を C を使って作成したいのですが,
A~J の大文字とa~jまでの小文字をつかって,2文字の文字列をつくるとき,
1文字目と2文字目が,形態も名称も異なる文字列(例 AB , Ab aB, ab, AC, Ac aC ac, ...)のcase文をつくりたいのですが,
'const char *' 型は 'char *' 型に変換できないというエラーメッセージがでてしまいます.下記プログラムをどう直せばいいかおしえてください.

#include <stdio.h>

#define MAX_NAME 256

int main(void)
{
const char *NAME12 = "Text9";
const char *NAME1 = "Text10";
const char *NAME2 = "Text11";
const char *ALPH = "ABCDEFGHIJabcdefghij";

FILE *fp = NULL;
char f_name[MAX_NAME];
int count = 0;
char *p = ALPH;
char *q = ALPH;

printf("ファイル名:");
scanf("%s", f_name);

fp = fopen(f_name, "w");
if (fp == NULL) {
printf("'%s':ファイルが見つかりません\n", f_name);
} else {
for (p = ALPH; *p != '\0'; p++) {
for (q = ALPH; *q != '\0'; q++) {
if (*p != *q) {
count++;
fprintf(fp, "Case %d\n", count);
fprintf(fp, "%s.Text = \"%c%c\"\n", NAME12, *p, *q);
fprintf(fp, "%s.Text = \"%c%c\"\n", NAME1, *p, *q);
fprintf(fp, "%s.Text = \"%c%c\"\n", NAME2, *p, *q);
}
}
}
fclose(fp);
}

return 0;
}

Case 1
Text9.Text = "AB";
Text10.Text = "A"; // 1文字目
Text11.Text = "B"; // 2文字目
case 2;
Text9.Text = "Ab";
Text10.Text = "A";
Text11.Text = "b";
case 3;
Text9.Text = "aB";
Text10.Text = "a";
Text11.Text = "B";
case 4;
Text9.Text = "ab";
Text10.Text = "a";
Text11.Text = "b";

上記のようなCase 文を C を使って作成したいのですが,
A~J の大文字とa~jまでの小文字をつかって,2文字の文字列をつくるとき,
1文字目と2文字目が,形態も名称も異なる文字列(例 AB , Ab...続きを読む

Aベストアンサー

★回答者 No.2 さんと同じです。
・『const char *』型と『char *』型のタイプを合わせます。
・つまり、
 const char *ALPH = "ABCDEFGHIJabcdefghij";
 const char *p = ALPH;
 const char *q = ALPH;
・とするか、
 char *ALPH = "ABCDEFGHIJabcdefghij";
 char *p = ALPH;
 char *q = ALPH;
・とします。
・また、ちょっと間違いがあるので指摘します。
・『fprintf(fp, "%s.Text = \"%c%c\"\n", NAME1, *p, *q);』は、
 『fprintf(fp, "%s.Text = \"%c\"\n", NAME1, *p );』です。
・『fprintf(fp, "%s.Text = \"%c%c\"\n", NAME2, *p, *q);』は、
 『fprintf(fp, "%s.Text = \"%c\"\n", NAME2, *q);』になります。
・以上。分かりますか?

●小言
・このプログラムで出力されるCソースを、何かの処理ルーチンとして使うのですか?
・もっと良い方法がありますけど。→文字列を動的に作成する方法はどうでしょう。
・以下にサンプルを載せておきます。→処理速度は少し落ちます。ループしているので。

●サンプル
void MakeString( int num, const char **text9, const char **text10, const char **text11 )
{
 static char buff9[ 4 ], buff10[ 4 ], buff11[ 4 ];
 static const char *ALPH = "ABCDEFGHIJabcdefghij";
 const char *p = ALPH;
 const char *q = ALPH;
 
 for ( p = ALPH ; *p != '\0' ; p++ ){
  for ( q = ALPH ; *q != '\0' ; q++ ){
   if ( *p != *q ){
    if ( --num <= 0 ){
     *text9 = buff9; sprintf( buff9, "%c%c", *p, *q );
     *text10 = buff10; sprintf( buff10, "%c", *p );
     *text11 = buff11; sprintf( buff11, "%c", *q );
     return;
    }
   }
  }
 }
}

●使用例
const char *Text9;
const char *Text10;
const char *Text11;

MakeString( 123, &Text9, &Text10, &Text11 );
・以上。おわり。

★回答者 No.2 さんと同じです。
・『const char *』型と『char *』型のタイプを合わせます。
・つまり、
 const char *ALPH = "ABCDEFGHIJabcdefghij";
 const char *p = ALPH;
 const char *q = ALPH;
・とするか、
 char *ALPH = "ABCDEFGHIJabcdefghij";
 char *p = ALPH;
 char *q = ALPH;
・とします。
・また、ちょっと間違いがあるので指摘します。
・『fprintf(fp, "%s.Text = \"%c%c\"\n", NAME1, *p, *q);』は、
 『fprintf(fp, "%s.Text = \"%c\"\n", NAME1, *p );』です。
...続きを読む


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

人気Q&Aランキング