トップページ⇒tech
1001コメント308KB

C言語なら俺に聞け(入門篇) Part 4

■ このスレッドは過去ログ倉庫に格納されています
0001デフォルトの名無しさん2006/11/09(木) 00:31:01
C言語の入門者向け解説スレです。
・C++言語はスレ違いです。
・分からない事をなるべく詳しく書いて下さい。
・ソースコードを晒すと答えやすくなるかもしれません。
・質問者は最初にその質問をした時のレス番号を名前欄に書いて下さい。

前スレ
C言語なら俺に聞け(入門篇) Part 3
http://pc8.2ch.net/test/read.cgi/tech/1160682950/

過去スレ
Part 1 http://pc8.2ch.net/test/read.cgi/tech/1146700389/
Part 2 http://pc8.2ch.net/test/read.cgi/tech/1153818463/


関連スレ
くだすれC言語(初心者用)
http://pc8.2ch.net/test/read.cgi/tech/1153542424/

【ISO/ANSI/JIS】 C言語なら俺に聞け! Part 130
http://pc8.2ch.net/test/read.cgi/tech/1159613789/
0266デフォルトの名無しさん2006/11/14(火) 22:36:41
どうもです、mallocの時〜は、自動でキャストしてくれるんでしたっけ
じゃあ自分のレベルではまだ使うこともなさそうですね
0267デフォルトの名無しさん2006/11/14(火) 22:38:38
>>266
まま、そうおっしゃらずに。
実はいける口なんでしょ?
0268デフォルトの名無しさん2006/11/14(火) 22:40:31
typedef struct{
int length;
char data[1];
}string;

struct{
int length;
char data[buf_size];
}a;

のとき

(string)a

のようにキャストするのもテクニックとしては知っておいたほうがいいかも
02692592006/11/14(火) 23:01:41
せいぜい数十行のコード書いて試す、を繰り返してる程度ですから…
>>268
すみません、どのように使うんでしょうか?
0270デフォルトの名無しさん2006/11/14(火) 23:02:25
すいません、先ほども質問しましたが、画面から配列に16進数を8桁入力して10進数に変換する処理ですがstrtol関数を使って
16進以外が途中に入力されたらエラーを出力したいのですが、何か良い方法はありますか?
気になって眠れません。
0271デフォルトの名無しさん2006/11/14(火) 23:07:29
>>270
どこまで変換したかってポインタが設定されるから、それを見たら?
途中で止まってたらおかしい。
0272デフォルトの名無しさん2006/11/14(火) 23:08:03
>>270
>249
0273デフォルトの名無しさん2006/11/14(火) 23:19:07
>>271さん
第一引数は配列名で第三引数は基数、第二引数をみるのですか?
0274デフォルトの名無しさん2006/11/14(火) 23:21:09
>>273
そう。
0275デフォルトの名無しさん2006/11/14(火) 23:49:34
>>269
268ではないが。
C言語ではコンパイル時に配列のサイズが決まっている必要があるが、
サイズを動的に変えられる(かのように扱える)構造体を使うためのテクニック。

配列のサイズは固定なので、基本的に最大の要素数を格納できるような
型を用意しておく必要がある。これでは、要素数の少ないデータしか
格納しない場合に無駄が多い。
よって、ケースバイケースで配列の要素数の異なる型が使えると嬉しい。

以下のようにすれば任意の要素数の配列として動的に確保できる。
string *p;
int size = 30;
p = (string *)malloc(sizeof(string) + sizeof(char)*(size - 1);
p->length = size;

この構造体を操作するときは、配列部分のサイズが固定じゃないから、
lengthメンバのようにどこかで配列サイズを保持しておき、
その分だけをアクセスするようにすればいい。

void func(string *pstr)
{
 int i;
 for(i = 0 ; i < pstr->length ; i++) {
  printf("%c", toupper(pstr->data[i]);
 }
}

当然、構造体の最後のメンバにしか適用できない。
0276デフォルトの名無しさん2006/11/14(火) 23:55:26
>>275
仕様書に違反している事には変わりがないけどな。
使うときは自己責任でって奴だ。
C99ではchar data[]って書き方が正式に許されたが。
0277デフォルトの名無しさん2006/11/15(水) 00:33:05
sizeof(char) は常に 1 なんだけど・・・


ま、いっか。
0278デフォルトの名無しさん2006/11/15(水) 02:04:53
2次元配列の意味がわかりません、簡単に言うと
どういう事なのでしょうか?入門書の説明が難しくて
わかりません。
あと、コメントが文字列なので2次元配列は、
どうして使えないのでしょうか?
0279デフォルトの名無しさん2006/11/15(水) 02:39:53
>>278
例えば学校で40人のクラスが5クラスあったとする。
その場合
int data [5][40];
とかになる

>あと、コメントが文字列なので2次元配列は、
>どうして使えないのでしょうか?

これは言ってる意味がわからない
0280デフォルトの名無しさん2006/11/15(水) 02:59:43
>>278
もしかして二次元配列とポインタの関係がわからなくて悩んでいるのか?
最初はポインタ無視していいよ。>>279の通りでいい。

>コメントが

これは俺も不明な質問だが、文字列の二次元配列という意味なら、文字列
そのものが既にchar型の一次元配列なので、1+2=3次元配列が必要になる。

例えば

char [][2][10] = {{"orange", "apple"}, {"banana", "pine"}};

のような感じで。
02812782006/11/15(水) 03:07:40
>>279
わkりました!!

>>280->>279
>>コメント
入門書にも詳しく書かれていないので、
自分でもよくわかりません、すんまそ。

>>char [][2][10] = {{"orange", "apple"}, {"banana", "pine"}};

のような感じで。


難しいです・・・まだここまで習っていないので参考にさせて
戴きます、頭が混乱するといけないので。

ありがとうございました。
0282デフォルトの名無しさん2006/11/15(水) 03:51:46
#include <stdio.h>
#include <time.h>
#include <stdlib.h>

//すごろくマップの構造体
struct board{
int p;//進む数
int h;//休む回数
char comment[128];
};

int p_position = 1; //プレイヤーの現在位置
int max = 10; //マップの全駒数
void writeBoard(void);

0283デフォルトの名無しさん2006/11/15(水) 03:52:25
main(){
int player; //プレイヤーのサイコロの目

int add; //止まった駒の進む数を格納する
struct board sugoroku[] = {
{0,0,"スタート"},
{0,0,"2駒目"},
{0,0,"3駒目"},
{3,0,"4駒目。3つ進む"},
{-2,0,"5駒目。2つ戻る"},
{0,0,"6駒目"},
{1,0,"7駒目。1つ進む"},
{0,0,"8駒目"},
{0,0,"9駒目"},
{-4,0,"10駒目。4つ戻る"}
};

printf("【すごろく】\n");
srand(time(NULL));

for(;;){
//サイコロを振る
printf("\nプレイヤーの番です。サイコロを振る > ");
while(getchar() != '\n'){}
player = rand()%6 + 1;

0284デフォルトの名無しさん2006/11/15(水) 03:53:05
//位置決定&マップ移動
p_position += player;
printf("目:%d\n",player);
if(p_position > max){break;}

//追加移動
do{
add = sugoroku[p_position-1].p;
printf("%s\n",sugoroku[p_position-1].comment);
p_position += add;
}
while(add != 0);
if(p_position > max){break;}

//現在位置の表示
printf("現在位置%d / %d\n",p_position,max);
writeBoard();
}
printf("あがり\n");
return 0;
}


0285デフォルトの名無しさん2006/11/15(水) 03:54:41
//現在位置を表す関数
void writeBoard(void){
int i;
for(i = 0; i < max; i++){
if(i == p_position-1){
printf("プ");
}
else{printf("□");}
}
printf("\n");
}

これで、合っていますが疑問があります。

>>[p_position-1]

で、-1と言うのが疑問です。何から-1にしているのでしょうか?
0286デフォルトの名無しさん2006/11/15(水) 04:18:00
>>285
質問に愚直に答えるなら、
p_positionから-1にしている。

日本語が不自由な君に軽くエスパーを駆使すると
配列の添え字が0から始まるのに対し、
p_positionは1から始まっているから。
0287デフォルトの名無しさん2006/11/15(水) 05:09:17
>>286
謎がとけました、サンクスです
0288デフォルトの名無しさん2006/11/15(水) 06:14:44
>>236
ありがとうございます
02892592006/11/15(水) 07:16:45
>>275,276
あ、(string)aというのは本当にそのままキャストするってことではなくて
領域についてこういう風な考え方もできるから知っておくといいという意味でしたか
現場ならではって感じですね、ありがとうございました
0290デフォルトの名無しさん2006/11/15(水) 11:20:55
質問です。
printfの%sに対して数値の0を渡したら、
文字化けやエラーではなく「(null)」という文字列が表示されました。
0291printf2006/11/15(水) 11:22:45
>>290
だって0 == '\0'なんだもん
空の文字列だと思ったんだもん
でも、違うかなと思って気を利かせたんだもん
0292デフォルトの名無しさん2006/11/15(水) 11:43:05
>>291
%s
0293デフォルトの名無しさん2006/11/15(水) 11:58:59
おおっと! 意外なことで291の無知が発覚してしまいました!
0294デフォルトの名無しさん2006/11/15(水) 12:05:59
ハァ?
0 == "\0" は真だろ。
無知はお前の方だろww
0295デフォルトの名無しさん2006/11/15(水) 12:33:00
>>290
環境依存。
未定義の動作だから処理系によって動作は違がう。
その例は単なるフェイルプルーフだからその動作を期待してはいけない。
0296デフォルトの名無しさん2006/11/15(水) 12:56:19
0 == '\0' は真だが 0 != "\0" だろ
0297printf2006/11/15(水) 13:02:24
>>294
私のために争わないで!!
勘違いしただけなんだもん
0==NULLなんだもん
だけど、参照できなかったんだもん
0298デフォルトの名無しさん2006/11/15(水) 13:48:45
引数として受け取った文字列を逆順にした文字列に書き換える関数
を作りたいんですけど、どうすればいいですか?
自分は
char str[6];
int i;

for (i=0;i<6;i++)
{
str[i]="文字列"[i];
}
printf("%s\n",str);
return 0;
}
こういう奴をいじっていくつもりなんですけど。
0299デフォルトの名無しさん2006/11/15(水) 13:53:35
まず「逆順」の定義を。
0300デフォルトの名無しさん2006/11/15(水) 14:02:54
>>298
#include <string.h>
#include <stdlib.h>
char* reverse(char str[]) /* return NULL if error */
{ int i, len=strlen(str); char* buf;
if ((buf=(char*)calloc(sizeof(*buf), len)) == NULL) return NULL;
for (i=0; i<len; i++) buf[i]=str[i]; for (i=0; i<len; i++) str[i]=buf[len-1-i];
free(buf); return str; }
0301デフォルトの名無しさん2006/11/15(水) 14:07:18
>>299
unkoだったらoknuって出るようにします
>>300
すいません、まだポインタ習ってないです。
0302デフォルトの名無しさん2006/11/15(水) 14:08:01
>>301
予習になったね
0303デフォルトの名無しさん2006/11/15(水) 14:14:30
if(strcmp(str,"unko")==0)
printf("oknu");
03042982006/11/15(水) 14:16:45
わからないことの内容に含まれると思うので言い直します><
ポインタ無しで>>298を(逆順の定義は>>301)解決したいです
どなたかお願いします。
文字列の連結やらコピーをするくらいまではなんとかできます。
0305デフォルトの名無しさん2006/11/15(水) 14:23:38
>>304
てことは、>>298の "文字列" ってのが
"列字文" ってならなくてもいいんだな?
03062982006/11/15(水) 14:26:38
>>305
それは困ります><
できたらできたほうがいいです
03072982006/11/15(水) 14:32:49
>>306は自分じゃないです。

>>301は だったら って書いたので例えのことです。
これだったら>>1でいう詳しく書いたことにならないようなので、
言い直すと入力した文字の後から1つ1つ順番に出力したいです。
0308デフォルトの名無しさん2006/11/15(水) 14:35:40
だから多バイト文字を1文字として扱うか複数文字として扱うかを訊いてんの。
0309デフォルトの名無しさん2006/11/15(水) 14:41:15
漢字1文字にかかるデータ量 が Cのデータ上で1つになるとは限らない。
0310デフォルトの名無しさん2006/11/15(水) 14:46:54
CRLFの問題もあるけどね
03112982006/11/15(水) 14:48:15
>>309
すいません、それすら知りませんでした。
>>308
>>298は課題が出たからわからないので聞きにきたんですが、
問題の内容にすら書いていません。今までの課題の流れだと日本語を入力したことがないので
流れから判断して多バイト文字は無視でお願いします。
0312デフォルトの名無しさん2006/11/15(水) 14:52:55
>>300
しかし汚いコードでつね
0313デフォルトの名無しさん2006/11/15(水) 15:38:39
宿題スレでやれ
0314デフォルトの名無しさん2006/11/15(水) 15:44:12
char str[6];
int i,k=6;

for (i=0;i<6;i++)
{
str[i]="文字列"[k--];
}
printf("%s\n",str);
return 0;


はいはい俺天才
0315デフォルトの名無しさん2006/11/15(水) 15:45:40
>>314
つ\0
0316デフォルトの名無しさん2006/11/15(水) 15:48:26
str[5] = '\0';

え、、えへへ
0317デフォルトの名無しさん2006/11/15(水) 15:51:31
>>314
いや、大きさが足りない
(男の人に言ったらまずかった?)
0318デフォルトの名無しさん2006/11/15(水) 15:52:08
釣りは釣りスレでやれ。
0319デフォルトの名無しさん2006/11/15(水) 15:53:24
k-- → --k
0320デフォルトの名無しさん2006/11/15(水) 15:55:52
str[6] → str[7]
0321デフォルトの名無しさん2006/11/15(水) 16:30:37
勉強になりました
0322大学生2006/11/15(水) 22:26:24
「問題16」eの値を実数として計算し表示せよ。
「問題17」πの値を実数として計算し表示せよ。

「問題18」eの値を小数点以下60桁まで求めよ。
「問題19」πの値を小数点以下60桁まで求めよ。
この問題16.17.18、19のC言語プログラム(C++)でお願いします。
それと多倍長少数を利用して作ってください。
0323デフォルトの名無しさん2006/11/15(水) 22:28:34
>>322
C/C++の宿題を片付けます 76代目
http://pc8.2ch.net/test/read.cgi/tech/1162771475/
0324デフォルトの名無しさん2006/11/15(水) 23:49:40
C言語の入門サイトを見て回ってVC++ 2005 ExpressEditionをインストールしたのですが
いろんなところでとりあえずこれでやってみれと書いてある
Win32コンソールアプリケーションで作ると追加できるソースファイルが*.cppです
とりあえずHelloWorld!は出たんですが
*.cファイルが追加できるように設定しといた方がいいんでしょうか?
0325デフォルトの名無しさん2006/11/15(水) 23:57:59
別に cpp でいいんじゃない?
0326デフォルトの名無しさん2006/11/16(木) 00:15:23
ファイル名を指定する時に拡張子付きで入力しろ。
03273272006/11/16(木) 03:22:17
テキストファイルを読み込んで特定の箇所を上書きしたんですが、
その書き換えかたがわかりません。教えていただけませんでしょうか><;
以下のように記述していまして、c(文字型)の部分に整数を入れたいんです。

   while((c = fgetc(fp)) != EOF)
   {
      if(c == '特定の文字')
      {
         //ここがわかりません
      }
   }
0328デフォルトの名無しさん2006/11/16(木) 03:36:04
>>327
f = ftell();
fseek(fp, 0, SEEK_CUR);
fputc(c, fp);

つまり"r+"で開いたファイルは、fseek()すればそのすぐ次には書いてもよい。
一度でも書いたらまたfseek()もしくはrewind()しないと読めない。
0329デフォルトの名無しさん2006/11/16(木) 03:37:18
while((c = fgetc(fp)) != EOF)
{
if(c == '特定の文字')
{
c = 15; //任意の整数
}
}
0330デフォルトの名無しさん2006/11/16(木) 03:38:59
おっとっとftell()は不要でした
0331デフォルトの名無しさん2006/11/16(木) 03:45:48
>>328
おまえ日本語読めないのか?
>>327はそんなこと望んでないぞ。
>>329が正解だろ。
0332デフォルトの名無しさん2006/11/16(木) 03:54:54
”上書きしたんですが”を”上書きしたいんですが”とエスパー読みしてみた
03333272006/11/16(木) 05:13:55
>>328さん
>>329さん
>>331さん

ありがとうございました。助かります。
すいません打ち間違ってしまったようで、
332の方のエスパー読みが実はこちらの言いたかったことなんです。
とすると、328の方のおっしゃったfseekを使えばいいんですか?
とりあえず使い方を調べて試してみます。
03343272006/11/16(木) 05:30:56
続けて失礼します。
試しに大文字と小文字を置き換えてみようと思って下のように
記述したのですが、これだと実行時にエラーになってしました。
恐らくfseekの使い方が誤っていると思うのですが、
どのように改善すればいいんですか? 質問ばかりで申し訳ないです。

  while((c = fgetc(fp)) != EOF)
  {
    if(c=='S')
    {
      fseek(fp,0,SEEK_CUR) ;
      fprintf(fp, "s") ;
      fseek(fp,0,SEEK_CUR) ;
    }
  }
0335デフォルトの名無しさん2006/11/16(木) 05:37:35
>>334
多分ファイルのオープンモードが"r"になってるんだと思うよ。
"r+"にしてね。
03363272006/11/16(木) 05:43:09
>>335さん

ありがとうございます。
モードは大丈夫みたいです。
他の文法や使い方は問題ないですか??
0337デフォルトの名無しさん2006/11/16(木) 05:43:43
あ、それともう一つ
fgetc(fp)で既にファイルポインタが一つ進んでいるので

fseek(fp, -1, SEEK_CUR);
fputc('s', fp);
fseek(fp, 0, SEEK_CUR);

だな
0338デフォルトの名無しさん2006/11/16(木) 05:45:44
それからcはintで宣言してる?charじゃだめだよ
EOFを表せないから
0339デフォルトの名無しさん2006/11/16(木) 05:47:49
眠気に耐えられないので寝まつ
後は他の人に任せた
03403272006/11/16(木) 05:53:27
>>335さん

ありがとうございます。
確認したんですがモードは大丈夫なようです。
前後は以下のようになってますが、
関数の使い方や文法に間違いはありませんか??
もしかすると最初に見つけたSで
処理を繰り返してしまっているかもしれません。


  fp = fopen("MMMMM.txt", "r+") ;

while((c = fgetc(fp)) != EOF)
{
if(c=='S')
{
fseek(fp,0,SEEK_CUR) ;
fprintf(fp, "s") ;
fseek(fp,0,SEEK_CUR) ;
}
}

fclose(fp) ;
03413272006/11/16(木) 06:00:43
>>339さん

ありがとうございました。
337を参考に変えてみたんですが、それでも変わりませんでした・・・。
改行したくないのでfprintfを使ってるのが問題なのかもしれません。

cは整数以外も読み込むのでcharでないとエラーになってしまうと
思います・・・。

遅くまでありがとうございました。頑張ってみます。
0342デフォルトの名無しさん2006/11/16(木) 09:09:46
>>341
fgetc()の戻り値はcharで表せないEOFも返す必要から、intになっている。
従って、cはintであることが望ましい。
#つーか、charで受けるのは間違い。

それと、最初のfseek()は1バイト戻せと既に指摘されているのだがそっちは無視か?
0343デフォルトの名無しさん2006/11/16(木) 13:18:35
>>342が無視された件・・・
0344デフォルトの名無しさん2006/11/16(木) 13:32:42
無知な奴ほど素直じゃないのさ
03453272006/11/16(木) 13:49:39
>>342さん

ありがとうございます。

fseekの-1は参考にさせてもらいました。
書き込みのタイミングがかぶってしまったようです。

おっしゃるとおりcharが落とし穴だったようで、
intにしたらうまくできました!
文字はcharというド素人の固定概念が間違ってました・・・><;

これを多少応用したものを作らなければならないので、
まだ安心はできませんが、なんとかなりそうです。
助かりました。ありがとうございましたm(__)m
0346デフォルトの名無しさん2006/11/16(木) 14:25:08
サーバに単純な数値だけのデータを送りたいのですが
どのようにすればよいのでしょうか?
windowsのマシンでCを使い
linuxのサーバにデータを送るという感じです
0347デフォルトの名無しさん2006/11/16(木) 14:35:59
>>346
サーバとクライアント用の二つのプログラムを用意する
(来週につづく...)
0348デフォルトの名無しさん2006/11/16(木) 14:38:13
>>346
そのサーバって何?http? ftp? samba?
そのプロトコルに従って通信してください。
03493462006/11/16(木) 14:38:53
ちなみにサーバ用はPHPを使うのですが出来ますか?
0350デフォルトの名無しさん2006/11/16(木) 14:45:09
メールで送ったらいいんじゃね?
0351デフォルトの名無しさん2006/11/16(木) 14:49:21
>>349
PHPってことはHTTPだろ。Winsockでも使ってやれ。
03523462006/11/16(木) 14:54:09
>>351
そうですねhttpです
クライアント用のほうは事情があって
Cで書かなきゃならないので・・・
Winesockですか調べてみます
これはCの中でできるんですよね?
0353デフォルトの名無しさん2006/11/16(木) 14:57:33
>>352
VC++, gcc, bccなどWin32APIが呼べる環境ならできる。
これ以上の話はCとは関係ないのでスレ違い。
0354デフォルトの名無しさん2006/11/16(木) 16:22:03
inetd使えば?
0355デフォルトの名無しさん2006/11/16(木) 18:33:09
おまいらに全てを捧げたくなる位惚れちゃってます。
0356デフォルトの名無しさん2006/11/16(木) 19:14:08
>>355
おまえのものはおれのもの
0357デフォルトの名無しさん2006/11/16(木) 20:04:59
>>356
よお、じゃいあん
0358デフォルトの名無しさん2006/11/16(木) 20:51:49
>>357
悪いけど、今日は歌いたい気分じゃない・・・
0359デフォルトの名無しさん2006/11/16(木) 21:17:08
fgets + sscanf でなく、scanf を使ってしまっても
構わないようなケースにはどのようなのがあるでしょうか。
0360デフォルトの名無しさん2006/11/16(木) 21:22:40
ちょっと実験するためだけのような使い捨てのコードなら。
0361わからないので教えてください2006/11/16(木) 21:46:32
すみません、この問題のプログラムはどう作ればよいのかがわからないので
ぜひ、よろしくお願いします・・・

問題
配列su(要素数:12)に任意の数値をランダムに初期値設定し、逐次決定法によって
整列(昇順)させ、結果を表示させるプログラムを作成してください。
0362デフォルトの名無しさん2006/11/16(木) 21:54:26
何とか法とか何とか論を皆が知ってると思うなよ
0363デフォルトの名無しさん2006/11/16(木) 22:03:07
どうみても宿題ですありが(r
0364デフォルトの名無しさん2006/11/16(木) 22:05:56
逐次決定法って何だよ。バブルソートか?単純選択法か?
0365デフォルトの名無しさん2006/11/16(木) 23:08:41
任意の数値をランダムに初期値設定って何?ランダム値を初期値にするってこと?
逐次決定法が何か知らんが昇順ソートでおk?
0366デフォルトの名無しさん2006/11/16(木) 23:19:29
C++やP2P技術に卓越したプログラマの方々
宜しければ一度で良いので拝見して頂きたいです
当企画の成立には貴方の力が必要です

次世代コミュニティ製作 C++,mod_perl,P2Pが使えるコーダ、グラフィッカ募集中
http://pc8.2ch.net/test/read.cgi/tech/1163349367/
■ このスレッドは過去ログ倉庫に格納されています