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

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

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

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

Q&A

解決済

4回答

2594閲覧

c言語のcharのmemsetの使い方

Hamada-hiro

総合スコア6

C

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

0グッド

0クリップ

投稿2019/12/26 14:40

編集2019/12/26 16:40

前提・実現したいこと

ここに質問の内容を詳しく書いてください。
文字列の比較をするプログラムをC言語で作っています。
エラーがcharの初期設定で出ていると思いますが、よくわかりません。
初期化はmemsetを使っています。

P2.c:13:15:エラー:バイナリ式に対する無効なオペランド( 'char [3]'および
'char [11]')
scanf( "%c"&a);
~~~~ ^〜
このエラー文が全くわかりません。
複数の文字を入れたいので%sではいけないんですか?

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

P2.c:5:5: warning: implicitly declaring library function 'memset' with type 'void *(void *, int, unsigned long)' [-Wimplicit-function-declaration] memset(a,'¥0', 11); ^ P2.c:5:5: note: include the header <string.h> or explicitly provide a declaration for 'memset' P2.c:5:14: error: character too large for enclosing character literal type memset(a,'¥0', 11); ^ P2.c:5:14: warning: multi-character character constant [-Wmultichar] P2.c:8:14: error: character too large for enclosing character literal type memset(b,'¥0', 11); ^ P2.c:8:14: warning: multi-character character constant [-Wmultichar] P2.c:12:15: error: invalid operands to binary expression ('char [3]' and 'char [11]') scanf("%s"&a); ~~~~^~ P2.c:14:15: error: invalid operands to binary expression ('char [3]' and 'char [11]') scanf("%s"&b); ~~~~^~ P2.c:16:5: warning: implicitly declaring library function 'strcmp' with type 'int (const char *, const char *)' [-Wimplicit-function-declaration] strcmp(a,b); ^ P2.c:16:5: note: include the header <string.h> or explicitly provide a declaration for 'strcmp' P2.c:17:9: error: array type 'char [11]' is not assignable if(a=b) ~^ 4 warnings and 5 errors generated. moridaiakira-no-MacBook-Air:desktop Taisei$ gcc -o program P2.c P2.c:4:10: error: definition of variable with array type needs an explicit size or an initializer char a[]; ^ P2.c:5:5: warning: implicitly declaring library function 'memset' with type 'void *(void *, int, unsigned long)' [-Wimplicit-function-declaration] memset(a,'¥0', 11); ^ P2.c:5:5: note: include the header <string.h> or explicitly provide a declaration for 'memset' P2.c:5:14: error: character too large for enclosing character literal type memset(a,'¥0', 11); ^ P2.c:5:14: warning: multi-character character constant [-Wmultichar] P2.c:7:10: error: definition of variable with array type needs an explicit size or an initializer char b[]; ^ P2.c:8:14: error: character too large for enclosing character literal type memset(b,'¥0', 11); ^ P2.c:8:14: warning: multi-character character constant [-Wmultichar] P2.c:16:5: warning: implicitly declaring library function 'strcmp' with type 'int (const char *, const char *)' [-Wimplicit-function-declaration] strcmp(a,b); ^ P2.c:16:5: note: include the header <string.h> or explicitly provide a declaration for 'strcmp' 4 warnings and 4 errors generated.

該当のソースコード

C言語

1#include<stdio.h> 2int main(void) 3{ 4 char a[]; 5 memset(a,'¥0', 11); 6 7 char b[]; 8 memset(b,'¥0', 11); 9 10 printf("2つの文字列を入力してください。"); 11 printf("文字列1:"); 12 scanf("%s"&a); 13 printf("文字列2:"); 14 scanf("%s"&b); 15 16 strcmp(a,b); 17 if(a=b) 18 { 19 printf("結果:2つの文字は一致します。(%s,%s)",a,b); 20 } 21 else 22 { 23 printf("結果:2つの文字は一致しません.(%s,%s)",a,b); 24 } 25 26 27 28}

試したこと

ここに問題に対して試したことを記載してください。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

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

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

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

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

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

SaitoAtsushi

2019/12/26 15:29

質問がかかれていません。 あなたがエラーメッセージをよくわからないことはわかりましたがあなたが聞きたい質問を提示してください。
jimbe

2019/12/26 15:32

> よくわかりません 一つ一つのエラーメッセージがそれぞれ何を言っているのかをお調べの上, 一つ一つ対処してください. 関係無い複数個所のエラーメッセージが一緒に出ていたり, 一つのエラーの所為で他でもエラーになっている等がありますので, 解きほぐす必要があります.
Hamada-hiro

2019/12/26 15:56

すいません。 P2.c:5:10:エラー:配列型の変数の定義には明示的なサイズが必要です       または初期化子     char a [];          ^ P2.c:6:14:エラー:文字が文字リテラルタイプを囲むには大きすぎます     memset(a、 '¥0'、11);              ^ 初期化が必要との事でしたがmemsetで設定ができているのではないのですか?
guest

回答4

0

言いたいことがいっぱいあって何から言えばいいんだか、な気分ですが。多分言い過ぎで質問者さんはオーバーフローするだろうなぁ...

まずは、質問のメッセージですね。コンパイラは、あなたの意思に関係なく、書いてある文字列をCのプログラムとして可能な形で解釈しようとします。その目でみると
scanf( "%c"&a);
は「scanf」「(」「"」「%c」「"」「&」「a」「)」という要素(トークン)に分解できます。

  • 「scanf」はナニカの名前...stdio.hに書かれている部分で、それは関数の名前だとコンパイラは知ります。
  • 「(」は、その直前の名前の関数を、このあと書かれている引数を持って呼び出す指示です。
  • 「"」「%c」「"」めんどくさいのでまとめますが、文字列リテラル(直書きの定数、と言っていいかな)です。メモリ上にchar型の配列としてそのデータを作成し、ポインタ(データの先頭アドレス)を返します。
  • 「&」ビット毎論理積の演算子です
  • 「a」整数型を要素とする配列です。配列が単独で記述されると、Cでは配列の最初の要素へのポインタと解釈します
  • 「)」引数並びの終わりです

そうすると、これは"%c"へのポインタの値とaの最初の要素へのポインタの値とのビット論理積をとって、それを引数としてscanf関数に渡して呼び出す、という処理に解釈するしかないのですが、ポインタ値の間でビット演算をする、というのはなんじゃそんな演算定義されてないぞ、ということでエラーにされた、ということです。

人間が見れば"%c"と&aの間に','があればなぁ、という想像もしますが、コンピュータはそんな忖度してくれません。まぁ、目茶苦茶な解釈をされたらキータイプのミスとかを疑う、という習慣で対処するとかいうところでしょう。

複数の文字を入れたいので%sではいけないんですか?

え? %sなんか使ってないじゃない。それはもしかして、"%c"と"%s"の区別がわからないということ?

なお、手元のgccではinvalid operands to binary & (have ‘char *’ and ‘char *’)となります。c++としてコンパイル(g++)するとinvalid operands of types ‘const char [3]’ and ‘char [11]’ to binary ‘operator&’なので、もしかしてC++としてコンパイルしてないかな、というのが気になるところ。

それと。何も考えずにscanfに与える変数に&を付けていたりするのかな。このscanfに与えるaには&は付けるべきじゃないです。付けても実行するには不都合はないですけれど、文法的にはおかしなこと。よくわからなくていーかげんなことをやっているというのが見る人が見るとバレる、ということになります。配列は(先にもちょっと書いたけど)単独で記述されるとその先頭要素へのポインタと解釈されます。一方、&はこの場合はオペランドの変数のアドレスを求める演算子。「配列そのもの」があるアドレスを求めます。配列の構造から考えれば、配列の先頭要素へのポインタと配列そのものへのポインタは同じアドレスになりますから動いちゃいますけど、意味が違うんです。

それと、char a[];でエラーになってしまうのが先のはずなのですが。それが引っかからないというのは、コンパイルしたのは本当に質問にあるソースなのでしょうか? そうでないとすると、何の議論をしているのかわからなくなってしまうこともあるので確認していただきたいです。

なんだかmemsetも話題になっていますが、まず警告を読むとわかるのは、ちゃんとした宣言が与えられていないので(memsetはよく使うから通してやる、みたいな話で)齟齬が発生しているようです。
#include <memory.h>かなにかで宣言を与えてやりましょう。
で、ここはmemsetも意味を理解して使うなら構わないのですが、初心者が意味もわからず初期値を与えるのにmemsetで0にするような使い方は私はおすすめはしません。
char a[11]={0}; //最初の要素に0を与え、初期化記述が足りない要素は0が自動補填されて初期化
とか
char a[11]=""; //空の文字列(つまり'\0')で初期化。足りない分は同上
とかにしておいてはいかがでしょう。(もちろん、これは「代入」ではないのでプログラムの途中で変数に値を与えるのには使えない書式ですが)

投稿2019/12/27 05:46

thkana

総合スコア7629

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

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

Hamada-hiro

2019/12/27 13:36

本当に丁寧に説明してくださり有り難うございます。 %dの時は&を付けていたんですが、今回は文字列だから&は付けないと考えてもいいんですか?それともaが初期化されていないからでしょうか? 何度も本当にすいません。
majiponi

2019/12/27 13:47

配列aに対して、次の2つの表記はほぼ同じ意味となります。 &a[0] と a いずれも、配列の先頭要素であるa[0]のアドレスを意味します。 %dのときも%sのときも、第2引数以降は変数のアドレスを渡す必要がありますが、aが配列であるため、&を省略して書ける、というだけなのです。
Hamada-hiro

2019/12/27 13:58

理解できました!丁寧に教えて下さり有り難うございます!
thkana

2019/12/27 22:56 編集

&を省略、というのは不十分な言い方かと。&aでなくa、という疑問なのですから。 aだけでいいというのは、配列は、単独で記述されるとその先頭要素へのポインタと解釈される、というCの規則があるから、&をつける必要がないのです。この規則により、aと&a[0]とが等価(記法が違うだけでおなじもの)。逆に、&aとすると意味が変わってしまいます。 例えば char a[11]; において、 printf("%p\n",a); printf("%p\n",&a); は同じ値が表示されるけれど(だからとりあえずは動く)、その違いの例を知りたければ... printf("%p\n",a+1); printf("%p\n",&a+1); あるいは printf("%d\n",sizeof(*a)); printf("%d\n",sizeof(*(&a))); として結果をみるといいてす。 (もしかして、scanfに渡す変数になんで&をつけたりするのか、という話が必要?)
guest

0

P2.c:13:15:エラー:バイナリ式に対する無効なオペランド( 'char [3]'および
'char [11]')
scanf( "%c"&a);

このエラーの意味が他の回答者さんのものには記載されていなかったので。 ```scanf("%c"&a);```という文は、まず、文字列リテラル"%c"(要素数3のchar型配列)と、変数a(要素数11のchar型配列)のビット積をとり、その結果をscanf関数の第1引数として、scanf関数を呼び出す、という意味になります。コンパイラのエラーは、配列のビット積はとれないぞ、という意味です。 引数を区切る場合、```scanf("%c", &a);```のように、カンマが必要となります。 ところで、他の回答者さんも指摘されていますが、質問コードは、問題のコードを「そのまま」コピペで入力してください。表示が崩れるからと、記号を全角にされてしまいますと、正しいアドバイスができなくなります。<code>というボタンを利用すれば、半角文字のままでも崩れないようにできます。

投稿2019/12/26 23:09

majiponi

総合スコア1720

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

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

0

ベストアンサー

char a[];

サイズが必要です。11文字なら↓
char a[11];
memset(a, '\0', sizeof a);
[追記]

text

1#include<stdio.h> 2#include <string.h> ←memset(),strcmp() 3 4int main(void) 5{ 6 char a[]; ←サイズが必要 7 memset(a,'¥0', 11); 8 9 char b[]; ←サイズが必要 10 memset(b,'¥0', 11); 11 12 printf("2つの文字列を入力してください。"); 13 printf("文字列1:"); 14 scanf("%s"&a); →scanf("%s",a); 15 printf("文字列2:"); 16 scanf("%s"&b); →scanf("%s",b); 17 18 strcmp(a,b); ←不要 19 if(a=b) ←if(strcmp(a,b)==0) 20 { 21 printf("結果:2つの文字は一致します。(%s,%s)",a,b); 22 } 23 else 24 { 25 printf("結果:2つの文字は一致しません.(%s,%s)",a,b); 26 } 27 28 29 return 0; 30}

出来ましたか?

text

1usr ~/Project/test % ./a.out 22つの文字列を入力してください。 3文字列1:1234 4文字列2:1234 5結果:2つの文字は一致します。(1234,1234) 6usr ~/Project/test % ./a.out 72つの文字列を入力してください。 8文字列1:1234 9文字列2:1235 10結果:2つの文字は一致しません.(1234,1235)

以下は結構自己流v^^;・・・文字列が長くて、改行が入らなかった時の確認していません。
各関数はC言語関数辞典を確認して下さい。
usr ~/Project/test % cat t2.c

c

1#include <stdio.h> 2#include <string.h> 3 4#define BUFF_SIZE (11) 5 6int main(void) 7{ 8 char a[BUFF_SIZE] = {0}; 9 char b[BUFF_SIZE] = {0}; 10 // 11 printf("2つの文字列を入力してください。\n"); 12 // 13 printf("文字列1:"); 14 fgets(a, sizeof a, stdin); 15 a[strlen(a) - 1] = '\0'; 16 // 17 printf("文字列2:"); 18 fgets(b, sizeof b, stdin); 19 b[strlen(b) - 1] = '\0'; 20 // 21 if(strcmp(a, b) == 0) { 22 printf("結果:2つの文字は一致します。(%s,%s)\n", a, b); 23 } else { 24 printf("結果:2つの文字は一致しません.(%s,%s)\n", a, b); 25 } 26 27 return 0; 28}

投稿2019/12/26 16:26

編集2019/12/27 03:16
cateye

総合スコア6851

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

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

Hamada-hiro

2019/12/26 16:34

memset(a,'\0',11); これとおんなじ意味ではないのですか?
cateye

2019/12/26 16:40 編集

現状では同じですが、aのサイズを変えてもmemset()は変更しなくてすみます。 参考→https://ja.wikipedia.org/wiki/%E3%83%9E%E3%82%B8%E3%83%83%E3%82%AF%E3%83%8A%E3%83%B3%E3%83%90%E3%83%BC_(%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%A0)
Hamada-hiro

2019/12/26 16:41

簡単になるんですね!ありがとうございます!
cateye

2019/12/27 00:06 編集

if(a=b) は文字列の比較ではなく、配列のアドレス代入(比較ではない)になっています。 ・・・やったことがないので、どうなるか? ・・・コンパイルエラー↓ P2.c:17:9: error: array type 'char [11]' is not assignable また、C言語に文字列を直接比較する演算子はありません、
cateye

2019/12/27 03:32

文字列が長い時は↓のように成りますw。 usr ~/Project/test % ./a.out 2つの文字列を入力してください。 文字列1:0123456789012 文字列2:結果:2つの文字は一致しません.(012345678,012) usr ~/Project/test % ./a.out 2つの文字列を入力してください。 文字列1:012345678901234567890 文字列2:結果:2つの文字は一致します。(012345678,012345678)
Hamada-hiro

2019/12/27 14:01

本当に有り難うございます。 やりたいように表示する事ができ理解できました。
guest

0

ちゃんとエラーメッセージ読んでくださいね。せっかくなのでGoogle 翻訳というすばらしいサービスにぶちこんだ結果置いときますね。

P2.c:5:5:警告:ライブラリ関数 'memset'を型で暗黙的に宣言しています 'void *(void *、int、unsigned long)' [-Wimplicit-function-declaration] memset(a、 '¥0'、11); ^ P2.c:5:5:注:ヘッダー<string.h>を含めるか、明示的に 「memset」の宣言 P2.c:5:14:エラー:文字が大きすぎて文字リテラル型を囲むことができません memset(a、 '¥0'、11); ^ P2.c:5:14:警告:複数文字の文字定数[-Wmultichar] P2.c:8:14:エラー:文字が大きすぎて文字リテラル型を囲むことができません memset(b、 '¥0'、11); ^ P2.c:8:14:警告:複数文字の文字定数[-Wmultichar] P2.c:12:15:エラー:バイナリ式に対する無効なオペランド( 'char [3]'および 'char [11]') scanf( "%s"&a); ~~~~ ^〜 P2.c:14:15:エラー:バイナリ式に対する無効なオペランド( 'char [3]'および 'char [11]') scanf( "%s"&b); ~~~~ ^〜 P2.c:16:5:警告:タイプを使用してライブラリ関数 'strcmp'を暗黙的に宣言しています 'int(const char *、const char *)' [-Wimplicit-function-declaration] strcmp(a、b); ^ P2.c:16:5:注:ヘッダー<string.h>を含めるか、明示的に 「strcmp」の宣言 P2.c:17:9:エラー:配列型 'char [11]'は割り当て不可 if(a = b) 〜^ 4つの警告と5つのエラーが生成されました。 森代明のMacBook-Air:デスクトップ大成$ gcc -o program P2.c P2.c:4:10:エラー:配列型の変数の定義には明示的なサイズが必要です または初期化子 char a []; ^ P2.c:5:5:警告:ライブラリ関数 'memset'を型で暗黙的に宣言しています 'void *(void *、int、unsigned long)' [-Wimplicit-function-declaration] memset(a、 '¥0'、11); ^ P2.c:5:5:注:ヘッダー<string.h>を含めるか、明示的に 「memset」の宣言 P2.c:5:14:エラー:文字が大きすぎて文字リテラル型を囲むことができません memset(a、 '¥0'、11); ^ P2.c:5:14:警告:複数文字の文字定数[-Wmultichar] P2.c:7:10:エラー:配列型の変数の定義には明示的なサイズが必要です または初期化子 char b []; ^ P2.c:8:14:エラー:文字が大きすぎて文字リテラル型を囲むことができません memset(b、 '¥0'、11); ^ P2.c:8:14:警告:複数文字の文字定数[-Wmultichar] P2.c:16:5:警告:タイプを使用してライブラリ関数 'strcmp'を暗黙的に宣言しています 'int(const char *、const char *)' [-Wimplicit-function-declaration] strcmp(a、b); ^ P2.c:16:5:注:ヘッダー<string.h>を含めるか、明示的に 「strcmp」の宣言 4つの警告と4つのエラーが生成されました。

投稿2019/12/26 15:39

yumetodo

総合スコア5850

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

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

SaitoAtsushi

2019/12/26 15:53

¥0 がどう間違ってるのかはちょっと初心者には気づきにくいかもしれませんね……。 特に紙の本で学んでると。 他は入門書をひととおり読めば理解できると思うんですが。
Hamada-hiro

2019/12/26 16:01

¥0の使い方が違いますか?
SaitoAtsushi

2019/12/26 16:07

これは調べてもわからないと思うので言っちゃいます。 `¥` ではなく `\` を使ってください。 ↑ これ、ひょっとして両方とも円マークに見えます? アスキーコードでバックスラッシュということになっている箇所に日本語環境では伝統的に円マークのグリフ割り当てることがあります。 書籍などでは円マークで書かれていることがありますし、ブラウザ上でも設定によっては円マークのように見えますが、実態としてはバックスラッシュでなければなりません。 円マークは円マークで別に符号が存在し、今回はそっちを使ってしまっているという状態です。
Hamada-hiro

2019/12/26 16:11

わかりました。\0を使ってやってみます
yumetodo

2019/12/26 17:39

まあ全般になぜか日本語IME有効の状態で,やら&やらその他ものもろ打ってるから全部死んでいっている感じですね。あるいはそのせいで打ててなくて死んでいっている。
yumetodo

2019/12/26 17:41

まあそもそもプログラミングするときはHackGenのようなそういうのがわかりやすいフォントを使うと生産性が上がります。 https://github.com/yuru7/HackGen
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問