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

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

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

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

Q&A

解決済

4回答

1308閲覧

char配列と数値配列の扱い方

Savanof

総合スコア33

C

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

0グッド

0クリップ

投稿2021/06/01 04:54

編集2021/06/01 08:52

前提・実現したいこと

昨日のこの質問の続きのような形になってしまって申し訳ありません。

C言語で多倍長整数の加算の実装を行おうと考えています。

下の様なワークフローで4番の実装を行おうと考えていたのですが、どうも文字配列と数字配列の扱い方が上手くいきません。

64行目以降のfor (int i = 1; i < N; i++){の部分で、二つの文字列から一つずつ要素を取り出し、数値型に変換する。数値型に変換した二つの要素を加算し、新規の配列に収納するという処理を行おうと思っているのですが、自分の意図した動作にならず、コードを自分の意図のようにかけません。

1. 文字列を2つ受け取る : ["1","2","3","4","5"] , ["1","7","8","9","1"] 2. 配列を逆に変換する  : ["5","4","3","2","1"] 3. 作成された二つの配列のうち、大きいサイズの方のサイズを基に新しい配列を作成する。 4. 二つの配列のそれぞれの要素の足し算を行う 例 : [5,4,3,2,1] と [1,9,8,7,1] という配列の場合 [(5+1) , (4+9) , (3+8) , (2+7) , (1+1)] → [6,13,11,9,2] ※ もし リストへのアクセスができない、範囲外の場合は0を割り当てる。 7. ある桁の数が10以上であれば、その桁を-10して、次の桁に1足す [6,13,11,9,2] → [6,3,2,0,3] 8. 配列を逆順にして、文字列に直す → "30236"

該当のソースコード

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <stdint.h> 4#include <string.h> 5#include <strings.h> 6#define MAX_INPUT 100 7 8 9// 二つの数を比較して大きい方を選択する 10int max(int a, int b) { return a > b ? a : b; } 11 12 13// 文字配列を逆順にする 14void revStr(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// main 30int main(){ 31 32 char input1[MAX_INPUT]; 33 char input2[MAX_INPUT]; 34 const char *p_input1; 35 const char *p_input2; 36 37 int input1_siz; 38 int input2_siz; 39 int ans_size; 40 41 42 printf("Enter The First LongInt \n"); 43 fgets(input1 , MAX_INPUT , stdin); 44 if(p_input1 = strchr(input1, '\n')){ 45 46 p_input1 = '\0'; 47 } 48 49 50 51 printf("Enter The Second LongInt \n"); 52 fgets(input2 , MAX_INPUT , stdin); 53 if(p_input2 = strchr(input2, '\n')){ 54 55 p_input2 = '\0'; 56 } 57 58 // input1,input2の配列サイズを入手する 59 input1_siz = strlen(input1); 60 input2_siz = strlen(input2); 61 62 // 二つの配列の内大きい方を作成する。 63 int N = (max(input1_siz, input2_siz)); 64 char ans_lis[N]; 65 66 revStr(input1); 67 revStr(input2); 68 69 for (int i = 0; i < N; i++){ 70 71 int num1 , num2; 72 // OutOfIndexしないようにする。 73 if(input1_siz < N){ 74 num1 = 0; 75 } 76 else{ 77 num1 = input1[i]- '0'; 78 } 79 80 if(input2_siz < N){ 81 num2 = 0; 82 } 83 else{ 84 num2 = input2[i] - '0'; 85 } 86 87 ans_lis[i] = (num1 + num2); 88 // printf("%d\n",ans_lis[i]); 89 // 最終的にはanslisも+'0'を行い文字列化する。 90 91 } 92 93 for(int i = 0; i <input1_siz;++i){ 94 printf("input1's no %d is %c \n" ,i,input1[i]); 95 } 96 97 for(int i = 0; i <input2_siz;++i){ 98 printf("input2's no %d is %c \n" ,i,input2[i]); 99 } 100 101 for(int i = 0; i <N;++i){ 102 printf("anslis's no %d is %d \n" ,i,ans_lis[i]); 103 } 104}

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

発生している問題がいくつかあるのですが、
1.文字配列を一文字ずつprintfすると、先頭が空白?になる
2.入力が"123" , "456"の場合はint_ans_lisの構造を[9,7,5]というようにしたいが、できない - 解決しました。
3.int_ans_lisの先頭にアクセスすると、意図しない数字(1998638272)が出現する。 - 解決しました。
これらの問題に対処できません。

Enter The First LongInt 123 Enter The Second LongInt 456 input1's no 0 is input1's no 1 is 3 input1's no 2 is 2 input1's no 3 is 1 input2's no 0 is input2's no 1 is 6 input2's no 2 is 5 input2's no 3 is 4 anslis's no 0 is -76 anslis's no 1 is 9 anslis's no 2 is 7 anslis's no 3 is 5

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

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

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

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

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

guest

回答4

0

ベストアンサー

1.文字配列を一文字ずつprintfすると、先頭が空白?になる

よく表示を見ると何が起こっているかわかります。

input1's no 0 is

input1's no 1 is 3

0のときのみ改行が多いです。
つまり0文字目には改行が入っています。
fgetsは通常入力文字列末尾に改行が入る仕様です。
(入らない場合もありえなくはない)

そのため

c

1fgets(input1 , MAX_INPUT , stdin); 2if(char* p = strchr(input1, '\n')){ 3 *p = '\0'; 4}

的な処理が必要です。

2.入力が"123" , "456"の場合はint_ans_lisの構造を[9,7,5]というようにしたいが、できない

atoiの使い方がまずいです。

char a[] = "123";の場合aには['1','2','3',0]が入ります。
atoi(&a[1])とするとatoiには['2','3',0]が渡り23が返ります。

atoiを使いたい場合は

c

1char atoi_buf[2] = {0}; 2atoi_buf[0] = input1[i]; 3num1 = atoi(atoi_buf);

としなければいけません。
面倒なのでASCIIコード表を分かってるプログラマーは

c

1num1 = input[i] - '0';

とします。

投稿2021/06/01 05:38

asm

総合スコア15149

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

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

Savanof

2021/06/01 09:16

回答ありがとうございます。atoiの仕様を把握せず、使用する事に固執し過ぎてしまったので実装が難しくなってしまいました。 fgetsで入力に改行が追加される事を今回把握したので、次からそうします。
guest

0

「発生している問題・エラーメッセージ」に示されたことを直接解決する回答ではありません:

もともとのご質問、

でいただいている回答で示唆されていること、つまり筆算でやることを実直にやっていけば良いのですが、atoiを無理に利用しようとするなど、少々ややこしい方向へ進んでいるように思います。これまでの回答やコメントでも一部指摘されていますが、例えば'0'と言う文字定数はASCIIコードの0x30で、'9'0x39、すなわち'9'から0x30を引くと0x39 - 0x30 = 0x099そのものになります。'9' - '0' = 9 です。

この性質を利用すると、charの配列の1文字1文字で計算できるようになり、繰り上がりにも対応できます。愚直な筆算をプログラムでやります。

以下は「123 + 198 = 321」を計算するプログラムの例です。簡単にするために、質問者さんのプログラム同様、下位桁を前に持ってきています。

C

1#include <stdio.h> 2 3/* 4 123 5+ 198 6------ 7答 321 8*/ 9int main() { 10 const char s1[] = "321"; 11 const char s2[] = "891"; 12 char ans[4]; 13 14 int v10 = 0; /* 繰り上がり分 */ 15 16 for (int i = 0; i < 3; i++) { 17 /* 下位桁の繰り上がりを意識しつつ、1桁を足す */ 18 int v = v10 + (s1[i] - '0') + (s2[i] - '0'); 19 20 /* 1の位のみ抽出 */ 21 int v1 = v % 10; 22 23 /* 繰り上がり分を保存 24 * ※ 10以上なら繰り上がっていてかつ19を超えることは無いので、 25 * v10 = 10 <= v ? 1: 0; でも良いかと。 26 */ 27 v10 = v / 10; 28 29 /* 当該桁をASCIIコードにして格納 */ 30 ans[i] = v1 + '0'; 31 } 32 33 ans[3] = '\0'; 34 printf("ans=[%s]\n", ans); 35 return 0; 36} 37 38

これを実行すると、以下のようになります。

terminal

1$ gcc -Wall t1.c 2$ ./a.out 3ans=[123]

出力は"123"ですが、これは"321"を示しています。繰り上がりも対応できていますね。これでいくらかヒントになったでしょうか。

投稿2021/06/01 05:51

dodox86

総合スコア9256

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

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

Savanof

2021/06/01 09:19

回答ありがとうございます。atoi関数を使う事にこだわり過ぎた、ASCIIコードの仕様を知らなかった事もあり、実装できていませんでした。 繰り上げ計算の部分の実装方針をかなりたってきたので、そうしてみます。
guest

0

パット見ですが、anslis[0]になんか変な値が入るのは、 int_ans_lis の計算を for (int i=1; i<N; i++) と、 i=1 から始めているせいですね。未初期化の値がそのまま出力されているものと思います

投稿2021/06/01 05:45

WoodenHamlet

総合スコア306

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

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

0

diff

1- const char *p_input1; 2- const char *p_input2; 3+ char *p_input1; 4+ char *p_input2; 5 6- p_input1 = '\0'; 7+ *p_input1 = '\0'; 8 9- p_input2 = '\0'; 10+ *p_input2 = '\0';

これで "123" と "456" は大丈夫でしょう。
何が悪かったか分かりますか?

でも、"123" と "987" はダメでしょう。

投稿2021/06/01 11:01

kazuma-s

総合スコア8224

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問