ページ 11

ポインタについて

Posted: 2010年3月12日(金) 17:57
by テツ
初めまして。テツと申します。
今回ポインタについてわからないことがあったので質問しました。

環境はBorland bcc5.5 OSはXPになります。

以下自分で作成した文字列を小文字にするサンプルです。
#include <stdio.h>

void StrToSmall(const char *conversionStr, char *convertedStr)
{
    while (*conversionStr) {
        *(convertedStr++) = tolower(*conversionStr++);
    }
    *convertedStr = '\0';
}

int main(void) 
{
    char    conversionStr[/url] = "HElloWORld";        // 元の文字列
    char    convertedStr[256];            // 変換後の文字列をセット
    
    StrToSmall(conversionStr, convertedStr);
    
    printf("変換前 : %s\n", conversionStr);
    printf("変換後 : %s\n", convertedStr);
    
    return 0;
}
このStrToSmall関数の以下の行なのですが、
*(convertedStr++) = tolower(*conversionStr++);
これはconversionStrの内容を小文字に変換してconvertedStrに格納した後conversionStrのアドレスを進めているという解釈で大丈夫でしょうか?

あともう一点あるのですが、関数内でconversion, StrconvertedStrの内容を確認出来ないのはなぜでしょうか?
printf文で確認してもnullが入っているのに、main側ではちゃんと内容が確認出来るのが不思議です。

ポインタをよく理解せずに使っているのでこの機会にしっかり押さえたいと思います。
しょうもない質問で申し訳ないですがよろしくお願いします。

Re:ポインタについて

Posted: 2010年3月12日(金) 18:45
by dic
void StrToSmall(const char *conversionStr, char *convertedStr)
{
    while (*conversionStr) {
        *(convertedStr) = tolower(*conversionStr);
        printf( "%c", *convertedStr );
        conversionStr++;
        convertedStr++;
    }
    printf( "\n" );
    *convertedStr = '\0';
}
で関数の中でも確認できます

>これはconversionStrの内容を小文字に変換してconvertedStrに格納した後conversionStrのアドレスを進めているという解釈で大丈夫でしょうか?
それでいいですよ

Re:ポインタについて

Posted: 2010年3月12日(金) 19:12
by box
> 関数内でconversion, StrconvertedStrの内容を確認出来ないのはなぜでしょうか?
> printf文で確認してもnullが入っている

そのときのソースを貼ってください。

ところで、printf「文」ではなく、printf「関数」です。
また、tolower(関数またはマクロ)を使うときは、
そのプロトタイプを宣言している ctype.h をインクルードしましょう。

Re:ポインタについて

Posted: 2010年3月12日(金) 20:31
by 初級者
たぶん、こんなので確認できるでしょうね。


#include <stdio.h>
#include <ctype.h>

void StrToSmall(const char *src, char *dest)
{
while (*src) {
*dest++ = tolower(*src++);
printf("%c %c\n", src[-1], dest[-1]);
}
*dest = '\0';
}

int main(void)
{
char conversionStr[/url] = "HElloWORld"; // 元の文字列
char convertedStr[256]; // 変換後の文字列をセット

StrToSmall(conversionStr, convertedStr);

printf("変換前 : %s\n", conversionStr);
printf("変換後 : %s\n", convertedStr);

return 0;
}

画像

Re:ポインタについて

Posted: 2010年3月12日(金) 20:48
by テツ
dic様

ソースをご提供いただきありがとうございます。
%cで確認すればいいのですね。

box様

ちなみにソースがこちらです。
#include <stdio.h>
#include <ctype.h>
void StrToSmall(const char *conversionStr, char *convertedStr)
{
    while (*conversionStr) {
        (*convertedStr++) = tolower(*conversionStr++);
    }
    *convertedStr = '\0';
    printf("%s\n", convertedStr);
}
int main(void)
{
    char    conversionStr[/url] = "HElloWORld";            // 元の文字列
    char    convertedStr[256];                        // 変換後の文字列をセット

    StrToSmall(conversionStr, convertedStr);

    printf("変換前 : %s\n", conversionStr);
    printf("変換後 : %s\n", convertedStr);

    return 0;
}
>ところで、printf「文」ではなく、printf「関数」です。
また、tolower(関数またはマクロ)を使うときは、
そのプロトタイプを宣言している ctype.h をインクルードしましょう。

その通りです。指摘ありがとうございます。

初級者様

ソースをご提供いただきありがとうございます。
ただ何故[-1]何でしょうか?よろしければ教えていただきたいです。

皆様にご指摘を受けて大変ありがたいのですが、なぜ%cでないといけないのかが分かりません。
%sで文字列と出力することは何故出来ないでしょうか?

Re:ポインタについて

Posted: 2010年3月12日(金) 21:09
by ideyan
%sで表示とは

>*convertedStr = '\0';
>printf("%s\n", convertedStr);

この部分のことでしょうか。

「convertedStrが今どこを指しているのか」を考えてみてください。

(適当な図ですいませんが)
convertedStr++とするたびに、ポインタが差す位置は
図の緑矢印の方向にずれていきます。

テツさんがprintfを呼び出している場所の時、
convertedStrは文字列 "helloworld\0" の'\0'の位置を指しているので
それに出力してもNULLが出るだけになります。


>ただ何故[-1]何でしょうか?よろしければ教えていただきたいです

*dest++ = tolower(*src++);
この文の実行後、ポインタは一つ進んでいるので
実際に変換した文字を見たければ一つ前を参照する必要があります。
ポインタが差している値の参照方法として
*dest
dest[0]
は同じ意味になるので
dest[-1]は現在指している位置の一つ前を参照していることになります。

>%sで文字列と出力することは何故出来ないでしょうか?
conversionStrに対しては%sを使っても構いません。
試しにループの中にprintfを入れてみると、
徐々にポインタの指す位置がずれていくのが分かると思います。

convertedStrの方は、今回の場合なら関数の最後でヌル文字を入れるまでは
使ってはいけません。終端が無いので変な所にアクセスする可能性があります。

Re:ポインタについて

Posted: 2010年3月12日(金) 22:17
by テツ
ideyan 様

図解で詳しく教えていただきありがとうございます。
すごく分かり易かったです。

ポインタが差している位置を考えれば自ずとわかるんですね。
あまり理解しないで使っていたので駄目でしたが、今日理解することが出来ました。

皆様

短時間でこれ程の返信ありがとうございました。
またお世話になるかもしれませんので、その際はよろしくお願いいたします。