可変長配列プログラム

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
カヌー
記事: 45
登録日時: 11年前

可変長配列プログラム

#1

投稿記事 by カヌー » 10年前

下は可変長配列のプログラムである.可変長配列に文字列を格納したいのですがどのように関数を使えばよいのでしょう.

コード:

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

/* 可変長配列の初期サイズ */
#define INIT_SIZE 5

typedef struct vector Vector;
typedef Vector *VectorPtr;

/* 可変長型配列の構造体 */
struct vector {
char **elems; /* 要素(文字列)の配列(固定長)*/
int size; /* 可変長配列のサイズ */
int capacity; /* 可変長配列の最大容量 */
};

/* 可変長配列を生成する */
VectorPtr create_vector(void) {
VectorPtr v = NULL;

v = malloc(sizeof(Vector));
if (v == NULL) {
fprintf(stderr, "Couldn't allocate memory for a vector\n");
exit(EXIT_FAILURE);
}

v->elems = malloc(sizeof(char *) * INIT_SIZE);
v->size = 0; /* 初期使用サイズは 0 */
v->capacity = INIT_SIZE;

return v;
}

/* 可変長配列の実質的な解放作業を行う.
* (次々と free() するので free() 後の NULL 代入は省略)
*/
void delete_vector0(VectorPtr v) {
int i;

/* free() と同様,NULLポインタに対しては何も行わない */
if (v == NULL) {
return;
}

/* 各要素(文字列)の領域を解放 */
for (i = 0; i < v->size; i++) {
free(v->elems[i]);
}
free(v->elems); /* 内部配列の領域を解放 */
free(v); /* 外側の枠も解放 */
}

/* 可変長配列 v を初期化する(未使用状態にするだけで領域は解放しない).*/
void clear_vector(VectorPtr v) {
int i;

assert(v);

/* 要素の各文字列を解放 */
for (i = 0; i < v->size; i++) {
free(v->elems[i]);
v->elems[i] = NULL;
}

/* 使用サイズを0にする */
v->size = 0;
}

/* 可変長配列 v を拡大する */
void expand_vector(VectorPtr v) {
assert(v);

/* 最大容量を2倍に増やす */
v->capacity *= 2;

/* 新しい最大容量を持つ領域を確保 */
v->elems = realloc(v->elems, sizeof(char *) * v->capacity);

/* サイズを変更できなかった場合のエラー処理 */
if (v->elems == NULL) {
fprintf(stderr, "Couldn't re-allocate memory for a vector\n");
exit(EXIT_FAILURE);
}
}

/* 可変長配列 v の最後に文字列 s を追加 */
void append(VectorPtr v, char *s) {
assert(s);

/* 容量が一杯になったら容量を拡大する */
if (v->size == v->capacity) {
expand_vector(v);
}
v->elems[v->size] = _strdup(s); /* 最後に要素を追加 */
v->size++; /* 使用部分のサイズを1つ増やす */
}

/* 可変長配列の(使用部分の)サイズを返す.*/
int get_vector_size(VectorPtr v) {
assert(v);
return v->size;
}

/* 可変長配列 v における添え字 index の要素(文字列)を取得 */
char *get_elem(VectorPtr v, int index) {
assert(v);

/* 配列添え字の範囲をチェック */
if (index < 0 || index >= v->size) {
fprintf(stderr, "Index out of bounds");
exit(EXIT_FAILURE);
}
/* 指定された添え字の値を返す */
return v->elems[index];
}

/* 可変長配列の内容を横に並べて表示する.*/
void print_vector(VectorPtr v) {
int i;

assert(v);

if (v->size == 0) {
printf("(empty)\n");
return;
}

for (i = 0; i < v->size; i++) {
printf(">>%s", v->elems[i]);
}
printf("\n");
}

int main(void)
{

return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 可変長配列プログラム

#2

投稿記事 by みけCAT » 10年前

カヌー さんが書きました:下は可変長配列のプログラムである.可変長配列に文字列を格納したいのですがどのように関数を使えばよいのでしょう.
普通にやりたいことをしてくれる関数を使えばいいでしょう。

コード:

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

/* 足りない関数 */
char *_strdup(const char *a) {
char *data = (char*)malloc(strlen(a) + 1);
if(data == NULL) {
fprintf(stderr, "malloc failed\n");
exit(1);
}
strcpy(data, a);
return data;
}

/* 可変長配列の初期サイズ */
#define INIT_SIZE 5

/* ここは同じなので省略 */

/* 可変長配列の内容を横に並べて表示する.*/
void print_vector(VectorPtr v) {
int i;

assert(v);

if (v->size == 0) {
printf("(empty)\n");
return;
}

for (i = 0; i < v->size; i++) {
printf(">>%s", v->elems[i]);
}
printf("\n");
}

int main(void)
{
VectorPtr kahennchouhairetu; /* 可変長配列の位置を保存する変数 */
kahennchouhairetu = create_vector(); /* 可変長配列を作る */
append(kahennchouhairetu, "文字列"); /* 可変長配列に文字列を格納する */
delete_vector0(kahennchouhairetu); /* 可変長配列を後片付けする */
return 0;
}
オフトピック
今回は合わせましたが、インデントを整えることをおすすめします。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

カヌー
記事: 45
登録日時: 11年前

Re: 可変長配列プログラム

#3

投稿記事 by カヌー » 10年前

解答ありがとうございます.可変長配列に格納された文字列をファイルに出力したいのですがfputs(kahennchouhairetu, fp)みたいな感じで出力できないのでしょうか?

コード:

int main(void)
{
    FILE *fp;
    char filename[64] = "output" 

    VectorPtr kahennchouhairetu; /* 可変長配列の位置を保存する変数 */
    kahennchouhairetu = create_vector(); /* 可変長配列を作る */

    fp = fopen(filename, "a");

    append(kahennchouhairetu, "文字列"); /* 可変長配列に文字列を格納する */

    fputs(kahennchouhairetu, fp);

    delete_vector0(kahennchouhairetu); /* 可変長配列を後片付けする */

    fclose(fp);

    return 0;
}

かずま

Re: 可変長配列プログラム

#4

投稿記事 by かずま » 10年前

カヌー さんが書きました:可変長配列に格納された文字列をファイルに出力したいのですがfputs(kahennchouhairetu, fp)みたいな感じで出力できないのでしょうか?
_strdup を strdup に変更しました。

コード:

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

#define INIT_SIZE 5 /* 可変長配列の初期サイズ */

typedef struct vector Vector;
typedef Vector *VectorPtr;

struct vector { /* 可変長型配列の構造体 */
    char **elems;   /* 要素(文字列)の配列(固定長) */
    int size;       /* 可変長配列のサイズ */
    int capacity;   /* 可変長配列の最大容量 */
};

/* 可変長配列を生成する */
VectorPtr create_vector(void)
{
    VectorPtr v = NULL;

    v = malloc(sizeof(Vector));
    if (v == NULL) {
        fprintf(stderr, "Couldn't allocate memory for a vector\n");
        exit(EXIT_FAILURE);
    }

    v->elems = malloc(sizeof(char *) * INIT_SIZE);
    v->size = 0;    /* 初期使用サイズは 0 */
    v->capacity = INIT_SIZE;

    return v;
}

/* 可変長配列の実質的な解放作業を行う.
 * (次々と free() するので free() 後の NULL 代入は省略)
 */
void delete_vector0(VectorPtr v)
{
    int i;

/* free() と同様,NULLポインタに対しては何も行わない */
    if (v == NULL) {
        return;
    }

    for (i = 0; i < v->size; i++) { /* 各要素(文字列)の領域を解放 */
        free(v->elems[i]);
    }
    free(v->elems);     /* 内部配列の領域を解放 */
    free(v);            /* 外側の枠も解放 */
}

/* 可変長配列 v を初期化する(未使用状態にするだけで領域は解放しない).*/
void clear_vector(VectorPtr v)
{
    int i;

    assert(v);

    for (i = 0; i < v->size; i++) { /* 要素の各文字列を解放 */
        free(v->elems[i]);
        v->elems[i] = NULL;
    }

    v->size = 0; /* 使用サイズを0にする */
}

/* 可変長配列 v を拡大する */
void expand_vector(VectorPtr v)
{
    assert(v);

    v->capacity *= 2; /* 最大容量を2倍に増やす */

    /* 新しい最大容量を持つ領域を確保 */
    v->elems = realloc(v->elems, sizeof(char *) * v->capacity);

    if (v->elems == NULL) { /* サイズを変更できなかった場合のエラー処理 */
        fprintf(stderr, "Couldn't re-allocate memory for a vector\n");
        exit(EXIT_FAILURE);
    }
}

/* 可変長配列 v の最後に文字列 s を追加 */
void append(VectorPtr v, char *s)
{
    assert(s);

    if (v->size == v->capacity) { /* 容量が一杯になったら容量を拡大する */
        expand_vector(v);
    }
    v->elems[v->size] = strdup(s);  /* 最後に要素を追加 */
    v->size++;      /* 使用部分のサイズを1つ増やす */
}

/* 可変長配列の(使用部分の)サイズを返す.*/
int get_vector_size(VectorPtr v)
{
    assert(v);
    return v->size;
}

/* 可変長配列 v における添え字 index の要素(文字列)を取得 */
char *get_elem(VectorPtr v, int index)
{
    assert(v);

    if (index < 0 || index >= v->size) { /* 配列添え字の範囲をチェック */
        fprintf(stderr, "Index out of bounds");
        exit(EXIT_FAILURE);
    }
    return v->elems[index]; /* 指定された添え字の値を返す */
}

/* 可変長配列の内容を横に並べて表示する.*/
void print_vector(VectorPtr v)
{
    int i;

    assert(v);

    if (v->size == 0) {
        printf("(empty)\n");
        return;
    }

    for (i = 0; i < v->size; i++) {
        printf(">>%s", v->elems[i]);
    }
    printf("\n");
}

int main(void)
{
    FILE *fp;  int i, n;

    VectorPtr v = create_vector();
    append(v, "abcdefg");
    append(v, "1234567890");
    append(v, "xyz");
    n = get_vector_size(v);

    fp = fopen("output", "w");
    if (!fp) return 1;
    for (i = 0; i < n; i++)
        fprintf(fp, "%s\n", get_elem(v, i));
    fclose(fp);

    delete_vector0(v);
    return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 可変長配列プログラム

#5

投稿記事 by みけCAT » 10年前

カヌー さんが書きました:解答ありがとうございます.可変長配列に格納された文字列をファイルに出力したいのですがfputs(kahennchouhairetu, fp)みたいな感じで出力できないのでしょうか?
このままでは難しいと思うので、print_vector関数をコピペして改造しました。

コード:

void fputtu(VectorPtr v, FILE* fp) {
int i;

assert(v);

if (v->size == 0) {
fprintf(fp, "(empty)\n");
return;
}

for (i = 0; i < v->size; i++) {
fprintf(fp, ">>%s", v->elems[i]);
}
fprintf(fp, "\n");
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

カヌー
記事: 45
登録日時: 11年前

Re: 可変長配列プログラム

#6

投稿記事 by カヌー » 10年前

fprintfを使えばそのように出力できるんですね.お二人の方ありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る