質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

875閲覧

C言語におけるポインタ構造体の扱いについて

Savanof

総合スコア33

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2021/06/09 09:19

編集2021/06/10 04:00

前提・実現したいこと

C言語において、多倍長整数の加算を行うプログラムの実装を考えています。加算の部分の実装は大体終わっているのですが、計算結果を自分の定義した関数に渡し結果を出力する過程が上手くいかず、困っています。

関数、構造体の引数や構造を変えれば、実装はできなくもないのですが、構造や引数は変えない方向性でお願いします。

該当のソースコード

ソースコードの大まかなワークフローは下の様な形です。

1.キーボードからの入力を2つと、結果表示用の値をTest構造体に入れる 2.(1.)で入れた値を、StructAdd関数に渡す。 3.結果表示用の値(関数の引数 r ,入れた値pAdd_Answer)をTest_print関数を介して、結果を表示する

C

1#define MAX_INPUT 100 2 3#include <stdio.h> 4#include <stdlib.h> 5#include <stdint.h> 6#include <string.h> 7#include <strings.h> 8 9// 二つの数を比較して大きい方を選択する 10int max(int a, int b) { return a > b ? a : b; } 11 12 13// 文字配列を逆順にする 14void ReverseStr(char* str){ 15 int size = strlen(str); 16 int i,j; 17 char tmp = {0}; 18 19 for(i = 0, j = size - 1; i < size / 2; i++, j--){ 20 tmp = str[i]; 21 str[i] = str[j]; 22 str[j] = tmp; 23 } 24 25 return; 26} 27 28 29// fgetsの入力に改行が含まれる場合、削除する。 30void remove_newline_ch(char *line) 31{ 32 int new_line = strlen(line) -1; 33 if (line[new_line] == '\n') 34 line[new_line] = '\0'; 35} 36 37 38 39// 構造体の定義 40struct Test { 41 char *val; 42}; 43 44// 長整数の表示関数 45// pを標準出力に表示する 46 47void Test_print(struct Test *p){ 48 49 char *String_Print; 50 51 String_Print = p->val; 52 53 printf("Number (in Func Print) is %s \n",String_Print); 54 55} 56 57 58// 加算関数 59// pとqの加算結果をrに入れる 60void Struct_add(struct Test *p, struct Test *q, struct Test *r){ 61 62 char *String_P , *String_Q , *String_R; 63 64 String_P = p->val; 65 String_Q = q->val; 66 String_R = r->val; 67 68 int p_Size = strlen(String_P); 69 int q_Size = strlen(String_Q); 70 71 int N = max(p_Size, q_Size); 72 char Add_Str_Lis[N]; 73 74 for (int i = 0; i < N; i++){ 75 76 int num1 , num2 , sum; 77 // OutOfIndexしないようにする。 78 if(p_Size-1 < i){ 79 80 num1 = 0; 81 } 82 else{ 83 num1 = (String_P[i]- '0'); // 数値化 84 } 85 86 if(q_Size-1 < i){ 87 88 num2 = 0; 89 } 90 else{ 91 num2 = (String_Q[i] - '0'); // 数値化 92 } 93 94 Add_Str_Lis[i] = (num1 + num2) + '0'; //文字化 95 96 } 97 98 ReverseStr(Add_Str_Lis); 99 String_R = Add_Str_Lis; 100 printf("Number(in Func add) is %s \n",String_R); 101 Test_print(r); 102 103} 104 105 106 107 108 109int main(){ 110 111 char input1[MAX_INPUT]; 112 char input2[MAX_INPUT]; 113 char Add_Char_answer[MAX_INPUT]; 114 115 struct Test Number1, Number2 , Add_Answer , Sub_Answer; 116 117 struct Test *pNumber1 = &Number1; 118 struct Test *pNumber2 = &Number2; 119 struct Test *pAdd_Answer = &Add_Answer; 120 struct Test *pSub_Answer = &Sub_Answer; 121 122 // fgetsから入力を受け取り、改行を消去した後に文字列を反転させる。 123 printf("Enter The First Number \n"); 124 fgets(input1 , MAX_INPUT , stdin); 125 remove_newline_ch(input1); 126 ReverseStr(input1); 127 128 printf("Enter The Second Number \n"); 129 fgets(input2 , MAX_INPUT , stdin); 130 remove_newline_ch(input2); 131 ReverseStr(input2); 132 133 134 //入力をlonginit構造体に入れる。 135 pNumber1 -> val = input1; 136 pNumber2 -> val = input2; 137 pAdd_Answer-> val = Add_Char_answer; 138 // longinit_addを呼び出して加算。 139 Struct_add(pNumber1 , pNumber2 , pAdd_Answer); 140}
<結果> Enter The First Number 100 Enter The Second Number 200 Number(in Func add) is 300 Number (in Func Print) is

発生している問題・エラーメッセージ

Struct_add関数内で加算の結果を表示するのは上手く動作しているのですが、Struct_add関数内でTest_print関数に値を渡して結果を表示するのが上手くいってないです。ポインターと構造体絡みのエラーだとは思うのですが、どの様に解決すればいいか分らないです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2021/06/09 09:32 編集

// struct Test *pNumber1 = &Number1; 構造体のポインタに対して配列のポインタを代入していますが、構造体のポインタを使用している理由はありますか? 追記 勘違いでした、すみません
Savanof

2021/06/09 09:37

void Struct_add(struct Test *p, struct Test *q, struct Test *r)の引数が構造体のポインタを要求していたので、構造体のポインタを使用していました。
guest

回答2

0

Struct_add関数内で加算の結果を表示するのは上手く動作しているのですが、main関数、Test_print関数内で結果を表示するのが上手くいってないです。

Struct_addのコメントにはpとqの加算結果をrに入れると書いてありますが、実際にはrに入れる操作は行われていません

投稿2021/06/09 09:24

編集2021/06/09 09:24
maisumakun

総合スコア145183

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

maisumakun

2021/06/09 09:25

逆質問ですが、どの操作で「rへの代入を行った」と考えましたでしょうか?
Savanof

2021/06/09 09:35

99行目のString_R = Add_Str_Lis;で代入を行ったつもりでした。
maisumakun

2021/06/09 09:36

それはローカル変数を書き換えているだけで、rの指し先には何も影響しません。
maisumakun

2021/06/09 09:38

(なお、char Add_Str_Lis[N]はローカル変数ですので、そこを指すアドレスは関数を抜ければ無効となります。この変数へのアドレスは、返してはいけません)
Savanof

2021/06/09 09:55

あっ、関数への引数もローカル変数になりますよね...
Savanof

2021/06/09 09:58

もし、Struct_add内にTest_print関数を導入して、Struct_add関数の引数rをTest_print関数に渡す場合には、どうすればいいですか? testprint関数で要求されている引数が構造体のポインタ―型なので、Struct_add関数内でどうやって渡せばいいか分らないです
maisumakun

2021/06/09 10:01 編集

> Struct_add関数の引数rをTest_print関数に渡す場合には、どうすればいいですか? そのまま渡して構いません。ポインタの「指す先」がローカル変数だと抜けてしまって問題になりますが、ポインタ「自体」がローカル変数であっても何ら問題ありません。
maisumakun

2021/06/09 10:05

(返り値や引数のポインタのように、関数の「実行を終えた後」に残るポインタにローカル変数を使うのが問題なのであって、関数Aから関数Bを呼ぶ時に、関数Aのローカル変数へのポインタを渡しても、関数Bがそのポインタを記録して後で使うような構造でなければ無問題です)
Savanof

2021/06/10 03:21

すいません、やっぱりうまく実装できなかったのでグローバル変数/ローカル変数の所も踏まえてもう一度書き直します。
Savanof

2021/06/10 04:06

ローカル変数、グローバル変数の違いを踏まえて、「StructAdd関数内でTest_print関数を呼び出し結果を表示するには」という趣旨で質問を書き変えました。最初にmaisumakunさんに質問された「rへの代入を行ったとは?」の部分に戻ってしまった気がしますが、rへどの様に代入して結果を主力すればいいか分らないです。
guest

0

ベストアンサー

修正しておきました。
又、加算時、桁の繰り上げ処理を行っていないので、それも行うようにしました。

C

1#define MAX_INPUT 100 2 3#include <stdio.h> 4#include <stdlib.h> 5#include <stdint.h> 6#include <string.h> 7#include <strings.h> 8 9// 二つの数を比較して大きい方を選択する 10int max(int a, int b) { return a > b ? a : b; } 11 12 13// 文字配列を逆順にする 14void ReverseStr(char* str){ 15 int size = strlen(str); 16 int i,j; 17 char tmp = {0}; 18 19 for(i = 0, j = size - 1; i < size / 2; i++, j--){ 20 tmp = str[i]; 21 str[i] = str[j]; 22 str[j] = tmp; 23 } 24 25 return; 26} 27 28 29// fgetsの入力に改行が含まれる場合、削除する。 30void remove_newline_ch(char *line) 31{ 32 int new_line = strlen(line) -1; 33 if (line[new_line] == '\n') 34 line[new_line] = '\0'; 35} 36 37 38 39// 構造体の定義 40struct Test { 41 char *val; 42}; 43 44 45 46 47// 加算関数 48// pとqの加算結果をrに入れる 49void Struct_add(struct Test *p, struct Test *q, struct Test *r){ 50 51 char *String_P , *String_Q , *String_R; 52 53 String_P = p->val; 54 String_Q = q->val; 55 String_R = r->val; 56 57 int p_Size = strlen(String_P); 58 int q_Size = strlen(String_Q); 59 60 int N = max(p_Size, q_Size); 61 char Add_Str_Lis[N+2]; 62 Add_Str_Lis[N] = '\0'; 63 int kuriage = 0; 64 for (int i = 0; i < N; i++){ 65 66 int num1 , num2 , sum; 67 // OutOfIndexしないようにする。 68 if(p_Size-1 < i){ 69 70 num1 = 0; 71 } 72 else{ 73 num1 = (String_P[i]- '0'); // 数値化 74 } 75 76 if(q_Size-1 < i){ 77 78 num2 = 0; 79 } 80 else{ 81 num2 = (String_Q[i] - '0'); // 数値化 82 } 83 sum = num1 + num2 + kuriage; 84 kuriage = 0; 85 if (sum > 9){ 86 sum = sum -10; 87 kuriage = 1; 88 } 89 Add_Str_Lis[i] = sum + '0'; //文字化 90 91 } 92 if (kuriage > 0){ 93 Add_Str_Lis[N] = kuriage + '0'; 94 Add_Str_Lis[N+1]= '\0'; 95 } 96 ReverseStr(Add_Str_Lis); 97 String_R = Add_Str_Lis; 98 printf("Number(in Func add) is %s \n",String_R); 99 strcpy(r->val,String_R); 100} 101 102 103 104// 長整数の表示関数 105// pを標準出力に表示する 106 107void Test_print(struct Test *p){ 108 109 char *String_Print; 110 111 String_Print = p->val; 112 113 printf("Number (in Func Print) is %s \n",String_Print); 114 115} 116 117 118 119int main(){ 120 121 char input1[MAX_INPUT]; 122 char input2[MAX_INPUT]; 123 char Add_Char_answer[MAX_INPUT]; 124 char Sub_Char_Answer[MAX_INPUT]; 125 126 struct Test Number1 ,MathSign, Number2 , Add_Answer , Sub_Answer; 127 128 struct Test *pNumber1 = &Number1; 129 struct Test *pNumber2 = &Number2; 130 struct Test *pAdd_Answer = &Add_Answer; 131 struct Test *pSub_Answer = &Sub_Answer; 132 133 // fgetsから入力を受け取り、改行を消去した後に文字列を反転させる。 134 printf("Enter The First Number \n"); 135 fgets(input1 , MAX_INPUT , stdin); 136 remove_newline_ch(input1); 137 ReverseStr(input1); 138 139 printf("Enter The Second Number \n"); 140 fgets(input2 , MAX_INPUT , stdin); 141 remove_newline_ch(input2); 142 ReverseStr(input2); 143 144 145 //入力をlonginit構造体に入れる。 146 pNumber1 -> val = input1; 147 pNumber2 -> val = input2; 148 pAdd_Answer-> val = Add_Char_answer; 149 // longinit_addを呼び出して加算。 150 Struct_add(pNumber1 , pNumber2 , pAdd_Answer); 151 Test_print(pAdd_Answer); 152 printf("Nunber (in main()) is %s \n",Add_Answer); 153 154 155} 156 157

差分

diff

161,62c61,63 2< char Add_Str_Lis[N]; 3< 4--- 5> char Add_Str_Lis[N+2]; 6> Add_Str_Lis[N] = '\0'; 7> int kuriage = 0; 882,83c83,89 9< 10< Add_Str_Lis[i] = (num1 + num2) + '0'; //文字化 11--- 12> sum = num1 + num2 + kuriage; 13> kuriage = 0; 14> if (sum > 9){ 15> sum = sum -10; 16> kuriage = 1; 17> } 18> Add_Str_Lis[i] = sum + '0'; //文字化 1986c92,95 20< 21--- 22> if (kuriage > 0){ 23> Add_Str_Lis[N] = kuriage + '0'; 24> Add_Str_Lis[N+1]= '\0'; 25> } 2690c99 27< 28--- 29> strcpy(r->val,String_R);

投稿2021/06/10 06:48

tatsu99

総合スコア5438

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問