C言語なら俺に聞け( ..
[2ch|▼Menu]
21:デフォルトの名無しさん
08/03/25 19:56:30
ポインタのポインタについて困ってます。
メインから構造体のポインタを渡し、構造体に内容を追加して、
追加後のポインタを返してもらいたいのですがうまくいきません。
void add_line(int num,struct lines **current){
char input_line[512];struct lines *buffer_pre,*buffer_fow;int length,i; struct lines *p;
p=*current;
do{
gets(input_line);
if((*input_line != '.')&&(*(input_line+1) != '\0')){
buffer_pre=p;
//構造体の前後のポインタ取得の処理は省きました
//構造体とテキストの領域をMALLOCで確保します
if (buffer_pre == 0){       //リストの連結
p->next=0;
p->prev=0;
}else if((buffer_pre != 0)&&(buffer_fow == 0)){
p->next=0;
p->prev=buffer_pre;
buffer_pre->next=p;
else if((buffer_pre != 0)&&(buffer_fow != 0)){
p->next=buffer_fow;
p->prev=buffer_pre;
buffer_pre->next=p;
buffer_fow->prev=p;
};
};
}while((*input_line != '.')&&(*(input_line+1) != '\0'));
*current=p;
return;}
何がまずいのでしょうか?

22:デフォルトの名無しさん
08/03/25 20:06:25
教えて

char MyStrMid( char buff[], const char string[], int pos, int len )
{
 char *dest = buff;
 
 if ( pos < strlen(string) ){
  for ( string += pos ; len > 0 ; len-- ){
   if ( *string == '\0' ){
    break;
   }
   *dest++ = *string++;
  }
 }
 *dest = '\0';
 return( buff );
}

っていうプログラムを教えてGooで見つけました。
MIDができる関数なんだけど、
const char stringで宣言しているのに
*string++ しているので、stringの中身を変更しないで
この関数を使いたいんだけど、どうしたらいいんでしょう?

23:デフォルトの名無しさん
08/03/25 20:19:09
>>22
なぜ中身が変更されていると思ったのでしょう?

24:デフォルトの名無しさん
08/03/25 20:21:14
*dest++ = *string++;

*dest = *string;
dest++;
string++;
とほぼ同じ動作。
string の中身は変わらないっつーか、
変わってたら string は const だからエラー出る。

25:デフォルトの名無しさん
08/03/25 20:26:39
>>23,>>24
ありがとうございます。

>>23
なぜ中身が変更されているかは、*string++をしているからですよね

>>24
*string++で中身が変わってしまい、constでエラーが出ることは理解できるのですが、
応用として、変数を増やすことなく、この関数を使用できないでしょうか?

26:デフォルトの名無しさん
08/03/25 20:27:26
>>25
中身は変更されないので確認してねって事です

27:デフォルトの名無しさん
08/03/25 20:28:25
>>21
・ gets より fgets を使う。
・ input_line[0] == '\0' の時に最初の条件式ではマズい。
 そもそも意図通りの条件なのかも怪しい。
・ *(input_line+1) とか読みにくい。input_line[1] にしてくれ。
・ 省略するより、省略なしでアップローダーにうpしてくれ。
・ 同じ条件式を二度も書くのは無駄。
 無限ループにして if(! (条件)) { break; } した方がすっきりする。
・ 双方向リストはリングリストの形で実装すると、途中の if-else チェインが不要になる。
・ add_line は本当に1行追加の関数にして、
 add_input_lines っての作ってそこで add_line を逐次呼ぶ実装にした方がすっきりする。

変数の説明も無いし読みづらいしで
とりあえずすっきりさせてからということで。

28:デフォルトの名無しさん
08/03/25 20:29:24
>>25
>*string++で中身が変わってしまい、constでエラーが出ることは理解できるのですが、
だから変わらないっつーの。

29:デフォルトの名無しさん
08/03/25 20:29:31
>>21
ポインタを返してもらうならvoid *add_line()だろ。

30:デフォルトの名無しさん
08/03/25 20:54:59
>>26
中身は変わらないです。ごめんなさい。

>>28
「中身を変えようとして」エラーが出ているって認識で大丈夫ですかね?

すいません。もうちょっとがんばってみます。
ありがとう。

31:21
08/03/25 20:55:53
>>27
とりあえず、ソースをあげてみました。
URLリンク(www.uploda.org)
まだご指摘いただいた点直してない部分がありますが、一度見ていただけないでしょうか?
入力を終了する条件式は「.」のみが入力された場合です。
構造体の中身は
struct lines{
char *word;
struct lines *next;
struct lines *prev;
};
で、テキストエディタのようなものですので、リングにしてしまうと一行目が分からなくなるかなと?
と思っったのでリング型にはしませんでした。
変数は
char input_line[512];//文字を一時的に入れる配列
struct lines *buffer_pre,*buffer_fow;//挿入部分の前後のポインタを入れておくところ
int length,i;//文字列の長さを入れるlinegth、ループ様のi
struct lines *p;/mainから受け取った構造体のアドレスを保存するとところ
です。
>>29
えっと、名前の部分は戻り値ありの場合の指定ではないのですか??

32:デフォルトの名無しさん
08/03/25 21:20:17
>>31
>構造体に内容を追加して、追加後のポインタを返してもらいたい
と書いてあるけど違うの?内容を追加するだけならvoidのままでいいけど。

33:デフォルトの名無しさん
08/03/25 21:32:17
>>32
あ、もちろん構造体に中身を追加して、その追加した部分のポインタを返してもらいたいです。
それをポインタのポインタを渡して、それに追加した部分のポインタの内容を代入して返すようにしたいです。

mainに現在の構造体のポインタの位置を表すポインタ「now」有。
nowのアドレスをポインタのポインタたるcurrentに入れてadd_lineに渡す。
add_lineの中でcurrentにそこで関数内でつくった構造体のポインタPを代入する。

呼び出す時は何行目に行を追加するかを表すnumと構造体のポインタのポインタ二つを渡して
add_line(num,now);//nowはmain中の構造体のアドレス
のようにしようと思っていました。
now=add_line(num,now);という様に関数の戻り値を使う場合のみ型を指定するのではないのでしょうか?

34:デフォルトの名無しさん
08/03/25 21:45:52
[a][b][c][d][e] ってあった場合、num を 1 にした際には
<X> [a][b][c][d][e] ここに追加されて欲しいのか
[a] <X> [b][c][d][e] ここに追加されて欲しいのか
どっちなんだろう。

前者はこのリストの仕様だと面倒臭いよね。
特にリストの末尾に追加する際。

35:デフォルトの名無しさん
08/03/25 21:50:18
空のリストに追加する際は常にこの面倒くさい状態になるから・・・

36:21
08/03/25 22:24:05
>>34
学校の課題で、特定の行の後に追加する関数と、前に追加する関数が求められていて、
この関数は後に追加のほうなので、[a] <X> [b][c][d][e]に追加したいです。
もし0行目の後に追加(一番最初に追加)の場合は特定の行の前に文章を追加する関数に
移るようにします。
>>35
リングにしてしまうと最初の行が分からなくなってしまう気がします。
その場合は構造体の中に行番号を入れるしか思いつきませんでした。
ただX行からY行をZ行の後に移動などの処理の時に困る気がするのですが・・・

37:デフォルトの名無しさん
08/03/25 22:29:48
>>36
ダミーのノードを1つ用意する。

ダミーノードの次のノードが最初のノードで、
ダミーノードの前のノードが最後のノード。

最初のノードの前のノードがダミーノードで、
最後のノードの次のノードがダミーノード。

ダミーノードがあると、
「〜の次に追加」 という関数にダミーノードを渡すと先頭に追加になり、
「〜の前に追加」 という関数にダミーノードを渡すと末尾に追加になる。

そして、一切の NULL チェックが不要になる(assert くらいはした方がいいと思うけど)。

38:21
08/03/25 22:42:57
>>37
おぉ!なるほど!
確かに大量にあるNULLチェックが必要なくなります!
ダミーノードはmainのコマンドの入力→該当関数の動作というループが始まる前に
mainの中で用意しておけばいいんですよね?
その場合ダミーノードかどうかの判別は保持しておいたアドレスを使って
最初に戻るのなら
while(c = ダミーのアドレス){
    c=c->prev;};
とすれば出来ますよね?

あと、構造体のポインタへのポインタの使い方は

39:デフォルトの名無しさん
08/03/25 22:50:37
引数に直接返すより戻り値から返した方が
自由度が高くてよい。

40:21
08/03/25 23:07:17
>39
えと、X行からN行を入力テキストに置き換える、という関数の中で
X行とN行のアドレス、それを取り出すときに使ったX行からN行の
実際の行数のintを返す関数を用意したいと思っているのですが、
やはりそれは戻り値を一つに出来るよう更に小型化するしかないのでしょうか?

41:デフォルトの名無しさん
08/03/25 23:27:37
複数の値を返さないといけない場合は、
値を返す用の引数を別個に用意するのが普通かな。

今の add_line の仕様だと、
struct lines * 型の戻り値を current に渡す、とかできないっしょ。

まあとりあえず、
>>21 のポインタへのポインタの使い方自体は間違ってないので、
変なのだとしたら他の所がおかしいんだと思うよ。

42:21
08/03/25 23:38:34
>>41
色々教えていただいてありがとうございます!

とりあえず、
struct lines *add_line(int num,struct lines *current){
この様に戻り値を使って値を返すことにしました!

ただ、やはりポインタのポインタが疑問でして、
自分が書いたとおりであってるとすると、その前は
mainでポインタのポインタたる**pに*p=0、
構造体のアドレスはNULLということをしてるだけなのですが
この書き方がマズイのでしょうか?

あと、もう一つなのですが・・・値を返す用のの引数とは
関数の動作に必要な引数の他に、値をもらう用のポインタ変数を
用意するということでしょうか??

43:デフォルトの名無しさん
08/03/25 23:45:41
ああ、もうソースが消えてるわ。
main 側はまだ見てなかったわ。

main 側では struct lines *p; として
add_line(num, &p); という形にすることになるはず。

>あと、もう一つなのですが・・・値を返す用のの引数とは
>関数の動作に必要な引数の他に、値をもらう用のポインタ変数を
>用意するということでしょうか??
そうなる。

44:21
08/03/26 00:31:31
>>43
スイマセン、ソースは自動で消えてしまったみたいです・・・

main側では**pの様なものは宣言せずに、渡す時に&を使うのですね。

勉強になりました!ありがとうございました!

45:デフォルトの名無しさん
08/03/26 07:47:20
struct Lines; /* typedefのための前方宣言 */
typedef struct Lines Lines;
typedef Lines * LinesPtr;
struct Lines { char *word; LinesPtr next, prev; };
LinePtr linesGetLast(LinePtr p) { if(p){ while(p && p->next) p = p->next; } return p; }
LinePtr linesGetFirst(LinePtr p) { if(p){ while(p && p->prev) p = p->prev; } return p; }
LinesPtr add_line(int num, LinesPtr current)
{
char input_line[512];
LinesPtr temp_lines = NULL;
while(fgets(input_line, sizeof(input_line), stdin) != NULL){
if(input_line[0] == '.' || input_line[0] == '\0') break;
temp_lines = malloc(sizeof(Lines)); /* エラーチェック省略 */
temp_lines->prev = NULL; temp_lines->next = NULL;
temp_lines->word = malloc(sizeof(char) * strlen(input_line) + 1);
strcpy(temp_lines->word, input_line);
if(current != NULL){
temp_lines->next = current->next; current->next = temp_lines;
temp_lines->prev = current;
if(temp_lines->next != NULL) temp_lines->next->prev = temp_lines;
}
current = temp_lines;
}
return temp_lines; /* 割り込み終了位置を返す */
}

46:45
08/03/26 07:49:39
改行大杉長過ぎで二度怒られたわw >>45の続き、ってかコメント。

numの使い道が分からんかったのでやや違うかもしれんけど、
やりたいのは大体こんな感じ?(関数名はinsertとかの方が適切っぽい)
ソース見てないから断言できんけど、呼び出し元が渡すのはポインタでよさげ。
割り込み開始位置は呼び出し元の current->next を見る。
NULLで呼び出してる時は linesGetFirst(p) で。

ちなみに自分なら1つの独立した構造体を作る関数を別に作って
土台のリストと新しく作ったのを追加用関数に渡す形にするかな。
その方がどこに加えたいかの指定が楽になるし、
構造体に手を加えても作成用関数だけいじれば大体事足りるようになるので。

『ポインタのポインタ』はポインタをtypedefして独立した1つの型として見ると理解し易いかも。


47:デフォルトの名無しさん
08/03/26 15:22:26
>>22
気になったので書き直してみた (処理速度的には不利だけど)
char MyStrMid( char buff[], const char string[], int pos, int len )
{
for(;pos>0 && *string;pos--,string++);
sprintf(buff, "%.*s", len, string);
return buff;
}

48:デフォルトの名無しさん
08/03/26 18:58:32
〜なら真を返すと、どういう意味かわかりません

49:デフォルトの名無しさん
08/03/26 19:38:27
0以外の値。
例えば常に真を返す関数tがあったとしたら、次のコードは常にtを出力する側へ分岐する。
if (t())
{
putchar('t');
}
else
{
putchar('f');
}

50:デフォルトの名無しさん
08/03/26 19:39:51
>>48
man コマンドとかマニュアル、ヘルプの読み方が分からないって事か?

51:デフォルトの名無しさん
08/03/26 21:35:01
真=はい
偽=いいえ

で覚えとけ

52:デフォルトの名無しさん
08/03/27 22:18:49
FIRフィルタをCで書くとどんなになりますかね?

53:デフォルトの名無しさん
08/03/27 22:22:24
>>52
for(i=0;i<srcsize;i++){
dest[i]=0;
for(j=0;j<fltsize && i+j<srcsize;j++){
dest[i]+=src[i+j]*flt[j];
}
}

54:デフォルトの名無しさん
08/03/27 22:30:18
>>52
コンボリューション演算をすればよろしい

55:デフォルトの名無しさん
08/03/27 22:39:26
>>52
// srcsize == fltsize == destsize (==2^x)
src_freq=fft(src, srcsize);
flt_freq=fft(flt, fltsize);
for(i=0;i<srcsize;i++) dest_freq[i]=src_freq[i]*flt_freq[i];
dest=fft(dest_freq, destsize);

56:デフォルトの名無しさん
08/03/27 22:42:53
入力した日は何曜日かを出したいのですが
どうしても曜日がずれて一日ずれて表示されてしまいます
どごが悪いのでしょう?
#include<stdio.h>

int main() {
int iyear,imonths,iday;
int sum,i;
int m_array[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
char*cweek[7] = {"日","月","火","水","木","金","土"};
sum =0;
printf ("input (e.g. ****/**/**)\n>>");
scanf ("%d/%d/%d",&iyear,&imonths,&iday);
/*閏年の判定*/
for(i=1;i<year;i++){
if((year%4==0)&&((year%100!=0))||(year%400==0)){
sum++;
i++;
}
year--;
/*前月までの日数*/
for (i =0; i < imonths-1; i++) {
sum += m_array[i];
}
year++;
sum=sum+day;
//曜日の出力
printf("%s曜日",cweek[sum%7]);
return 0;
}
}


57:デフォルトの名無しさん
08/03/27 22:48:13
>>56
それではコンパイルすらできませんが

58:デフォルトの名無しさん
08/03/27 23:45:44
読んでないけど演算結果が0==月曜日とかってことないよね?

59:デフォルトの名無しさん
08/03/27 23:50:23
ヒント:グレゴリオ暦で遡って行った場合、西暦1年1月1日は月曜日

60:デフォルトの名無しさん
08/03/28 00:45:01
>>57
#include<stdio.h>
int main() {
int year,months,day;
int sum,i;
int m_array[12] = {31,28,31,30,31,30,31,31,30,31,30,31};
char*cweek[7] = {"日","月","火","水","木","金","土"};
sum =0;
printf ("input (e.g. ****/**/**)\n>>");
scanf ("%d/%d/%d",&year,&months,&day);

/*閏年の判定*/
for(i=1;i<year;i++){
if((year%4==0)&&((year%100!=0))||(year%400==0)){
sum++;
i++;
}
year--;

/*前月までの日数*/
for (i =0; i < months-1; i++) {
sum += m_array[i];
}

year++;

sum=sum+day;
//曜日の出力
printf("%s曜日",cweek[sum%7]);
return 0;
}
}

61:デフォルトの名無しさん
08/03/28 00:52:32
>>60
あなたが手を加える前のプログラムに戻してみては?

62:デフォルトの名無しさん
08/03/28 01:08:24
>>61
それだとできないことはないんですけど
別で作ってみたいなと思いまして・・・・

63:デフォルトの名無しさん
08/03/28 01:11:37
>>62
まずはインデントをしっかりそろえてみ?
forがおかしなネストをしててループ変数iが破壊されてるぞ

64:デフォルトの名無しさん
08/03/28 01:23:55
ファイルを読み込んで、構造体に入れて、それを表示させたいのですが何故か上手くいきません。
どこを直したらいいのでしょうか?
struct lines{
char *word;
struct lines *next;
struct lines *prev;
};
void main(){
char input_line[512],file_name[100];
struct lines *buffer_pre,*buffer_fow;
int length,i;
struct lines *p;
FILE *fp;
printf("*");
gets(file_name);


65:デフォルトの名無しさん
08/03/28 01:24:48
if((FILE *)NULL==(fp=fopen(file_name,"r"))){
printf("can not open\n");
};
i=0;
while(i=0){
fgets(input_line,513,fp);
  if(feof(fp)){
break;
    };
  if(ferror(fp)){
break;
};
//前後のポインタの取得
buffer_pre=p;
if (buffer_pre == 0){
buffer_fow=0;
}else{
buffer_fow=0;
}
//領域の確保
p=(struct lines *)malloc(sizeof(struct lines));
length=strlen(input_line);
p->word=(char*)malloc(length+1);
strcpy(p->word,input_line);



66:デフォルトの名無しさん
08/03/28 01:25:19
//リストの連結
if (buffer_pre == 0){
p->next=0;
p->prev=0;
}else if((buffer_pre != 0)&&(buffer_fow == 0)){
p->next=0;
p->prev=buffer_pre;
buffer_pre->next=p;
};
};
fclose(fp);
       while(p->prev != 0){
p=p->prev;
};
while(p != 0){
printf("%s\n",p->word);
p=p->next;
};
return;}

67:デフォルトの名無しさん
08/03/28 01:59:43
何がどうなってどう上手くいかないのかくらい書いてくれ。
>fgets(input_line,513,fp);
なんで513なんだ?

68:デフォルトの名無しさん
08/03/28 02:02:39
>while(i=0){
代入でいいのか?

>};
関係ないけど、なんですべてのスコープの後ろにセミコロンが?

なんか他にもつっこみたくなる要素が満載だぞw

69:64
08/03/28 02:19:59
>>68
すいません、そこは「==」でした・・・
あとスコープの外側にはセミコロンはいらないんですね・・・

>>67
説明が足りなくて申し訳ございません・・・。

まず513ですが、一行の行数の最大値が512なので、NULL文字の分も入れて513にしてみました

問題点なのですが、「//リストの連結」という部分のすぐ下で読み込んだ構造体をつないでいきます。
その段階では構造体の現在のアドレスと現在の構造体の->prevのアドレスは正しく表示されるのですが、
ループを抜けた後、構造体のアドレスを一番最初に戻すために、       
while(p->prev != 0){
p=p->prev;
}
を実行しています。その途中でprevのアドレスがずれて、セグメント例外になってしまいます。


70:デフォルトの名無しさん
08/03/28 04:18:05
>buffer_pre=p;

71:デフォルトの名無しさん
08/03/28 04:21:55
>>69
ならinput_line[512]も513にしたら?

72:64
08/03/28 07:31:11
>>71
あ、確かに。ありがとうございます。

>>70
pは関数が始まる時に0に初期化していて、
一列終わるごとにそのその構造体のアドレスがbufferf_preに
入るので間違っては居ない気がするのですが・・・


73:デフォルトの名無しさん
08/03/28 07:40:31
>>63
見直してみましたがよくわかりません
どこのfor文なのでしょうか?


74:デフォルトの名無しさん
08/03/28 07:44:24
>>72
>70

75:デフォルトの名無しさん
08/03/28 07:46:28
>>73
あんたの節穴で見直すのではなく、インデントを揃えてみろ。
できればエディタで。

76:デフォルトの名無しさん
08/03/28 07:48:08
>>73
/*閏年の判定*/
for(i = 1; i < year; i++){

/*前月までの日数*/
for (i =0; i < months-1; i++) {

どっちもi使ってるだろ?後者で上書きされてるだろう?


77:デフォルトの名無しさん
08/03/28 10:01:09
>>72
>70で問題点が理解できないようじゃ、プログラムに向いてないだろ。
無意味で無駄な部分多すぎるし。

78:デフォルトの名無しさん
08/03/28 14:01:52
p == NULLで初期化してwhile(i==0)にしたら動いたけど

79:デフォルトの名無しさん
08/03/28 20:20:18
>>72,73
『間違っては居ない気がする』とかいってないで
デバッガでブレークポイント置いてステップ実行するなり
assert()とかprintf()とか入れて変数の状態を確認しようよ
見直すって眺めるのと違うんだけど

80:デフォルトの名無しさん
08/03/28 22:44:23
#include <stdio.h>
void main()
{
int count;

for (count = 0; count < 5; count++) {
printf( "countは今%dです\n", count );
}
if(count==4){printf("正解です%dです\n",count);}
else{printf("残念");}

}

VC++2008でデバックしましたがなぜかこれが"残念"のほうが出力されます。
countは4だと思うんですがなにか間違えてますか?

81:デフォルトの名無しさん
08/03/28 22:45:30
>>80
count の値を表示してみればいい

82:デフォルトの名無しさん
08/03/28 22:54:43
>>81
forで5のprintfが実行されなくてもカウントは5になってるんですね
ありがとうございました

83:デフォルトの名無しさん
08/03/28 23:06:04
count++のあとcount < 5を判断する

84:デフォルトの名無しさん
08/03/28 23:18:13
>>82
つーか、5になったからループを抜けたんだよ。

85:デフォルトの名無しさん
08/03/29 11:28:37
#include<stdio.h>
main(){
char a[80],b[32];
int ca(char *,char [],int *),i,n;
while(1){
printf("文字\n");
scanf("%s",a);
n=0;
ca(a,b,&n);
for(i=0;i<n;i++){
printf("%c ",b[i]);
}
printf("\n\n");
}
}
int ca(char *s,char t[],int *n){

int i;
while(*s){
for(i=0;i<*n;i++) if(*s==t[i]) break;
if(i>=*n){
t[i]=*s;
(*n)++;
}
s++;
}
}

nがどのようになっているのか理解不能です。
*n と nがどうなっているのか教えてください。

86:デフォルトの名無しさん
08/03/29 11:46:37
どこが分からないのか言ってくれないとどうしようもない

1行ずつ追っていって、結果を紙に書いていくんだ
そうすればどこの行が分からないのかが分かる


87:デフォルトの名無しさん
08/03/29 11:48:09
*nとn[0]が同じだってことは判っているのだろうか。

88:85
08/03/29 11:55:52
8行目でn=0となっていて、20行目の*nの値はどうなるのでしょうか?


89:デフォルトの名無しさん
08/03/29 11:58:13
最初は0だよもちろん。

90:デフォルトの名無しさん
08/03/29 11:59:10
>>88
1になったらそれ以降増えない
whileにprint分入れて*nを出力したりとかして自力で知らべられるようにした方がいいよ

デバッガというものもあるし

91:デフォルトの名無しさん
08/03/29 12:01:51
増えるだろw
aに入った文字列を一文字づつ取り出してbに格納、
既出の文字は無視、格納した文字の総数をnに入れてく関数だよ。

92:デフォルトの名無しさん
08/03/29 12:06:21
>>91
馬鹿?

93:85
08/03/29 12:11:59
ごめんなさい。理解できないみたいです。
まずfor(i=0;i<*n;i++)の*nは最初は0なんですよね?
だと繰り返さないような気がしてなりません。

94:デフォルトの名無しさん
08/03/29 12:13:29
バカは>>90だろw

95:デフォルトの名無しさん
08/03/29 12:14:47
>>93
そうです繰り返しません
そして次のif文はi が0 , *nが0なので真となり中身が実行されますが
その結果*n が1となりwhile(*s)の次の回では実行されません
そのままなにもしないままwhile文が回り続けて終了です

96:デフォルトの名無しさん
08/03/29 12:16:18
>>90=95?
でたらめ書く前に実行してみたら?

97:デフォルトの名無しさん
08/03/29 12:19:18
>>96
お前がやれよアホ

98:デフォルトの名無しさん
08/03/29 12:30:41
a[]は入力した文字列、b[]はその文字列から重複した文字を抜いた文字列、
nはb[]の文字数になる。

99:85
08/03/29 12:36:35
aaaと入力したときを考えると
for文はi=0,*n=0だから繰り返さないで次のif文にいき
実行されてt[0]にaが代入され、*nの中身がプラス1されて*n=1となって、2番目のaに移る。

for文はi=0,*n=1だから一回繰り返されてif文で*s=t[0]ならbreakで打ち切りされて
次のif文でi=0,*n=1だからだめで3番目のaに移る。

見たいな感じでいいんですか?

100:デフォルトの名無しさん
08/03/29 12:41:02
そうだね。

101:85
08/03/29 12:43:11
すみません。ちょっとだけ理解できたようです。
みなさんありがとうございます。

102:デフォルトの名無しさん
08/03/29 12:43:54
要するに、
forは文字(*s)がtの中で既出かどうか探している。
次のifは、既出でない場合に条件が成立し、
tに文字(*s)を追加。
*nはtに格納した文字数だよ。

103:デフォルトの名無しさん
08/03/29 12:46:57
春になると90みたいなキチガイが湧くんだなw

104:デフォルトの名無しさん
08/03/29 12:49:40
>>102
nは文字数なんですね。
あとnは*nとする必要もないですよね?

105:デフォルトの名無しさん
08/03/29 12:51:20
main関数内のnとca関数内の*nは別物。
できれば違う変数名にした方が混同しなくていいと思うけど。

106:デフォルトの名無しさん
08/03/29 12:58:19
>>105
main関数内のfor文のnはca関数内の*nの値が入るのですよね。

107:デフォルトの名無しさん
08/03/29 12:58:45
>>104
>あとnは*nとする必要もないですよね?
必要ないと思うならそう書き換えてコンパイルしてごらん。

108:デフォルトの名無しさん
08/03/29 12:59:41
yes

109:デフォルトの名無しさん
08/03/29 13:05:09
>>107
文字がでなくなった。
なんかもう頭がこんがらがってきた。
ポインタって難しいんですね・

110:デフォルトの名無しさん
08/03/29 13:15:01
>>109
難しいといわれてるが一度理解するとそうでもなく、
プログラミングする上でこの上なく便利な機能だ。
めげずに落ち着いて頑張るといいよ

111:デフォルトの名無しさん
08/03/29 13:19:28
プログラム書くときはなんか本とか見ながら書いてますか?

112:デフォルトの名無しさん
08/03/29 13:19:39
この場合型が違うのに変数名を同じnにしてるのが混乱のもとじゃね?

113:デフォルトの名無しさん
08/03/29 13:22:01
>>109
caの中のnは、mainの中のnを指して(ポイントして)いる。
caの中の*nという表記は、mainの中のnを読んだり書き換えたりしている。

114:デフォルトの名無しさん
08/03/29 13:22:53
無理に引数で渡さなくても
int ca(char *s, char t[])
{
int i, n = 0;
while(*s) {
for(i=0; i<n; i++) if(*s==t[i]) break;
if(i==n) {
t[i] = *s;
n++;
}
s++;
}
return n;
}
にしてmain内でn = ca(a, b)ってすればまだ分かりやすいのに。

115:デフォルトの名無しさん
08/03/29 13:31:58
>>111
日本語書くときはなんか辞書とか見ながら書いてますか?
という質問と同じに聞こえる。

116:デフォルトの名無しさん
08/03/29 13:56:40
>>113
なるほど、わかりました。
なんとなくですが>>

>>114
たしかにそのほうがわかりやすそうです。

117:デフォルトの名無しさん
08/03/29 15:08:02
>>115
言い得て妙 だな

118:デフォルトの名無しさん
08/03/29 15:19:06
2chの書き込みくらいでは辞書なんて引きません。
でも、ちょっとまじめな文章を書くときには、国語辞典を引きます。

119:デフォルトの名無しさん
08/03/29 15:35:24
日本語に例えるのは上手くないような・・
英語だとしっくりくる

120:デフォルトの名無しさん
08/03/29 17:17:22
正解はこれな
日本語しかわからないあなたがフランス語を書くときに辞書無しで書けますか?

121:デフォルトの名無しさん
08/03/29 19:29:42
>>111
時々リファレンスみる程度。初心者でなければコピペとかないから。
そう意味できいてるなら真面目に勉強してください。

122:デフォルトの名無しさん
08/03/29 22:47:33
ポインタについて質問です
整数型とint ポイント型の違いがわかりづらいのですが
ポイント型はアドレスを格納できて整数型はアドレスを出力するだけですか?

123:デフォルトの名無しさん
08/03/29 22:57:35
>>118
そんなもんだろ。だいたいは頭に入ってるから空で書ける。
細かい仕様(引数の順番とか関数の戻り値とか)が必要になったらネットなり書籍なりで確認して書く。

124:デフォルトの名無しさん
08/03/29 23:09:18
>>122
変数からアドレスを求めるのはアドレス演算子&。
整数型はアドレスを出力するだけというのはなんか変だ。


125:デフォルトの名無しさん
08/03/29 23:09:35
>>122
int*はint型の変数のアドレスを格納する変数

int x=50;
int *xp = &x;

この時、printf("%d",*xp) と printf("%d",x) は50を表示し、
printf("%p",xp) と printf("%p",&x) はxのアドレスを表示する

126:デフォルトの名無しさん
08/03/29 23:46:54
>>124
アドレスを変数に格納せず&で出力ができるという感じですか?
>>125
printf("%d",*xp)が50を表示するというのが難しく感じるところです
*xpという箱は整数型で宣言されそこには&xというアドレスが代入される
となるとprintf("%d",*xp)ではアドレスが出力されると考えてしまいます。

127:デフォルトの名無しさん
08/03/29 23:50:00
変数はあくまでxp

128:デフォルトの名無しさん
08/03/29 23:59:29
なんとなくわかりました
*xpはアドレスを格納する変数
だからprintf("%d",xp)だとそのままアドレスを出力
printf("%d",*xp)はわざわざ*をつけてるから逆にデータのほうを表示する

129:デフォルトの名無しさん
08/03/30 00:26:12
2行目の「*xp」は「xp」ね。それ以外は大体その認識でOK

130:デフォルトの名無しさん
08/03/30 09:26:32
そうかな、なんか危ういきがす

131:デフォルトの名無しさん
08/03/30 10:37:35
int *xp = &x;
これと
printf("%d", *xp);
これの「*」の意味が違うことに>>128は多分気付いていない。
同じ文字を逆の意味の2つの演算子に使うという、C言語の糞仕様のおかげだな。
「ポインタ宣言子」と「間接参照演算子」の違いね。

そもそも初心者に教えるときに、
int *xp = &x;
では混乱が起きる。

int *xp;
xp = &x;
上のように書いてやらないと
int *xp = &x;
  ↑
意味的にはここで切れていることに、初心者は気がつかない。

132:デフォルトの名無しさん
08/03/30 11:40:43
>>131
「int* xp」と書いた方がわかりやすいかな。
「int*」が変数の型(intへのポインタ型)、xpが変数名。

133:デフォルトの名無しさん
08/03/30 11:56:25
int* xp, x

134:デフォルトの名無しさん
08/03/30 12:05:48
>>133
C言語のダメなところだよね。「int *」が型なのに、宣言は個別に「*」を付けなきゃいけないなんて。
複数の変数を1行で宣言できることがそんなに重要なんだろうか。

135:デフォルトの名無しさん
08/03/30 12:17:50
int i, *p, (*f)();

136:122
08/03/30 15:44:32
printf("%d",*xp)というのは間接参照演算子というポインタ変数の機能なんですね
まだそれは勉強してませんでしたがおかげでわかりました

ポインタの練習用プログラムを見てどう出力されるかはわかるようになってきました
ありがとうございました

137:デフォルトの名無しさん
08/03/30 19:28:11
typedef struct
{
int Number;
}DATA , *PDATA;
int main()
{
DATA data;
PDATA pdata;
data.Number = 10;
pdata = &data;
printf("%d",pdata->Numer
}
*PDATAはポインタ型を作っているという解釈でよろしいんでしょうか?
ちなみに
typedef char *PCHAR;を書くと
sizeof(char) == 1
sizeof(PCHAR) == 4
になってました。


138:デフォルトの名無しさん
08/03/30 19:38:53
>>137
そのとおり。
DATA*とPDATAが同じ。
char*とPCHARが同じ。

139:137
08/03/30 20:06:28
>>138
ありがとうございます。

140:デフォルトの名無しさん
08/03/31 04:46:11
戻り値の最上位ビットが 1 のときはAを、0 のときはBを示す関数、REABがあるのですが、
if(REAB() < 0) //Aの時
となるのは何故なんですか?

141:デフォルトの名無しさん
08/03/31 04:48:39
2の補数の場合はそうなる
あとはぐぐればすぐ分かる

142:デフォルトの名無しさん
08/03/31 04:53:28
最上位ビットが1なら負の数になるんですね
ありがとうございました

143:デフォルトの名無しさん
08/03/31 12:22:07
>>142
Cの規格上は必ずしもそうなると言う保証はない点に注意。
そもそも、「最上位ビット」に意味があるのだからきちんと最上位ビットをチェックするロジックを書くべき。
# 処理速度などを睨んで改変するのは二の次三の次。

144:デフォルトの名無しさん
08/03/31 19:31:48
>>143
符号つきで最上位ビットが 1 の場合は負ってのは規格で保証されてなかったっけ?
その制限の中でどういう負数表現をとるかは環境依存だけど。

145:デフォルトの名無しさん
08/04/01 02:35:47
>>144
REAB()の戻り値がsignedなんて、どこにも書かれていませんよ。


146:デフォルトの名無しさん
08/04/01 03:03:58
例えば極端な話、戻り値がcharだったらコンパイルオプションでsignedかunsignedか切り換えられるかも知れない。
だとすると、signedのときは正しく動いてunsignedのときは(エラーも起こさず)正しく動かないことになる。
>143ではないが、先ずはそれに頼らないコードを書いた方がいいとは思う。

147:デフォルトの名無しさん
08/04/01 07:32:19
やらない方がいい事は確かだけど、
結局規格ではどうなってるんだ?

148:デフォルトの名無しさん
08/04/01 08:40:35
>>144
規格で決まってるのは、符号ビットが1ビットあることだけじゃなかったっけ?

149:デフォルトの名無しさん
08/04/01 12:29:56
FIRフィルタのプログラムで浮動小数点演算を使わずに実装
したいのですが、普通係数hnは浮動小数点ですよね。
入力のadは24ビットで係数hnを32768倍して固定小数点にして
最後に32768で割ろうとしたのですが、hn[k] * xn[k]の部分で
オーバーフローの可能性がでてきます。
回避するよいやり方はないでしょうか?

#define ORDER_2 50
static double xn[ORDER+1];
long firFilter(long ad)
{
long yn, acc;
int k;

xn[0] = ad;

acc = 0.0;
for (k = 0; k <= ORDER; k++) /* multiply and accumulate */
acc = acc + hn[k] * xn[k];
yn = acc;
for (k = ORDER; k > 0; k--) /* shift input samples */
xn[k] = xn[k-1];
return yn; /* output */
}

150:デフォルトの名無しさん
08/04/01 12:34:30
>>149
コンパイラによるけど long long を使うとかは?

151:デフォルトの名無しさん
08/04/01 12:55:46
・32768倍をやめて1024倍とか256倍とかで妥協する
・long long intを使う
・素直にfloatを使う

例えばx86でSSE2が使えるなら、巧く書けばベクタ化できるから下手すりゃ整数で小細工するより速いよ。

152:デフォルトの名無しさん
08/04/01 13:53:13
dest.txtの内容
[abcdefgabcdefg]
HANDLE hFile;
BOOL bVal;
DWORD numOFRead;

hFile = CreateFile("dest.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,0,0);
DWORD dwSize = GetFileSize(hFile,NULL);
char *file_buffer = (char *)calloc(dwSize+1,sizeof(char));
if(file_buffer == NULL){
return -1;
}

bVal = ReadFile(hFile,file_buffer,dwSize,&numOFRead,0);
if(bVal == 0){
return -1;
}
CloseHandle(hFile);
dest.txtの中のfgという文字列をajkoに置き換えてファイル生成したいんですが、
どうすれば出来ますか?

153:デフォルトの名無しさん
08/04/01 14:25:42
system("sed -e 's/fg/ajko/g' dest.txt > foo")

154:デフォルトの名無しさん
08/04/01 14:40:13
apple
test
hello

と言うテキストを
String[ ][ ]

の様な2次元配列で読み込みたい場合、
Stringの確保はどのようにすればよいのでしょうか?

155:デフォルトの名無しさん
08/04/01 14:57:03
Stringって何よ?
ここはCのスレだけど、C++かC#かJavaか何かと間違ってやしませんか?

156:デフォルトの名無しさん
08/04/01 15:13:53
char String[][]の積もりだろ。

>>154
文字列長に制限があってよければ、例えば
char String[][10] = {"apple", "test", "hello", };

可変長にしたいとか、そもそも文字列も可変個数だと言うのなら、ポインタのポインタを使うことになる。
まぁ、入門サイトでも探してくれ。それで判らなければ出直してくれて構わんから。

157:デフォルトの名無しさん
08/04/01 15:23:36
>>155
済みませんでした。

>>156
ありがとうございました。

158:デフォルトの名無しさん
08/04/01 15:45:25
>>153
それは何ですか?

159:デフォルトの名無しさん
08/04/01 19:53:37
>>153について誰か教えて下さい。

160:デフォルトの名無しさん
08/04/01 20:12:44
Stringは型の名前にあるからねえ
俺は文字列変数名にstrやsを使う

>>159
sedプログラムに3つの引数-eと's/fg/ajko/g'とdest.txt を渡して呼び出す
sedプログラムが標準出力したメッセージはfooというファイルに書き込む
かな?
sedの質問があれば正規表現スレでどうぞ

161:デフォルトの名無しさん
08/04/01 20:45:25
すみません。
私Windowsです。

162:デフォルトの名無しさん
08/04/01 21:00:44
私はIRIXです

163:デフォルトの名無しさん
08/04/01 21:12:58
Windows でも Cygwin とかある

164:デフォルトの名無しさん
08/04/01 21:15:01
これを愛用している
URLリンク(www.vector.co.jp)

スレチだが

165:デフォルトの名無しさん
08/04/02 18:36:45
曖昧な質問で悪いのですが、

picをはんだして、モーターとリモコンに繋げなければなりません。

そういった用途のc言語プログラムというのはどこで拾えばよいのでしょうか?

166:デフォルトの名無しさん
08/04/02 19:40:13
宿題なら先生、仕事なら先輩。

167:デフォルトの名無しさん
08/04/02 20:52:03
>165
自分の文章を読み直してみろ
その文章で何を言ってるか理解できるか?



168:デフォルトの名無しさん
08/04/02 20:55:38
>>167
きっとロボット制御して半田付けするってことだ
で、ロボット制御するためのc言語プログラムというのを探している


169:デフォルトの名無しさん
08/04/02 20:57:00
>>165
導線と半田を用意して、こてで溶着すればいいんじゃない?

170:デフォルトの名無しさん
08/04/02 21:05:38
位置独立コードの事かと思ったよ。

171:デフォルトの名無しさん
08/04/02 23:09:20
Cである一定のstate数ループさせる方法ってあるんけ?


172:デフォルトの名無しさん
08/04/03 00:20:25
state数って何よ、asm("NOP") * nってこと?

173:fxで裁判中。教えて
08/04/03 08:28:12
外国為替証拠金取引会社のアトランティックトレードと裁判になりました。

裁判の内容をここに記してみました
システム障害等でくわしいかた、是非とも情報をお待ちしております。よろしくお願いします。
URLリンク(members3.jcom.home.ne.jp)


174:デフォルトの名無しさん
08/04/03 10:49:25
なかなかの魚拓が取れたみたいなので、ここに置いておきますね。
ZDNet Japan builder「C/C++のポインタの機能--参照渡しののような処理」
URLリンク(s03.megalodon.jp)

オリジナルは
URLリンク(builder.japan.zdnet.com)


175:デフォルトの名無しさん
08/04/03 11:20:59
すげえバカだw
そういやこの筆者と似たようなことぬかしてたヤツが宿題スレでボコボコにされてたな。

176:デフォルトの名無しさん
08/04/03 15:25:56
あちこち同じリンク張るな。いい加減うっとおしい。

177:デフォルトの名無しさん
08/04/03 17:55:05
全く無知な人間が
C言語をマスターするにはどれくらいの時間がかかりますか?

178:デフォルトの名無しさん
08/04/03 17:58:15
>>177
物覚えの良い人ならそれだけ早いだろうし
やる気によっても左右される
マスターがどれくらいの事を言ってるのかもわからない

179:デフォルトの名無しさん
08/04/03 18:10:47
僕もマスターしたという基準がよく分からないのですが
C言語の試験とか資格ってのはあるんですか?

180:デフォルトの名無しさん
08/04/03 18:19:43
聞いたことないし、あったとしても役立たないものであることは確かだな。
著名なプログラマが資格を持っているなんて話、聞いたことがない。

181:デフォルトの名無しさん
08/04/03 20:58:04
最低限の足切くらいはできるんじゃないか?
Fizz-Buzz みたいにw

使えないやつが暗記してくるのは見破れないけど
暗記すらできないやつなら落とすことができる
使えるやつは暗記する必要もない、と

182:デフォルトの名無しさん
08/04/03 21:02:56
そのレベルのcの資格なら存在しているな

183:デフォルトの名無しさん
08/04/03 22:36:16
>>177
参考書と問題集何冊か買って受験勉強並みに真剣に勉強すれば3ヶ月くらいで
1000行程度のフリーソフトが作れるくらいにはなる。マスターとは程遠いけどね…


184:デフォルトの名無しさん
08/04/03 23:50:20
うちは1プロジェクト数万行レベルの組み込みCなんだが、全く無知の人間がきたとして
作業要員に換算できるレベルに1〜3か月ってとこかな?
PCに慣れているかどうかでかなり変わるとは思うが。

185:デフォルトの名無しさん
08/04/04 17:44:31
コンパイラの使い方がわかりません。
例えばtest.cppをVC++でコンパイルするとして
cl.exe D:/test.cpp
と実行してもコンパイルは出来るのですが、
どこにプログラムが作られているのかわかりません。
プログラムの保存先はどのように指定すればよいのでしょうか?

186:デフォルトの名無しさん
08/04/04 17:55:02
cl.exe /help
と実行すれば、指定できるオプションの一覧が出る

187:デフォルトの名無しさん
08/04/04 19:21:06
>>185
カレントディレクトリに実行ファイルができているんじゃないかな。


188:デフォルトの名無しさん
08/04/04 22:45:35
#include <stdio.h>
int main(void)
{
char str[2];
scanf("%s",str);
printf("%c %c\n",str[0],str[1]);
return 0;
}

これをVC++で実行しました。
EOSを考慮して01という2桁の入力をすると結果は0 1と正常な結果なんですが
なぜかデバックエラーがでてしまいます。
なにが問題なんでしょうか

189:デフォルトの名無しさん
08/04/04 22:48:49
char str[3];

190:デフォルトの名無しさん
08/04/04 22:49:34
>>188
\0 が入る余地がない

191:188
08/04/04 22:57:33
0から始まるから[0]と[1]に文字が入って[2]に\0が入るんじゃないんですか?

192:デフォルトの名無しさん
08/04/04 22:59:12
char str[2];
これだと二文字分の領域しか確保した事にならない

[0] = '0';
[1] = '1';
[2] = '\0';

の3Byte必要

193:デフォルトの名無しさん
08/04/04 23:00:24
>>191
str[2]を使うなら、char str[3];で定義しないとダメ。

194:デフォルトの名無しさん
08/04/04 23:03:32
添え字が0から始まる事と、配列の要素数は別

char str[0];

と書いても1文字分確保されるわけじゃない

195:188
08/04/04 23:13:06
今char str[0];で宣言してみたらサイズが0の宣言は無効とでました。
なるほど、てことはchar str[1];だと1文字が入るサイズってなわけですね。
皆さまありがとうございました。

196:デフォルトの名無しさん
08/04/04 23:32:33
>.188
慣れてしまえば、なんでもないことなんだが。
Cの初心者が最初につまずく問題であることは確か。

1.文字列を格納する文字配列は、文字列の最後の\0分も含めて確保しなければならない。
2.配列を定義するときの添え字(char str[3]の3)は、配列要素の数であり、どこまで使うかではない。

197:デフォルトの名無しさん
08/04/04 23:34:24
追加
3.Cの配列の添え字は0オリジンである。

198:デフォルトの名無しさん
08/04/05 00:13:30
すみませんCの質問とは若干異なるかもしれませんが
「JmEditor2」を使用していて下パネルで
『cファイルをコンパイルして作ったexe』を実行したときに
[scanf]などの入力を必要とする操作部分が実行できません
解決策を知っている方がいればお願いします

コマンドプロンプトから同じexeファイルを実行したところ問題なく動きました

199:デフォルトの名無しさん
08/04/05 00:32:38
JmEditor2のヘルプには入力できるって書いてあるんですか?
それと若干じゃなくて大幅にスレ違いです。

200:デフォルトの名無しさん
08/04/05 02:37:46
いいえ、スレ違いではありません。鼬害です。

201:デフォルトの名無しさん
08/04/05 06:19:59
>>198
「ツール」メニューの「コマンド実行」を使う。

下パネルから実行したとき、子プロセスの標準出力がうまく表示されない。
プロセスが終了するまで、子プロセスの標準出力の内容が表示されないようになっている。

202:デフォルトの名無しさん
08/04/05 15:08:33
そして板違いの指摘の後にレスする馬鹿。

203:デフォルトの名無しさん
08/04/05 21:37:05
>>201
ありがとうございます。

>>他
すみませんね、住人さん。自治会お疲れ様です。

204:デフォルトの名無しさん
08/04/06 01:47:50
#include <stdio.h>

main()
{
char ss[80];

gets(ss);
puts(ss);
}

文字を80文字以上入力しても、全ての文字が表示されるんですか
何故80文字以上gets()で読み込んでputs()で表示する事ができるのでしょうか

205:デフォルトの名無しさん
08/04/06 01:51:04
ss のサイズが 80 までなんて gets は全く知らないから
メモリを破壊してどんどん文字を保存していってしまう。
非常に危険。
gets は使っちゃダメ。代わりに fgets を使うべし。


次ページ
最新レス表示
スレッドの検索
類似スレ一覧
話題のニュース
おまかせリスト
▼オプションを表示
暇つぶし2ch

5379日前に更新/199 KB
担当:undef