ページ 1 / 1
ファイル(初心者です)
Posted: 2008年12月04日(木) 14:32
by ざこ
今ファイルを一行ずつ読み込み、一行の最後尾まで移動して後ろから順に.があるまで取り出すプログラムを作成中なのですが
{
FILE *fp
char *str
char buf[1000]
if((fp=fopen("ファイル名","r"))!=NULL){
str=buf;
int len=strlen(str);
for(i=0,i<=len;i++){
str++;
}
while(isdigit(*str)){
for(i=0;i<len;i++){
str--;
}
printf("%d\n",str);
}
}
}
1234.321.151(実行前)
↓
151
123
4321(実行後)
という具合にしたいんですけど上記のプログラム全然違いますよね?
コメント付きで教えていただけるとうれしいです。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 14:36
by 御津凪
手書きですか?
ところどころ括弧がおかしいですが…。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 14:43
by ざこ
ファイル名のとこだけ手書きでした・・後コピー漏れが少しありました。変更しておきます。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 14:50
by バグ
ファイルをオープンしただけで、読み込み処理を行っていませんね。
ついでに、ファイルのクローズも忘れているようです。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 14:56
by 御津凪
コメント付けました。
(見やすいように字下げしておきます)
{ // int main() が無い
FILE *fp // ';' が無い
char *str // ';' が無い
char buf[1000] // ';' が無い
if((fp=fopen("ファイル名","r"))!=NULL){
// テキストを buf に読み込んでいない
str=buf;
int len=strlen(str);
/*
for(i=0,i<=len;i++){
str++;
}
*/
// 上の代わりにこうしたほうがラク。
str += len;
/* これは処理が色々おかしいので間違い。
while(isdigit(*str)){
for(i=0;i<len;i++){
str--;
}
printf("%d\n",str);
}
*/
// 代わりにこうすると良いかも。
--str;
while(buf <= str){
if(isdigit(*str)){
printf("%c",*str);
}
else if(*str == '.'){
printf("\n");
}
--str;
}
printf("\n");
}
// ファイルをクローズしていない
}
分からないところがあれば聞いてください。
(何が原因だったのかとかなんでこれで動くのかとか)
あ、動作チェックはしていませんのであしからず。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 15:28
by ざこ
ありがとうございます。では質問させていただきます。
for(i=0,i<=len;i++){
str++;
の代わりに
str += len;ですよね
for文の方は最後尾まで移動する。最初が1234.4567.328であれば8に。
str+=lenの方は実際にはstr=str+lenで
strには文字列が入っていてlenは数字でそれを足したらfor文の方といっしょになるというのが
いまいちよくわからないのです。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 15:57
by 御津凪
これは「ポインタ」が大きく絡むのですが、サンプルで簡単に説明します。
int main(){
char* buf = "sample text.";
char* str;
int i;
int len = strlen(buf);
printf("str++ を使った処理\n");
str = buf;
for(i=0;i<len;i++){
printf("%d文字目は'%c'\n",*str);
str++;
}
printf("str += 1 を使った処理\n");
str = buf;
for(i=0;i<len;i++){
printf("%d文字目は'%c'\n",*str);
str+=1;
}
printf("str を使った処理\n");
str = buf;
for(i=0;i<len;i++){
printf("%d文字目は'%c'\n",str);
}
printf("str = buf+i を使った処理\n");
str = buf;
for(i=0;i<len;i++){
str = buf+i;
printf("%d文字目は'%c'\n",*str);
}
return 0;
}
それぞれの処理は全て同じ結果になるはずです。
str 自体は文字列では無く、文字列への場所(ポインタ)を指しています。
なので、str = buf とした場合は文字列のコピーではなく str は buf を指すだけです。
ここで str += len (str = str + len) とした場合、文字列に len を足すのではなく、
str の指す場所を len 文字ずらすと言う処理になるのです。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 16:00
by ざこ
成る程、すごく参考になります
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 16:03
by 御津凪
あ、ミスしてました。
printf("%d文字目は'%c'\n",*str);
じゃ無くて
printf("%d文字目は'%c'\n",i,*str); // i を入れ忘れ
でした。
すみません。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 16:30
by ざこ
>str 自体は文字列では無く、文字列への場所(ポインタ)を指しています
質問するのも躊躇するぐらい簡単な質門なのですが本を見てもよくわからなかったので・・
*strがstrのポインタで場所を示す と思ってたんですが。
strと*strの違いがピンと来ないんです。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 16:41
by GPGA
>strと*strの違いがピンと来ないんです。
*strとstr[0]は同じ意味
*(str + 1)とstr[1]も同じ意味になります。
配列を先に勉強していると思うので
これでわかると思うのですが、いかがでしょうか?
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 16:47
by ざこ
成る程、変にとらえてました。*str=str[0]なのは勉強した覚えがあります。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:03
by バグ
ポインタは最初は理解しづらいですよね(^_^;)
私は、配列を本に例えて考えてみたら、パッと理解できました。
変数の名前(str) = 本のタイトル
配列の要素数(今回は1000) = ページ数(ただし、0ページから始まるとする)
今回は本を例えに使いますので、ポインタを栞(しおり)として考えます。
『str += len』というのは、strという本の最初のページからlenページ分進めた位置にはさんである栞だと思ってください。『*(str + len)』というのは、その栞が挟んであるページそのものだと思ってください。
栞の内容を書き換えても、本のページには変化ありませんよね?
ですから、ページの内容を書き換えたい場合には、栞の挟んであるページそのものを書き換えてやる必要がある…ということになります。
どうでしょう、かなり本題から話が逸れてしまいましたが、私はこういう風に考えてポインタを理解しましたんで、手助けになればいいかと思い、書き込みしてみました。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:16
by ざこ
{
FILE *fp;
char *str;
char buf[1000];
if((fp=fopen("ファイル名","r"))==NULL){
printf("fail open error");
return 0;
}
while(fgets(buf,1000,fp){
int len=strlen(str);
{
str+=len;
--str;
while(buf <= str){
if(isdigit(*str)){
printf("%c",*str);
}
else if(*str == '.'){
printf("\n");
}
--str;
}
printf("\n");
}
// ファイルをクローズしていない
}
一行ずつ読み込むというのが抜けたので修正しました。
while(fgets(buf,1000,fp){ の部分でfpから読んだ文字列1行をbufに入れる。
str=bufでstrはbufを指すという意味。
少し簡単にする為に最後尾から読むという作業は省きますが
デバッグで確認した所、bufに123.435.456という文字列が入っていました。上記のは一文字ずつ読んで表示しているのかな?
123
435
456
を保存する方法も知りたいです。
質問が曖昧ですが、123,435,456はbufに入っています。
では123と435と456を一旦保存しておくことはどうやったらできるのかということなんです。
すごく参考になります。
ポインタはまだ認識が甘い所がありますので。>バグさん
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:35
by GPGA
>では123と435と456を一旦保存しておくことはどうやったらできるのかということなんです。
保存というのは、プログラム内部で保存ですか?
それともファイルに保存ですか?
もし、ファイルに保存するのであれば、printfをfprintfに変更するだけで実現可能になります。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:37
by ざこ
プログラム内です。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:40
by 御津凪
ファイルから buf に読み込んだ後、 str = buf でポインタを代入していないので、
strが初期化されず、処理がおかしくなってしまいます。
バグさんの本で例えるなら、本に栞を挟んでいない状態です。
> デバッグで確認した所、bufに123.435.456という文字列が入っていました。
読み込み元のテキストにはその一行が入っていますか?
(最初の質問時のテキストと違うのですが。)
> 上記のは一文字ずつ読んで表示しているのかな?
実はその周りの処理で数値だけを反転して数値を行で区切って表示しています。
buf の最後から逆方向に1文字ずつ表示し、'.'が出たら改行しています。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:49
by GPGA
きちんとしたものを作るには、動的確保を行ったほうがいいのですが
やり方が難しいので、今回は固定配列でやります。
char save[10][100]; // 10行、1列100文字まで対応
という保存領域を作っておき、カウンタを2つ用意します。
int cnt1, cnt2;
これらのカウンタはsave配列のインデックスに使用します。
save[cnt1][cnt2];
そして
while(buf <= str){
の中で、数字が来たらsave[cnt1][cnt2]の中に数字を保存して、cnt2を+1する。
[.]が来たら、cnt1を+1し、cnt2を0にする。
こうすることで、saveの中に、データが保持されます。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 17:56
by ざこ
>最初の質問時のテキストと違うのですが
一行ずつ読み込むというのが抜けたので修正しましたと記載した通りです。
>>ファイルから buf に読み込んだ後、 str = buf でポインタを代入していないので
違うのをコピーしていました。
{
FILE *fp;
char *str;
char buf[1000];
if((fp=fopen("ファイル名","r"))==NULL){
printf("fail open error");
return 0;
}
while(fgets(buf,1000,fp){
str=buf
int len=strlen(str);
str+=len;
--str;
while(buf <= str){
if(isdigit(*str)){
printf("%c",*str);
}
else if(*str == '.'){
printf("\n");
}
--str;
}
printf("\n");
}
}
かな。ですが今行うと何も表示されませんね。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 18:01
by GPGA
提示されたソースにはコンパイルエラーになる箇所が2か所ほどあります。
そこを修正したら、問題なく表示されましたよ。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 18:06
by ざこ
成る程、あぁセミコロンがないですね・・手書きだとどうも忘れてしまいます。
後1つがわかりません。
Re:ファイル(初心者です)
Posted: 2008年12月04日(木) 18:10
by GPGA
>while(fgets(buf,1000,fp){
です。
手書きではなく、実際にコンパイルしているソースをコピペするようにしてください。