ページ 1 / 1
配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 10:36
by mokopoko
2度目の投稿になります。どうぞよろしくお願いします。前回も配列がらみでしたが、今回も配列についてです。(前回はご助言通りに作り直して、うまくいきました。ありがとうございました)
コード:
↓main関数内で宣言
(*str3)[80];
int b = 0;
int z =10;
for(;b < z; b++, z--){
swap(str3[b],str3[b + z - 1]); エラー→2番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
→1番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
}
-----------------main関数はここまで
下が私が作成したswap関数です。
void swap(char (*x)[80], char (*y)[80]){
char (*temp)[80];
int i = 0;
temp = x;
while(*x[i])
{
(*temp)[i] = (*x)[i];←ここでエラー*temp)は初期化されずに使用されるかもしれません。
(*y)[i] = (*x)[i];
(*x)[i] = (*temp)[i];
i++;
}
}
2次元配列の勉強を兼ねて、
一行の英文内にあるすべての英単語を並べ替えていくプログラムを作っています。
質問は2つです。
①swap関数の引数として、7行目の、(str3
,str3[b + z - 1])は適切なのでしょうか。それからこのエラーの意味はどういうことなんでしょうか?
②swap関数内のエラーの理由は何でしょうか?
恐縮ですがよろしくお願いします。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 11:16
by box
できましたら、エラーが出ているソースコードを全部見せていただけないでしょうか。
こちらで動作確認するために、今提示されているmain関数(の一部)を
勝手に作り替えてしまうと、お手元にあるはずのソースコードと中身が異なってしまうおそれがあり、
正確な意思の疎通ができなくなることを懸念しています。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 11:45
by mokopoko
ご返信ありがとうございます。了解しました。次が私の書いたコードです。
エラー部分に注釈を入れておきます。
コード:
#include <stdio.h>
#include <stdlib.h>
# define _SPACE 0x20
void swap(char (*x)[80], char (*y)[80]);
void swap(char (*x)[80], char (*y)[80]){ //expected char (*x)[80] but argument is 'char'
char (*temp)[80];
temp = x;
int i = 0;
while(*x[i])
{
(*temp)[i] = (*x)[i];//(*temp)は初期化されずに使用されるかもしれません。
(*y)[i] = (*x)[i];
(*x)[i] = (*temp)[i];
i++;
}
}
int main(int argc, char * argv[]){
int j, h, k, z, b;
char str[80], (*str3)[80];
j = 0;
h = 0;
k = 0;
z = 0;
b = 0;
gets(str);//str3[] = str;
for (; str[h];h++) {
str3[k][j] = str[h];//str3はこの関数内初期化されずに使用されるかもしれません。
if (str[h] != _SPACE) {
printf("%c", str3[k][j]);
j++;
}
else {
str3[k][j+1] = '\0';
printf("\n");
j = 0;
k++;
}
}
str[h+1] = '\0';
for(; z <= h; z++){
int a = (int) ( z + 1 * rand() / (RAND_MAX + 1.0));
for (; b <= a; b++){
swap(str3[b][80],str3[b + z - 1][80]);//2番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
//1番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
}
}
for(;str3[k];k++){
for(;str3[k][h];h++){
if(str3[k][h]){
printf("%c", str3[k][h]);
}
else{
printf(" ");
}
}
}
return(0);
}
恐縮ですがよろしくお願いします。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 12:27
by non
char str[80], (*str3)[80];
この(*str3)[80] はどういう意味で使ってますか?
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 12:34
by mokopoko
ご返信ありがとうございます。
(*str3)[80]はstr3[][80]という意味だと考えております・・・
str3[k][j] = str[h]がおかしいのでしょうか?
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 13:45
by non
(*str3)[80]はポインタですから、どこか実際のメモリを指すようにしないと(初期化しないと)使えません。
普通に str3[10][80] (単語数を10個以内と仮定している場合)にしたらどうですか?
これが、学校の課題なら、課題を正確に記述してください。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月11日(月) 14:59
by naohiro19
コード:
main.cpp(46): error C2664: 'swap' : 1 番目の引数を 'char' から 'char (*)[80]' に変換できません。(新しい機能 ; ヘルプを参照)
1> 整数型からポインター型への変換には reinterpret_cast、C スタイル キャストまたは関数スタイル キャストが必要です。
このエラーが出るってことは間違いがあります。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月12日(火) 22:54
by tamaneko
初心者で色々分らないので聞きます
void swap(char (*x)[80], char (*y)[80]) についてですけど
これは何をする関数ですか?
引数のchar (*x)[80]って何を受け取るんですか? 2次元配列の実体でしょうか?
char (*temp)[80];
は何をしているんですか? 2次元配列の実体を作成?
temp = x;
tempが2次元配列の実体なら、x配列全部をtemp配列にコピーしているんですか?
*x
は引数で受け取った物の何を見ているんですか?
(*temp) = (*x);
(*temp)、(*x)で何をしているんですか?
(*temp)、(*x)で何をしているんですか?
temp = x;でx配列全部をtemp配列にコピーしているのに更に何をコピーしているんですか?
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月13日(水) 00:32
by box
mokopoko さんが書きました:
2次元配列の勉強を兼ねて、
いわゆる「2次元配列(配列の要素が配列である)」と、
「配列へのポインター」との区別が正確に付いていないように見えます。
コード:
char (*s)[80];
char t[100][80]; // 100は適当な数値
sとt両者の概念は、全く異なります。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月14日(木) 13:03
by ookami
こんにちは、ookamiです。
勘違いならすみませんが、単に文字列をswapしたいだけなら
コード:
void swap(char *x,char *y) {
char tmp[80]; // 十分な長さであること
strcpy(tmp,x);
strcpy(x,y);
strcpy(y,tmp);
}
でいいのでは?strcpyを使わないとか、なにかシバりがあるなら別ですが...
--追記
あぁポインタ入れ替えるだけでいいんだわ^^; 上記のコードはあまり参考にしなくてよいです。残しておきますけどもw
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月14日(木) 23:52
by かずま
mokopoko さんが書きました:
①swap関数の引数として、7行目の、(str3,str3[b + z - 1])は適切なのでしょうか。それからこのエラーの意味はどういうことなんでしょうか?
不適切です。
void swap(char (*x)[80], char (*y)[80]) ですから、x はポインタです。
(char [80]) 全体を指すポインタです。
main() 内で、char (*str3)[80]; ですから、str3 はポインタです。
(char [80]) 全体を指すポインタです。
str3 は、str3 が指している (char [80]) が複数並んでいるものの b番目のものです。
str3 の型は、(char [80]) ですが、これは (char *) に変換されます。
ポインタには違いありませんが、char へのポインタです。
(char [80]) へのポインタである x を (char *) である str3 で初期化することは不適切です。
mokopoko さんが書きました:コード:
swap(str3[b],str3[b + z - 1]); エラー→2番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
→1番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
そこでそんなエラーメッセージが出ることはあり得ません。
mokopoko さんが書きました:コード:
swap(str3[b][80],str3[b + z - 1][80]);//2番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
//1番目のswapに引数を渡すときに整数からキャストなしにポインタを作成しています。
こちらのエラーメッセージは正しいものです。
str3
の型が (char [80]) ですから、str3[80] の型は char です。
char は式の中で参照するとき、自動的に int に格上げされますから、
整数からキャストなしに 「(char [80]) へのポインタ」を作成しようとしています。
mokopoko さんが書きました:
②swap関数内のエラーの理由は何でしょうか?
temp は x で初期化されていますから、Microsoft Visual C++ コンパイラ、Borland C++ コンパイラ、GNU C++ コンパイラ では、そのようなエラーは出ません。
使っているコンパイラは何ですか?
mokopoko さんが書きました:コード:
int a = (int) ( z + 1 * rand() / (RAND_MAX + 1.0));
1 * rand() は rand() と同じ。
rand() / (RAND_MAX + 1.0) の値は 1.0 未満ですから、z に加えても、
int へのキャストで無くなってしまいます。したがって、これは
int a = z;
と同じです。
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月15日(金) 02:32
by かずま
mokopoko さんが書きました:
2次元配列の勉強を兼ねて、
一行の英文内にあるすべての英単語を並べ替えていくプログラムを作っています。
2次元配列の勉強にはならないプログラムです。
コード:
#include <stdio.h>
void swap(char **x, char **y) { char *t = *x; *x = *y; *y = t; }
int main(void)
{
char str[80], *word[40]; int i = 0, n = 0;
gets(str);
while (str[i]) {
word[n++] = &str[i];
while (str[i] && str[i] != ' ') i++;
if (str[i]) str[i++] = 0;
}
// for (i = 0; i < n; i++) puts(word[i]);
for (i = 0; i < n; i++) swap(&word[i], &word[rand() % n]);
for (i = 0; i < n; i++) printf("%s ", word[i]);
putchar('\n');
return 0;
}
Re: 配列を引数にもつ関数が動きません。
Posted: 2012年6月16日(土) 15:32
by かずま
tamaneko さんが書きました:
初心者で色々分らないので聞きます
最初の質問者とは違う人ですね。
tamaneko さんが書きました:
void swap(char (*x)[80], char (*y)[80]) についてですけど
これは何をする関数ですか?
引数のchar (*x)[80]って何を受け取るんですか? 2次元配列の実体でしょうか?
x はポインタで、呼び出し元にある 2次元配列の実体を指します。
2次元配列の実体を参照できる 2つの引数があって、swap という名前だから、
2つの 2次元配列の中身を交換するのかと思いきや、やりたいことは
1つの 2次元配列の中の 2つの行を交換したいだけのようです。
1つの行には 1つの単語が入っています。
その行は char の 1次元配列ですから、void swap(char *x, char *y) とするだけで十分です。
おまけに、temp の使い方や *x
という書き方を間違っているので、思ったようには動きません。
tamaneko さんが書きました:
char (*temp)[80];
は何をしているんですか? 2次元配列の実体を作成?
2次元配列へのポインタを宣言しているだけです。2次元配列の実体はありません。
tamaneko さんが書きました:
temp = x;
tempが2次元配列の実体なら、x配列全部をtemp配列にコピーしているんですか?
temp も x もポインタで、呼び出し元の 2次元配列の実体を指すだけで、配列全体のコピーはしません。
temp が x と同じ 2次元配列を指すようになるだけです。
ただし、そのプログラムでは、呼び出し元に 2次元配列の実体はありません。
tamaneko さんが書きました:
*x
は引数で受け取った物の何を見ているんですか?
x が 2次元配列の i 番目の行ですから、*x はその行の先頭の char 1文字です。
i が 1つずつ増えていくと、次の行(次の単語)の先頭の 1文字を参照します。
(*x) と書くべきところを間違って *x と書いています。
tamaneko さんが書きました:
(*temp) = (*x);
(*temp)、(*x)で何をしているんですか?
(*temp)、(*x)で何をしているんですか?
(*x) は 2次元配列の先頭の行ですから、(*x)[i] はその行内の i番目の文字です。
(*temp) や (*temp)[i] も同様ですが、今、temp と x は同じ 2次元配列を指しているので
この代入は無意味です。
tamaneko さんが書きました:
temp = x;でx配列全部をtemp配列にコピーしているのに更に何をコピーしているんですか?
temp = x; では配列全体のコピーはされていません。