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

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

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

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

Q&A

解決済

4回答

1788閲覧

C言語 単語をASCII順に並び替えたい

varmosy

総合スコア4

C

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

1グッド

1クリップ

投稿2024/01/03 07:36

編集2024/01/03 09:24

実現したいこと

10個の単語one, two, three, ... , ten をASCIIコード順に並び替えるプログラム(C言語)でポインタを使って作りたいです。VScodeです
初学者なので、もしよろしければ丁寧に教えてほしいです。
main関数のところのprintf辺りは課題の要件に沿った記述方法なので気にしないでください。

発生している問題・分からないこと

自分では原因のわからないエラーコードが発生します。
なぜ下記のようなエラーコードがでるのか、またどうしたら直るのか、どのようにしたら上記のプログラムを実現できるのか教えてほしいです。

エラーメッセージ

error

1passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion] 2passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion] 3passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion] 4passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion] 5passing argument 1 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]

該当のソースコード

#include <stdio.h> #include <string.h> int moji(char p[], char q[]) { if(p[0]>q[0]){ return 1; }else if(p[0]==q[0] && p[1]>q[1]){ return 1; }else{ return -1; } } void swap(char *a) { for(int i=0; i<10; i++){ for(int j=i+1; j<10; j++){ if(moji((char*)(a+i), (char*)(a+j))==1){ char x[10]; strcpy(x, a[i]); strcpy(a[i], a[j]); strcpy(a[j], x); } } } } int main(void) { char *a[10]={"one","two","three","four","five","six","seven","eight","nine","ten"}; swap(&a[0]); for(int k=0; k<3; k++){ for(int l=0; l<3; l++){ printf("%s,", a[3*k+l]); } printf("\n"); } printf("%s\n", a[9]); return 0; }

試したこと・調べたこと

  • teratailやGoogle等で検索した
  • ソースコードを自分なりに変更した
  • 知人に聞いた
  • その他
上記の詳細・結果

3日くらいかけて調べて色々試しましたが、全く回復しませんでした。
色々調べすぎて、もはや何が正しいのかもよくわかりません。

補足

特になし

tatsu99👍を押しています

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

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

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

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

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

jimbe

2024/01/03 09:00

c と c++ は別の言語です。 c の質問でしたら c++ のタグは不要です。
varmosy

2024/01/03 09:25

コメントありがとうございます。タグの修正をいたしました。
jimbe

2024/01/03 12:39

編集ありがとうございます。
guest

回答4

0

char a[10][10] = {"one","two","three","four","five","six","seven","eight","nine","ten"};

のように定義した場合の変数aの状態は、以下のようになります。
イメージ説明
この場合は、strcpyによる入れ替えが可能になります。
以下、そのサンプルです。

C

1#include <stdio.h> 2#include <string.h> 3 4int moji(char p[], char q[]) 5{ 6 if(p[0]>q[0]){ 7 return 1; 8 }else if(p[0]==q[0] && p[1]>q[1]){ 9 return 1; 10 }else{ 11 return -1; 12 } 13} 14 15void swap(char a[10][10]) 16{ 17 for(int i=0; i<10; i++){ 18 for(int j=i+1; j<10; j++){ 19 if(moji((char*)(a+i), (char*)(a+j))==1){ 20 char x[10]; 21 strcpy(x, a[i]); 22 strcpy(a[i], a[j]); 23 strcpy(a[j], x); 24 } 25 } 26 } 27} 28 29int main(void) 30{ 31 char a[10][10] = {"one","two","three","four","five","six","seven","eight","nine","ten"}; 32 printf("---Before swap---\n"); 33 for (int i = 0;i<10;i++){ 34 printf("%s\n",a[i]); 35 } 36 swap(a); 37 printf("---After swap---\n"); 38 for (int i = 0;i<10;i++){ 39 printf("%s\n",a[i]); 40 } 41/* 42 for(int k=0; k<3; k++){ 43 for(int l=0; l<3; l++){ 44 printf("%s,", a[3*k+l]); 45 } 46 printf("\n"); 47 } 48 printf("%s\n", a[9]); 49*/ 50 return 0; 51} 52

実行結果
---Before swap---
one
two
three
four
five
six
seven
eight
nine
ten
---After swap---
eight
five
four
nine
one
seven
six
ten
three
two

投稿2024/01/04 03:04

編集2024/01/04 04:27
tatsu99

総合スコア5540

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

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

0

修正しておきました。
char *a[10]={"one","two","three","four","five","six","seven","eight","nine","ten"};
で定義した場合、変数aの状態は、以下のようになります。
イメージ説明
この場合、strcpyによる入れ替えはできません。ポインターの付け替えのみが可能となります。

C

1#include <stdio.h> 2#include <string.h> 3 4int moji(char p[], char q[]) 5{ 6 if(p[0]>q[0]){ 7 return 1; 8 }else if(p[0]==q[0] && p[1]>q[1]){ 9 return 1; 10 }else{ 11 return -1; 12 } 13} 14 15void swap(char *a[10]) 16{ 17 char *x; 18 for(int i=0; i<10; i++){ 19 for(int j=i+1; j<10; j++){ 20 if(moji(a[i],a[j])==1){ 21 x = a[i]; 22 a[i] = a[j]; 23 a[j] = x; 24 } 25 } 26 } 27} 28 29int main(void) 30{ 31 char *a[10]={"one","two","three","four","five","six","seven","eight","nine","ten"}; 32 printf("---Before swap---\n"); 33 for (int i = 0;i<10;i++){ 34 printf("%s\n",a[i]); 35 } 36 swap(&a[0]); 37 printf("---After swap---\n"); 38 for (int i = 0;i<10;i++){ 39 printf("%s\n",a[i]); 40 } 41 42/* 43 for(int k=0; k<3; k++){ 44 for(int l=0; l<3; l++){ 45 printf("%s,", a[3*k+l]); 46 } 47 printf("\n"); 48 } 49 printf("%s\n", a[9]); 50*/ 51 return 0; 52} 53

実行結果
---Before swap---
one
two
three
four
five
six
seven
eight
nine
ten
---After swap---
eight
five
four
nine
one
seven
six
ten
three
two

投稿2024/01/03 10:31

編集2024/01/04 02:56
tatsu99

総合スコア5540

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

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

varmosy

2024/01/04 01:41

回答ありがとうございます。tatsu99 さんのコードでエラー等は起きなかったです。本当にありがとうございます。 まだまだ理解できていない部分も有るので、C言語の勉学に励みたいと思います。
tatsu99

2024/01/04 03:00

char *a[10]={"one","two","three","four","five","six","seven","eight","nine","ten"}; のように定義した場合の、変数aの状態を図で示しました。この場合、strcpyは使用できません。 char a[10][10] = {"one","two","three","four","five","six","seven","eight","nine","ten"}; のように定義した場合は、strcpyによる入れ替えが可能になります。 strcpyによる入れ替えのサンプルを別途回答します。
varmosy

2024/01/04 04:13 編集

ありがとうございます! 一つ質問なのですが、char a[10][10] というのは、単語(10文字以下)が10個ある文字配列、という認識でよろしいでしょうか? [修正] すいません、もう一方の回答で理解できました。ありがとうございます。
guest

0

ベストアンサー

swap 関数の引数・仮引数がそれで良いのか確認してください。
a+i(a[i]も同じ) や a+j(a[j]も同じ) は考えているようなデータを指しているでしょうか。


文字列領域に文字列を展開して書き換えるタイプです。
moji 関数は strcmp と同じですので変更しています。

c

1#include <stdio.h> 2#include <string.h> 3 4#define STRMAX (9+1) //+1 は '\0' 分 5 6void sort(char a[][STRMAX], int n) { //文字列領域配列と, 配列の件数 7 for(int i=0; i<n; i++) { 8 for(int j=i+1; j<n; j++) { 9 if(strcmp(a[i], a[j]) > 0) { 10 char x[STRMAX]; 11 strcpy(x, a[i]); 12 strcpy(a[i], a[j]); 13 strcpy(a[j], x); 14 } 15 } 16 } 17} 18 19int main(void) { 20 char a[][STRMAX]={"one","two","three","four","five","six","seven","eight","nine","ten"}; 21 22 int n = sizeof(a) / sizeof(a[0]); //a の件数 23 24 sort(a, n); 25 26 for(int i=0; i<n; ) { 27 printf("%s", a[i++]); 28 printf("%s%s", i<n?",":"", i%3&&i<n?"":"\n"); 29 } 30 31 return 0; 32}

投稿2024/01/03 09:06

編集2024/01/03 13:00
jimbe

総合スコア13329

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

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

varmosy

2024/01/03 09:58

自分的には、a[i]とa[j]の順を入れ替えるために、strcpy「xにa[i]代入したあとにa[i]にa[j]を代入、その後a[j]にa[i]を代入されたxを代入する」というのを下記プログラムで実現したつもりです。 ``` char x[10]; strcpy(*x, *a[i]); strcpy(*a[i], *a[j]); strcpy(*a[j], *x); ``` もし何か間違えいがあればご教授していただけると幸いです。
jimbe

2024/01/03 11:56 編集

思いこむとなかなか気付き難いのですが、 swap の引数は char *a となっています。これは文字列の先頭アドレスという意味です。 ですから a+i にしろ a[i] にしろ、*文字列の中の* 文字を指すアドレスもしくは文字そのものであって、main で宣言している a (文字列の配列) の要素は差していません。 まずは main で宣言している a を swap に正しく渡す( swap 関数内でも a[0] が "one" を指し a[1] が "two"を指すようになる)にはどう書くのかを調べてみては如何でしょう。
jimbe

2024/01/03 12:01

また、文字列リテラルは(一般的に?)書き換え不可能な所に保存されますので、 strcpy 等で上書きは出来ません。 a の宣言を変えて書き換え可能な状態にするか、 strcpy では無くポインタの入れ替えをする必要があります。 tatsu99 さんの回答コードがポインタの入れ替えですね。
varmosy

2024/01/04 01:14

回答ありがとうございます。なんとなく理解はできました。 少し確認なのですが、このコードを書き始めたとき、strcpy辺りを以下のように書いていました。 (昨日は少しテンパっていたので質問の欄に書くのを忘れていました。すいません...) ``` x = *a[i]; *a[i] = *a[j]; *a[j] = x; ``` これは、(例えば)*a[i]というのは、「アドレスに代入されたある文字(例えばone)を指しているだけなので、交換はできない」のであって、tatsu99 さんのような ``` x = a[i]; a[i] = a[j]; a[j] = x; ``` というのは、(例えば)a[i]は「アドレスそのものを示しているのでxを使って参照先のアドレスを交換している」という認識でよろしいでしょうか? 度々の質問でご迷惑おかけしますが、どうかよろしくお願いします。
jimbe

2024/01/04 03:52 編集

>*a[i]というのは、「アドレスに代入されたある文字(例えばone)を指している a[0] は "one" の先頭を指す(char*型の)アドレスですので、 *a[0] は(char型の) 'o' という文字になります(a[0][0] と同じ。アドレスでは無いので『指す』では無く『表す』ですかね)。 ですのでアドレス交換のつもりで char* x で交換しようとしても型も違いますし、勿論 char x では先頭の文字を交換するだけになります。 ということで >a[i]は「アドレスそのものを示しているのでxを使って参照先のアドレスを交換している」という認識 であっています。
varmosy

2024/01/04 04:10

ありがとうございます!とても理解できました。 何度も質問してご迷惑おかけいたしました。
guest

0

strcpy(x, a[i]);

strcpy という関数は、第一引数、第二引数、双方ポインタのはずですが、こいつはそうなっていません
ここらへんどうにかしましょう

# 他の行も同様

投稿2024/01/03 08:19

y_waiwai

総合スコア88163

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

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

varmosy

2024/01/03 09:53

回答ありがとうございます。 ``` char x[10]; strcpy(*x, *a[i]); strcpy(*a[i], *a[j]); strcpy(*a[j], *x); ``` y_waiwaiさんがおっしゃるとおりに上記のように双方をポインタにしたのですが、以下のようなエラーがでました。 ```error invalid type argument of unary ‘*’ (have ‘int’) invalid type argument of unary ‘*’ (have ‘int’) invalid type argument of unary ‘*’ (have ‘int’) passing argument 1 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion] ``` (各エラーは上から順に一個目のstrspyの第二引数、二個目の第一、二引数、一個目の第一引数に関する物です。) それぞれ全く意味がわかりません。もしよろしければご教授よろしくお願いします。
y_waiwai

2024/01/03 09:59

> strcpy(*x, *a[i]); これちがいます strcpy(x, &a[i]); とすべきです *という演算子は何をするものか、&という演算子は何をするこのか、を調べてみよう
varmosy

2024/01/04 01:30

回答ありがとうございます。下記URLを参考にしたのですが、*は「配列の中身」を、&は「配列のアドレス」を示している、という認識でよろしいでしょうか? https://qiita.com/pen2000/items/fc5b06795dce3e0f679c また、jimbe さんのほうのコメントでも先ほど同様の記述させていただいたのですが、strcpy関数で参照するアドレスを交換する、と言うのがここでの役割になるのでしょうか? あと、以下のように修正したところ、 ``` char x[10]; strcpy(x, &a[i]); strcpy(&a[i], &a[j]); strcpy(&a[j], x); ``` 警告文「passing argument 1 of ‘swap’ from incompatible pointer type [-Wincompatible-pointer-types]」(swap(&a[0] に関する物) とエラーコード「*** stack smashing detected ***: terminated」 が出ました。 こちらについてもよくわかっていないので、お時間あればご教授お願いします。
y_waiwai

2024/01/04 02:10

swap関数の第一引数がどーこーというメッセージです。 エラーが出たからと言ってそこで思考停止するんじゃなく、そのメッセージを読もう。 翻訳サイトもたくさんありますよ その言語をマスターしたいなら、自分ができることを全部やろう。
varmosy

2024/01/04 04:01

わかりました。ありがとうございます、もう少し自分で勉強してきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問