構造体の動的配列の記述を教えてください。
構造体の動的配列の記述を教えてください。
C言語初心者です。
参考書に書いてあるコードを書いていたのですが、配列に不定定数を入れる部分でエラーが出ており、これの直し方がわかりません。mallocを使用して試しているのですが、上手く動きません。
また逆参照になってしまっている部分,バッファオーバーランしている部分、についても直し方がわからないので、教えてほしいです。
Visual Studioを使用しています。
下記、コードになります。お願いします。
code
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node {
int value;
struct bin_node* less_equal;
struct bin_node* bigger;
}BIN_NODE;
void set(BIN_NODE* src, BIN_NODE* dest) {
if (src->value > dest->value) {
if (dest->bigger) {
set(src, dest->bigger);
}
else
{
dest->bigger = src;
}
}
else {
if (dest->less_equal) {
set(src, dest->less_equal);
}
else {
dest->less_equal = src;
}
}
}
int main(int argc, char* argv[])
{
BIN_NODE nums[argc]; //エラーの部分
/* //mallocを使用して試した部分
BIN_NODE* nums =0;
nums= (BIN_NODE * )malloc(sizeof(BIN_NODE)*argc);
*/
nums[0].value = 0; //逆参照になっている部分
nums[0].less_equal = nums[0].bigger = NULL;
for (int i = 0; i < argc; i++) {
nums.value = atoi(argv); //バッファオーバーランしている部分
nums.less_equal = nums.bigger = NULL;
set(&nums, &nums[0]);
}
BIN_NODE* min = &nums[0];
while (min->bigger) //逆参照になっている部分
{
min = min->less_equal;
}
BIN_NODE* max = &nums[0];
while (max -> bigger) //逆参照になっている部分
{
max = max->bigger;
}
printf("min = %i,max = %i\n", min->value, max->value);
free(nums);
}
/code
参考書に書いてあるコードを書いていたのですが、配列に不定定数を入れる部分でエラーが出ており、これの直し方がわかりません。mallocを使用して試しているのですが、上手く動きません。
また逆参照になってしまっている部分,バッファオーバーランしている部分、についても直し方がわからないので、教えてほしいです。
Visual Studioを使用しています。
下記、コードになります。お願いします。
code
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node {
int value;
struct bin_node* less_equal;
struct bin_node* bigger;
}BIN_NODE;
void set(BIN_NODE* src, BIN_NODE* dest) {
if (src->value > dest->value) {
if (dest->bigger) {
set(src, dest->bigger);
}
else
{
dest->bigger = src;
}
}
else {
if (dest->less_equal) {
set(src, dest->less_equal);
}
else {
dest->less_equal = src;
}
}
}
int main(int argc, char* argv[])
{
BIN_NODE nums[argc]; //エラーの部分
/* //mallocを使用して試した部分
BIN_NODE* nums =0;
nums= (BIN_NODE * )malloc(sizeof(BIN_NODE)*argc);
*/
nums[0].value = 0; //逆参照になっている部分
nums[0].less_equal = nums[0].bigger = NULL;
for (int i = 0; i < argc; i++) {
nums.value = atoi(argv); //バッファオーバーランしている部分
nums.less_equal = nums.bigger = NULL;
set(&nums, &nums[0]);
}
BIN_NODE* min = &nums[0];
while (min->bigger) //逆参照になっている部分
{
min = min->less_equal;
}
BIN_NODE* max = &nums[0];
while (max -> bigger) //逆参照になっている部分
{
max = max->bigger;
}
printf("min = %i,max = %i\n", min->value, max->value);
free(nums);
}
/code
Re: 構造体の動的配列の記述を教えてください。
読みやすくして
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node {
int value;
struct bin_node* less_equal;
struct bin_node* bigger;
}BIN_NODE;
void set(BIN_NODE* src, BIN_NODE* dest) {
if (src->value > dest->value) {
if (dest->bigger) {
set(src, dest->bigger);
}
else
{
dest->bigger = src;
}
}
else {
if (dest->less_equal) {
set(src, dest->less_equal);
}
else {
dest->less_equal = src;
}
}
}
int main(int argc, char* argv[])
{
BIN_NODE nums[argc]; //エラーの部分
/* //mallocを使用して試した部分
BIN_NODE* nums =0;
nums= (BIN_NODE * )malloc(sizeof(BIN_NODE)*argc);
*/
nums[0].value = 0; //逆参照になっている部分
nums[0].less_equal = nums[0].bigger = NULL;
for (int i = 0; i < argc; i++) {
nums.value = atoi(argv); //バッファオーバーランしている部分
nums.less_equal = nums.bigger = NULL;
set(&nums, &nums[0]);
}
BIN_NODE* min = &nums[0];
while (min->bigger) //逆参照になっている部分
{
min = min->less_equal;
}
BIN_NODE* max = &nums[0];
while (max->bigger) //逆参照になっている部分
{
max = max->bigger;
}
printf("min = %i,max = %i\n", min->value, max->value);
free(nums);
}
Re: 構造体の動的配列の記述を教えてください。
エラー
c:\b>cl c1.c
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.c
c1.c(30): error C2057: 定数式が必要です。
c1.c(30): error C2466: サイズが 0 の配列を割り当てまたは宣言しようとしました。
c1.c(30): error C2133: 'nums': サイズが不明です。
c1.c(40): error C2231: '.value': 左のオペランドが 'struct' へのポインターです。'->' を使用してください。
c1.c(40): warning C4047: '関数': 間接参照のレベルが 'const char *' と 'char **' で異なっています。
c1.c(40): warning C4024: 'atoi': の型が 1 の仮引数および実引数と異なります。
c1.c(41): error C2231: '.less_equal': 左のオペランドが 'struct' へのポインターです。'->' を使用してください。
c1.c(41): error C2231: '.bigger': 左のオペランドが 'struct' へのポインターです。'->' を使用してください。
c1.c(42): warning C4047: '関数': 間接参照のレベルが 'BIN_NODE *' と 'BIN_NODE (*)[0]' で異なっています。
c1.c(42): warning C4024: 'set': の型が 1 の仮引数および実引数と異なります
Re: 構造体の動的配列の記述を教えてください。
argc は定数式ではないので配列は宣言出来ません
参考書に書いてあるコードを書いていたのですが、
とありますが よく確認してみましょう
参考書に書いてあるコードを書いていたのですが、
とありますが よく確認してみましょう
Re: 構造体の動的配列の記述を教えてください。
独習C 新版 という本の312ページに リスト11.9 ch11-08.c
として 同じプログラムがあるようです
2分木でコマンドライン引数を昇順にならべかえるそうです
例として
> a.exe 1 5 80 -3 3 5 32 97
min=-3,max=97
となっているようです
unix系 なので テストできませんが
使っている OS コンパイラは何ですか
として 同じプログラムがあるようです
2分木でコマンドライン引数を昇順にならべかえるそうです
例として
> a.exe 1 5 80 -3 3 5 32 97
min=-3,max=97
となっているようです
unix系 なので テストできませんが
使っている OS コンパイラは何ですか
Re: 構造体の動的配列の記述を教えてください。
ソースコードを提示する際は、BBCodeが有効な(無効にしない)状態で、
BBCodeのcodeタグの開始タグと終了タグの組(開始タグが先)で囲んでいただけると、
見やすくてありがたいです。
[]で囲まれていないcodeや/codeは、codeタグではありません。
したがって、対応するコンパイラ(gccなど)をC99モード(gccなら-std=c99)で用いるといいでしょう。
自分への辺ができてしまい、無限ループになってしまいます。
forループをi=0ではなくi=1から始めるようにするといいでしょう。
このことにより、通常argv[0]として与えられる実行ファイルのファイル名を
数値として処理しようとすることも回避できます。
さらに、mallocが成功したかを確かめるため、戻り値がNULLでないかをチェックし、
もしNULLであったらその後の処理を中止するような処理を入れるといいでしょう。
「逆参照になっている部分」のうち、 については、条件をmin->biggerではなくmin->less_equalにするといいでしょう。
他の2箇所については、特に直さなくてよさそうです。
また、「バッファオーバーランしている部分」についても、
特に範囲外アクセスになりそうな処理は見られず、直さなくてよさそうです。
BBCodeのcodeタグの開始タグと終了タグの組(開始タグが先)で囲んでいただけると、
見やすくてありがたいです。
[]で囲まれていないcodeや/codeは、codeタグではありません。
これは可変長配列(Variable-Length Array)といい、C99では必ず認められ、C11ではオプションの仕様です。
したがって、対応するコンパイラ(gccなど)をC99モード(gccなら-std=c99)で用いるといいでしょう。
i=0のときもset(&nums[i], &nums[0]);をしているため、
自分への辺ができてしまい、無限ループになってしまいます。
forループをi=0ではなくi=1から始めるようにするといいでしょう。
このことにより、通常argv[0]として与えられる実行ファイルのファイル名を
数値として処理しようとすることも回避できます。
さらに、mallocが成功したかを確かめるため、戻り値がNULLでないかをチェックし、
もしNULLであったらその後の処理を中止するような処理を入れるといいでしょう。
「逆参照」をググったところ、間接参照と同じような意味であり、悪いことではなさそうです。
「逆参照になっている部分」のうち、 については、条件をmin->biggerではなくmin->less_equalにするといいでしょう。
他の2箇所については、特に直さなくてよさそうです。
また、「バッファオーバーランしている部分」についても、
特に範囲外アクセスになりそうな処理は見られず、直さなくてよさそうです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の動的配列の記述を教えてください。
掲示板の不親切設計によって[/i]が無いのにも関わらず[i]が斜体を表すタグとして解釈され、消えています。Meta3 さんが書きました: ↑4年前読みやすくして
その消えたままのコードを使用しているため、不正なコードになっています。
codeタグを使わずに貼り付けられたコードは、表示された本文から直接コピペするのではなく、
引用ボタンを押して引用投稿用のフォームからコピペするといいでしょう。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の動的配列の記述を教えてください。
nums[0].valueに入れている0についても最大値や最小値を求める対象としているため、
全て正の数を入力した時にはmin = 0となってしまいます。
また、全て負の数を入力したときにはmax = 0となってしまいます。
これを回避するには、例えばnums[0].valueにはINT_MIN (limits.hで定義) を入れておき、
&nums[0]ではなくnums[0].biggerから最大値や最小値の探索を始める、という方法が考えられます。
ただし、この場合引数を与えずに実行した時にNULLをデリファレンスしてエラーになる可能性があるので、
このケースへは別途対処するべきでしょう。
また、malloc()系の関数で確保したポインタでもNULLでないポインタをfree()に渡してはいけません。
すなわち、 に対して を実行してはいけません。
全て正の数を入力した時にはmin = 0となってしまいます。
また、全て負の数を入力したときにはmax = 0となってしまいます。
これを回避するには、例えばnums[0].valueにはINT_MIN (limits.hで定義) を入れておき、
&nums[0]ではなくnums[0].biggerから最大値や最小値の探索を始める、という方法が考えられます。
ただし、この場合引数を与えずに実行した時にNULLをデリファレンスしてエラーになる可能性があるので、
このケースへは別途対処するべきでしょう。
また、malloc()系の関数で確保したポインタでもNULLでないポインタをfree()に渡してはいけません。
すなわち、 に対して を実行してはいけません。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の動的配列の記述を教えてください。
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node {
int value;
struct bin_node* less_equal;
struct bin_node* bigger;
}BIN_NODE;
void set(BIN_NODE* src, BIN_NODE* dest) {
if (src->value > dest->value) {
if (dest->bigger) {
set(src, dest->bigger);
}
else
{
dest->bigger = src;
}
}
else {
if (dest->less_equal) {
set(src, dest->less_equal);
}
else {
dest->less_equal = src;
}
}
}
int main(int argc, char* argv[])
{
//BIN_NODE nums[argc]; //エラーの部分
//mallocを使用して試した部分
BIN_NODE* nums= (BIN_NODE *)malloc(sizeof(BIN_NODE)*argc);
if( argc>2 ) {
printf( "argv[ %d ]%s\n", 1, argv[ 1 ] );
nums[ 0 ].value = atoi( argv[ 1 ] ); //バッファオーバーランしている部分
nums[ 0 ].less_equal = nums[ 0 ].bigger = nullptr;
for (int i = 2; i < argc; i++) {
printf( "argv[ %d ]%s\n", i, argv[ i ] );
nums[ i-1 ].value = atoi( argv[ i ] ); //バッファオーバーランしている部分
nums[ i-1 ].less_equal = nums[ i-1 ].bigger = nullptr;
set(&nums[ i-1 ], &nums[0]);
}
BIN_NODE* min = &nums[0];
while (min->less_equal != nullptr ) //逆参照になっている部分
{
min = min->less_equal;
}
BIN_NODE* max = &nums[0];
while (max -> bigger != nullptr ) //逆参照になっている部分
{
max = max->bigger;
}
printf("min = %i,max = %i\n", min->value, max->value);
}
free(nums);
return 0;
}
https://qiita.com/hikarabitagobou/items ... 5783a2463c
argc, argv とは? - Qiita(ja)
https://qiita.com/keitean/items/1a79c96adcf3fc02b1e5"
C言語 main(int argc, char const *argv[]) について - Qiita(ja)
https://ja.wikipedia.org/wiki/Null
Null - ジャパリ図書館(ja)
// end.
VTuber:
[香車]東上☆Aho(暎帆)☆海美
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。
中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。
[香車]東上☆Aho(暎帆)☆海美
http://atassyu.php.xdomain.jp/vtuber/index.html
レスがついていないものを優先して、レスするみみ。時々、見当外れなレスしみみ。
中の人:
手提鞄あたッしュ、[MrAtassyu] 手提鞄屋魚有店
http://ameblo.jp/mratassyu/
Pixiv: 666303
Windows, Mac, Linux, Haiku, Raspbery Pi, Jetson Nano, 電子ブロック 持ち。
Re: 構造体の動的配列の記述を教えてください。
うーん…まあ、C言語初心者だからといってC言語を使っているとは限らない、
むしろ初心者だからC言語を使うのを避けるという可能性もあるからなあ…
ただ、C++ならmalloc/freeではなくnew/deleteやstd::vectorを使うべきではないかなあ…?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)
Re: 構造体の動的配列の記述を教えてください。
#15 のコード VisualStudio2019 で c1.cpp として動きました
c1.c ではエラー
c++としてのc
c:\b\p>cl /EHsc c1.cpp
Microsoft(R) C/C++ Optimizing Compiler Version 19.26.28806 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
c1.cpp
Microsoft (R) Incremental Linker Version 14.26.28806.0
Copyright (C) Microsoft Corporation. All rights reserved.
/out:c1.exe
c1.obj
c:\b\p>c1.exe
c:\b\p>c1.exe 1 9 6 3
argv[ 1 ]1
argv[ 2 ]9
argv[ 3 ]6
argv[ 4 ]3
min = 1,max = 9
c:\b\p>
c++としてのc
Re: 構造体の動的配列の記述を教えてください。
投稿したものです。
確認不足でclangではなくvisual studioの標準のものでコンパイルしていたため、clangに直した所実行することができました。
様々な意見からC言語そのものの勉強が圧倒的に足りていないということを知れたので、今以上に勉強に励みたいと思います。
確認不足でclangではなくvisual studioの標準のものでコンパイルしていたため、clangに直した所実行することができました。
様々な意見からC言語そのものの勉強が圧倒的に足りていないということを知れたので、今以上に勉強に励みたいと思います。
Re: 構造体の動的配列の記述を教えてください。
#13 で教えていただいた
「@「「掲示板の不親切設計によって[/i]が無いのにも関わらず[i]が斜体を表すタグとして解釈され、消えています。
その消えたままのコードを使用しているため、不正なコードになっています。」を修正
「@「「掲示板の不親切設計によって[/i]が無いのにも関わらず[i]が斜体を表すタグとして解釈され、消えています。
その消えたままのコードを使用しているため、不正なコードになっています。」を修正
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node {
int value;
struct bin_node* less_equal;
struct bin_node* bigger;
}BIN_NODE;
void set(BIN_NODE* src, BIN_NODE* dest) {
if (src->value > dest->value) {
if (dest->bigger) {
set(src, dest->bigger);
}
else
{
dest->bigger = src;
}
}
else {
if (dest->less_equal) {
set(src, dest->less_equal);
}
else {
dest->less_equal = src;
}
}
}
int main(int argc, char* argv[])
{
BIN_NODE nums[argc]; //エラーの部分
/* //mallocを使用して試した部分
BIN_NODE* nums =0;
nums= (BIN_NODE * )malloc(sizeof(BIN_NODE)*argc);
*/
nums[0].value = 0; //逆参照になっている部分
nums[0].less_equal = nums[0].bigger = NULL;
for (int i = 0; i < argc; i++) {
nums[i].value = atoi(argv[i]); //バッファオーバーランしている部分
nums[i].less_equal = nums[i].bigger = NULL;
set(&nums[i], &nums[0]);
}
BIN_NODE* min = &nums[0];
while (min->bigger) //逆参照になっている部分
{
min = min->less_equal;
}
BIN_NODE* max = &nums[0];
while (max->bigger) //逆参照になっている部分
{
max = max->bigger;
}
printf("min = %i,max = %i\n", min->value, max->value);
free(nums);
}
Re: 構造体の動的配列の記述を教えてください。
間違いがあるようです 正しくは
#include <stdio.h>
#include <stdlib.h>
typedef struct bin_node { // 定義内で自構造体を利用するのでタグが必要
int value;
struct bin_node *less_equal; // 構造体指定子が完了していないので「struct タグ」で参照
struct bin_node *bigger; // 構造体指定子が完了していないので「struct タグ」で参照
} BIN_NODE; // 型名
// 設定先のノードよりも値が大きければright、小さいか等しければleftに設定する関数
// パラメータの構造体自体を書き換えるので、ポインターで受け取る必要がある
void set(BIN_NODE *src, BIN_NODE *dest) {
if (src->value > dest->value) {
if (dest->bigger) { // すでに他の構造体をポイントしていればその構造体に設定
set(src, dest->bigger);
} else {
dest->bigger = src;
}
} else {
if (dest->less_equal) { // すでに他の構造体をポイントしていればその構造体に設定
set(src, dest->less_equal);
} else {
dest->less_equal = src;
}
}
}
int main(int argc, char *argv[])
{
BIN_NODE nums[argc]; // 要素0を起点とする
nums[0].value = 0;
nums[0].less_equal = nums[0].bigger = NULL;
for (int i = 1; i < argc; i++) {
nums[i].value = atoi(argv[i]);
nums[i].less_equal = nums[i].bigger = NULL;
// 起点の要素0から小さい(less_equal)、大きい(bigger)に振り分ける
set(&nums[i], &nums[0]);
}
BIN_NODE *min = &nums[0];
// 起点からless_equalが指す構造体を終端(less_equalがNULL)までたどると最小値
while (min->less_equal) {
min = min->less_equal;
}
BIN_NODE *max = &nums[0];
// 起点からbiggerが指す構造体を終端(biggerがNULL)までたどると最大値
while (max->bigger) {
max = max->bigger;
}
printf("min=%i, max=%i\n", min->value, max->value);
}