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

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

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

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

3回答

3245閲覧

文字列と文字列の文字を数値に変換する関数について。

carnage0216

総合スコア194

C

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

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2021/02/21 08:31

編集2021/02/22 03:13
#include <stdio.h> int main(void) { char str[] = "0123456789"; int a, b; sscanf_s(str + 2, "%1d", &a);//3番目の数字があるアドレスを指定して、1文字だけ数値として読み取る //引数(目的)にint型のaを用意するが、sscanf_sはアドレスしか扱えないようなので //&aとした。多分、strのアドレスを+2したときのアドレスに入っている数値(2)の変数aの入っている //「アドレスに入れるためにa自体のアドレスを表す&を付けたのだろう。そのaのアドレスに数値(2)が入るように」 sscanf_s(str + 5, "%1d", &b);//6番目の数字があるアドレスを指定して、1文字だけ数値として読み取る printf("%d\n", a + b);

での char str[] = "0123456789";の文字列ですが0123456789という文字を表しているのですよね?
**char str[] =**となる文字列はすべて文字のみを表しているとかでしょうか?
そして、仮に10や35など二桁を 文字列 に入れたい場合はどう書けばいいのでしょうか?
char str[] = "'12''473''900''4'";で合っていますか?
逆にchar str[] =で文字としての値ではなく数値としての文字列を表現することはできるのでしょうか?

二問目の質問です。
以下のプログラム

#include <stdio.h> #include <stdlib.h> int main(void) { char str[] = "0123456789"; int i = 0; int num = 0; int num2 = 0; int num3 = 0; int num4 = 0; num = atoi(str); printf("int型変数numの値は: %d\n", num); i = 2; num2 = str[i] - '0'; // atoiは文字列を数値にするものであって文字を数値にするものではない i = 5; num3 = str[i] - '0'; num4 = num2 + num3; printf("int型変数num4の値は: %d\n", num4); } ```では、 char str[] = "0123456789";の文字列は下に書いたプログラムより数値ではなく、「文字」としての数字を扱ってるため関数 atoiを使って、"1"と言う文字は'1'と言う数字、数値に変えられています。 どうやって文字の数字を数値に変えているのでしょうか? 原理とプログラムが知りたいです。 三つ目の問題です。 ```ここに言語を入力 #include <stdio.h> int main(void){ char str[] = "0123456789"; int a; a = (str[2] - '0') + (str[5] - '0'); //()は無くてもいいけど... printf("int型変数aの値は: %d\n",a); char dt[] = { 0,1,2,3,4,5,6,7,8,9 }; a = dt[2] + dt[5]; printf("int型変数aの値は: %d\n",a); return 0; }

'0'は数値としての0を表すのでしょうか?
仮にそうだとして、なぜ数字の文字である char str[] = "0123456789";より
(str[2] - '0')を見た時に文字の0(0の文字コード)とstr2と引き算が出来るのでしょうか?変だと思いました。
どうやってatoiの関数を使わずに文字列の文字を数値にせずに(str[2] - '0') できたのか。。。
どうか問題が複数ありますが一つ一つに回答して頂けるとありがたいです。そして私の間違いを正してください。

編集

#include <stdio.h> int main(void) { char str[] = "0123456789"; int a, b; sscanf_s(str + 2, "%1d", &a);//3番目の数字があるアドレスを指定して、1文字だけ数値として読み取る //引数(目的)にint型のaを用意するが、sscanf_sはアドレスしか扱えないようなので //&aとした。多分、strのアドレスを+2したときのアドレスに入っている数値(2)の変数aの入っている //「アドレスに入れるためにa自体のアドレスを表す&を付けたのだろう。そのaのアドレスに数値(2)が入るように」 sscanf_s(str + 5, "%1d", &b);//6番目の数字があるアドレスを指定して、1文字だけ数値として読み取る printf("%d\n", a + b);

に関して、sscanf_s(str + 2, "%1d", &a);で指定したアドレスにある文字は2で値は50です。そして、sscanf_s(str + 5, "%1d", &b);で指定されたアドレスにある文字は5で値は53です。それなのにprintf("%d\n", a + b);での実行結果は7となりました。なぜ103ではないのでしょうか?関数sscanf_sには関数atoiのような文字2などを値2にするような作用などあるのでしょうか?

編集1

#include <stdio.h> int main(void) { char str[] = "0123456789"; printf("%d\n", str[2] + str[4]); }

なぜ、配列の書き方が char str[] = "0123456789" の場合は
str[2] + str[4]の足し算が50+52で102と10進数で出るのでしょうか?
てっきり答えは6と思っていました。
char str[] = "0123456789";と書いて、かつ配列ので文字列の数字を扱う場合はそうなるルールなのでしょうか?

#include <stdio.h> int main(void) { char str[] = { 1,2,3,4,5 }; printf("%d\n", str[1] + str[3]); }

の char str[] = { 1,2,3,4,5 }; とした場合は6と出ます。

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

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

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

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

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

Zuishin

2021/02/21 08:35

知恵袋で教えて貰ってるはず。回答者に謝ってこい。
episteme

2021/02/21 08:49

山と里の往復を繰り返すコーモリか。
maisumakun

2021/02/21 10:38

> そして私の間違いを正してください。 いくつものサイトやハンドルを、それと知らせずに使い続けるのが最大の間違いかと。
carnage0216

2021/02/21 10:51

>>いくつものサイトやハンドルを、それと知らせずに使い続けるのが最大の間違いかと。 確かにそうですが、いろんな方のご意見や考えが知りたくて。ごめんなさい。
episteme

2021/02/21 11:37

> 、いろんな方のご意見や考えが知りたくて ルール/マナーを破る理由にならん。
m.ts10806

2021/02/21 21:14 編集

CとC++の並行がいつの間にか戻っている。 数日に一度あなたは初期化されるんですか? 成長しないのも納得。
m.ts10806

2021/02/22 03:46

もう「自分の都合よく動く言語」作ったらいいね。既存のドキュメント読めないんだから。 そしたら質問する必要もなく、周囲を巻き込むことなく。みんなしあわせ。
guest

回答3

0

C

1#include <stdio.h> 2#include <string.h> // memcpy 3 4int main(void) 5{ 6 char s1[4] = "012"; 7 char s2[4] = { '0', '1', '2', '\0' }; 8 char s3[4] = { 48, 49, 50 ,0 }; 9 char s4[4] = { 0x30, 0x31, 0x32 ,0x00 }; 10 char s5[4] = { '0', 49, 0x32, 0 }; 11 printf("[%s]\n", s1); 12 printf("[%s]\n", s2); 13 printf("[%s]\n", s3); 14 printf("[%s]\n", s4); 15 16 char s[5] = { 0x41, 0x42, 0x43, 0x44, 0 }; 17 printf("[%s]\n", s); 18 19 int i = 0; 20 memcpy(&i, s, 4); 21 printf("%d %#x\n", i, i); 22 23 float f = 0.0; 24 memcpy(&f, s, 4); 25 printf("%f %a\n", f, f); 26 27 char c[5] = { 0 }; 28 memcpy(c, &f, 4); 29 printf("[%s]\n", c); 30}

実行結果

text

1[012] 2[012] 3[012] 4[012] 5[ABCD] 61145258561 0x44434241 7781.035217 0x1.868482p+9 8[ABCD]

宣言時の初期化については、= "012";= { '0', '1', '2', '\0' }; は同じです。
'0' と 48 と 0x30 は常に同じです。
'\0' と 0 は常に同じです。
'0' と 0 は異なります。
'2' と 2 は異なります。

メモリ中の 0x41, 0x42, 0x43, 0x44 というデータがあったとします。
型が char[4] なら 'A', 'B', 'C', 'D' という値です。
型が int なら 1145258561 (0x4434241) という値です。
型が float なら 781.035217 という値です。

メモリ中の同じデータでも、型によって値が異なります。
型とは、データの値の意味を決定するものです。

定数 48 や 0x30 は値であり、型は int です。アドレスはありません。
文字定数 '0' は 48 という値であり、C では型は int です。アドレスはありません。
文字定数 '0' は 48 という値であり、C++ では型は char です。アドレスはありません。

int i = 0; という宣言があると、i は変数であり、型は int です。アドレスは &i です。
char c = '0'; という宣言があると、c は変数であり、型は char です。アドレスは &c です。
char s[4] = "abc"; という宣言があると、s は配列変数であり、型は「char [8]」です。
s[0]、s[1]、s[2]、s[3] という配列要素があり、それらは変数のようにふるまいます。

atoi のサンプル実装を示します。
実際の atoi がこうなっているわけではありません。

C

1#include <stdio.h> 2#include <ctype.h> // isspace, isdigit 3 4int atoi2(const char *s) 5{ 6 int negative = 0, i = 0, value = 0; 7 unsigned char c = s[i]; 8 while (isspace(c)) c = s[++i]; 9 if (c == '-') { negative = 1; c = s[++i]; } 10 else if (c == '+') c = s[++i]; 11 while (isdigit(c)) { value = value * 10 + (c - '0'); c = s[++i]; } 12 return negative ? -value : value; 13} 14 15int main(void) 16{ 17 int i = atoi2(" -753"); 18 printf("i = %d\n", i); 19}

投稿2021/02/22 05:16

kazuma-s

総合スコア8224

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

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

carnage0216

2021/02/22 05:42

ありがとうございます。 じっくり読みます。基礎で分からなくなったらここを見れるようにブックマークを付けておきます。
carnage0216

2021/02/22 05:49

ちなみに関数atoiを使い、配列char str[] = "0123456789";を用いて、 printf("%d\n", str[2] + str[4]);により整数6を求めるプログラムを組むことは可能でしょうか? 自分の中で汚いですが、組んだ際には関数atoiを使って組むことはできませんでした。
kazuma-s

2021/02/22 06:07 編集

なぜ、関数atoi を使うべきでないところで atoi を使おうとするんでしょうか? 答えてください。 2桁以上の文字列に対しては atoi は有用ですが、 1文字の数字を数値にするなら '0' を引くほうが簡単です。 もちろん atoi を使って 1文字の文字列から int の値を取得できますが、 それには atoi に渡す 1文字の文字列を用意する必要があります。 str とは別に 1文字の文字列を入れる「char の配列」を用意するか、 str の内容を変更して、そこに 1文字の文字列を作るかです。 後者の場合、str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); でしょうか?
carnage0216

2021/02/22 06:17

>>なぜ、関数atoi を使うべきでないところで atoi を使おうとするんでしょうか? 答えてください。 純粋な好奇心です。どうやって作ればいいのかなって考えてしまいます。自分では作れないのに。
carnage0216

2021/02/22 06:25 編集

ちなみにプログラムは以下のようで大丈夫でしょうか。 実行結果は2が出ました。 #include <stdio.h> #include <stdlib.h> int main(void) { char str[] = "0123456789";//char str[] = { '0','1','2','3','4','5','6','7','8','9','\0'};でもいい。 str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); }
carnage0216

2021/02/22 06:25 編集

以下のコードでも #include <stdio.h> #include <stdlib.h> int main(void) { char str[] = "0123456789";//char str[] = { '0','1','2','3','4','5','6','7','8','9','\0'};でもいい。 str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[4])-atoi(&str[2])); } 実行結果は2と出ました。なぜatoi(&str[2]), atoi(&str[4])をatoi(&str[4])-atoi(&str[2])と書いていないのに引き算と同じ結果の2が出来たのですか?
carnage0216

2021/02/22 06:30

図に書いたら少し理解できました。以下のプログラムでもできますね。 #include <stdio.h> #include <stdlib.h> int main(void) { char str[] = "0123456789";//char str[] = { '0','1','2','3','4','5','6','7','8','9','\0'};でもいい。 int a, b; str[3] = '\0'; printf("%d\n", atoi(&str[2])); }
kazuma-s

2021/02/22 06:33

> 後者の場合、str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); でしょうか? 疑問形で書いていますよね。 str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]) + atoi(&str[4])); としたら、期待通りの結果が出ました、という返事がほしかった。 なぜ、「+」にせずに「-」にしたんでしょうか? 元が str[2] + str[4] だから、+ と考えることが普通です。
Zuishin

2021/02/22 07:00 編集

連絡先を交換して二人で個人授業することはできないんでしょうか? 特に公開しなければならないような誰かの役に立つ質問は今までなかったと思いますし、マルチポストを垂れ流しても結局 kazuma-s さんの回答しか目に入っていないようです。kazuma-s さんもこの質問者の質問には必ず回答しているので、負担が増えることはないと思いますが。
Zuishin

2021/02/22 06:51

Qiita ならば記事を限定公開して、URL を知っている人にだけ見せることができます。記事は当然マークダウンが使えますし、そのコメントにも使えます。個人授業にはもってこいだと思いますがいかがでしょうか。 あるいは GitHub の issue も良いのではないかと思います。
carnage0216

2021/02/22 07:18 編集

なぜ、「+」にせずに「-」にしたんでしょうか? 2という整数を出すためです。 もちろん >>str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]) + atoi(&str[4])); としたら、期待通りの結果が出ました、という返事がほしかった。 atoi(&str[2]) + atoi(&str[4])とすることで6が得られるので期待した結果が出ます。 ただなぜprintf("%d\n", atoi(&str[2]), atoi(&str[4]));と書いただけで、 atoi(&str[4])- atoi(&str[2])と同じような2という整数が出る結果が出たのか知りたいです。
carnage0216

2021/02/22 07:41 編集

Zuishinさん、あの誰と連絡先を交換すればよいのでしょうか? 多分カズマさんと交換しろって言っているとは思うのですが、リクエストに応えてとりあえず聞いてみました。
kazuma-s

2021/02/22 08:52

> ただなぜprintf("%d\n", atoi(&str[2]), atoi(&str[4]));と書いただけで、 > atoi(&str[4])- atoi(&str[2])と同じような2という整数が出る結果が出たのか知りたいです。 printf を使って何年になりますか? 答えてください。 printf の書式と引数の対応が分からないのですか? 「書式」という用語を知らないのですか? Visual Studo でビルドした時、エラーメッセージや警告メッセージは読まないのですか? 4 - 2 は引き算をしなくても、引く数を表示すると 2 になるのが不思議ですか?
Zuishin

2021/02/22 09:37

> 後者の場合、str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); 引数多くありませんか?
carnage0216

2021/02/22 17:31

>> 引く数を表示すると 2 になるのが不思議ですか? いえ[2]にの持つ値が2なので、2が表示されたのかなと思っています。 なので正しくはprintf("%d\n", atoi(&str[2]));だと解釈しています。
kazuma-s

2021/02/22 23:22

> いえ[2]にの持つ値が2なので、 これは何ですか? きちんと書いてください。 また、質問にはすべて答えてください。 2021/02/22 14:49 > ちなみに関数atoiを使い、配列char str[] = "0123456789";を用いて、 > printf("%d\n", str[2] + str[4]);により整数6を求めるプログラムを > 組むことは可能でしょうか? > 自分の中で汚いですが、組んだ際には関数atoiを使って組むことはできませんでした。 最初の質問はこれでした。 2つのやり方があり、 「後者の場合、str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); でしょうか?」 と私は書きました。 これは正しい答えではないので、「でしょうか?」と書いています。 でも、正しい答えを導くためのヒントになることを書いています。 str[3] = '\0' と atoi(&str[2]) str[5] = '\0' と atoi(&str[4]) これから最初の質問の正しい答えである str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]) + atoi(&str[4])); が分かるはずです。 ところが、あなたは正しい答えにたどり着けず、そのまま書いて 「ちなみにプログラムは以下のようで大丈夫でしょうか。 実行結果は2が出ました。」と報告し、次に 「printf("%d\n", atoi(&str[4])-atoi(&str[2])); } 実行結果は2と出ました。なぜatoi(&str[2]), atoi(&str[4])をatoi(&str[4])-atoi(&str[2])と書いていないのに引き算と同じ結果の2が出来たのですか?」 と書いて泥沼にはまっていきました。 atoi を使って「整数6」を求めるプログラムが知りたいのに、 ヒントをもらっても正しいプログラムにはたどり着けず、 いつのまにか「整数2」を求めるプログラムに問題をすり替えています。 こういった経緯を把握していますか?
Zuishin

2021/02/22 23:34

> 後者の場合、str[3] = str[5] = '\0'; printf("%d\n", atoi(&str[2]), atoi(&str[4])); 引数多くありませんか?
kazuma-s

2021/02/22 23:43

質問者の理解を試すために、「エラーではないけれど間違ったコード」を書いている ということを Zuishin さんは読み取れないのですか?
Zuishin

2021/02/22 23:47

試さなくても理解できるはずがないとまだわかりませんか?
Zuishin

2021/02/22 23:50

あなたが今まで書いた数々の「俺 SUGEEE だろコード」でこの人が大混乱してあちこちに迷惑をかけています。他を巻き込まず二人で話すことはできませんか?
Zuishin

2021/02/23 00:10

「こんな XXX なコードをいつもどこから拾ってくるのか」「書き方が古臭い」「イキったコード」と、このような陰口をたたかれているのを知っていますか?
carnage0216

2021/02/24 03:52

>>質問者の理解を試すために、「エラーではないけれど間違ったコード」を書いている それは困ります。ただでさえ迷走してるのにさらに迷走してしまいます。 printfの使い方くらいわかってるのに、引数の数が多いので警告はでるけど、カズマさんの書いたコードが正しい信用してコンパイルしたと思いきや、あえて間違ったコードを送られ、printfも使いこなせないのかのように言われるのはなんか嫌です。 >>> いえ[2]にの持つ値が2なので、 これは何ですか? きちんと書いてください。 また、質問にはすべて答えてください。 配列str[2]が持つ数値が2ということを言いたかったのです。
guest

0

char str[] = "0123456789";の文字列ですが0123456789という文字を表しているのですよね?
char str[] =となる文字列はすべて文字のみを表しているとかでしょうか?

合ってます。

そして、仮に10や35など二桁を 文字列 に入れたい場合はどう書けばいいのでしょうか?

char str[] = "10";

char str[] = "35";
ですね。

char str[] = "'12''473''900''4'";で合っていますか?

は、'12''473''900''4'という数字・引用符混じりの文字列です。

逆にchar str[] =で文字としての値ではなく数値としての文字列を表現することはできるのでしょうか?

「数値としての文字列」の意味が不明です。数値は文字列ではありません。

関数 atoiを使って、"1"と言う文字は'1'と言う数字、数値に変えられています。

どうやって文字の数字を数値に変えているのでしょうか?

atoiの中身がそういうプログラムになっています。そんなに難しいプログラムではないので、Cを学んで数週間レベルであれば自分で書けます。

'0'は数値としての0を表すのでしょうか?

いいえ。文字としての0です。
あるいは、正確には、0という文字の文字コード表す数値です(普通の環境では数値の48)。

なぜ数字の文字である char str[] = "0123456789";より

(str[2] - '0')を見た時に文字の0(0の文字コード)とstr2と引き算が出来るのでしょうか?

09数字の文字コードは、連続しています。
つまり、「2の文字コード = 0の文字コード + 2」です。
移項すると「2の文字コード - 0の文字コード」は2です。

どうやってatoiの関数を使わずに文字列の文字を数値にせずに(str[2] - '0') できたのか。。。

これで分かったでしょうか?1桁の数字なら、'0'を引くだけで数値になります。

投稿2021/02/21 09:57

otn

総合スコア85901

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

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

carnage0216

2021/02/21 10:50 編集

なるほど、文字コードの0の値は48で2の文字コード2の文字コードの値は50なので、 引いて答えが値が2というわけですね。 またchar str[] = には様々な書き方がありますが、すべて文字コードを表す文字で、値と言うのは文字コードの値と言うものであり、例えばchar str[] ={'1''2''3''4'}の文字コードを値で表すと char str[] ={'49''50''51''52'}となる。ただ、私のしたかったことはそうではなく、文字コードの文字のままを数値にしたかったため関数atoiかsscanf(環境によってはsscanf_s)を使いchar str[] ={'1''2''3''4'}を数値1,2,3,4としたかったのです。
otn

2021/02/21 12:20

> 例えばchar str[] ={'1''2''3''4'}の文字コードを値で表すとchar str[] ={'49''50''51''52'}となる。 いいえ。char str[] ={49,50,51,52}; です。 > 文字コードの文字のままを数値にしたかったため char sr[] = "1,2,3,4"; sscanf(str, "%d,%d,%d,%d", &a, &b, &c, &d); のようなことをしたいという事でしょうか?
guest

0

char というのは、1バイトの整数型、です。
文字も入れることができるってだけの話なので、数値を入れたいなら普通に代入すればいいです

そして、仮に10や35など二桁を 文字列 に入れたい場合はどう書けばいいのでしょうか?

char str[]={ 10,35,うんちゃらかんちゃら };

投稿2021/02/21 08:53

編集2021/02/21 09:03
y_waiwai

総合スコア88042

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

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

carnage0216

2021/02/21 09:24

しかし、その10や35は「値」ではなく値の形をした「文字」、ようは文字コードなのですよね?
y_waiwai

2021/02/21 10:38

ちがいますよ。整数の数値です
carnage0216

2021/02/21 10:54

え、、、 ですがotnさんより char str[] = "0123456789";の文字列ですが0123456789という文字を表しているのですよね? char str[] =となる文字列はすべて文字のみを表しているとかでしょうか? という疑問に対する答えははいでしたが。 char str[]={ 10,35,うんちゃらかんちゃら };の書き方だと、文字コードとかではなく、10、35とそのまま値が取れるのですか?そんなはずはないと思うのですが。。。
y_waiwai

2021/02/21 10:56

実際にやってみましょうよ。
carnage0216

2021/02/22 03:09

おお、前言撤回します。すいませんでした。 なるほど、char str[] =の書き方によっては数字は文字としても扱えるし、数値としても扱えるわけですね!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.35%

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

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

質問する

関連した質問