質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

Q&A

解決済

3回答

783閲覧

C言語:const修飾子の使い方など

sanshirou

総合スコア7

VC++

VC++ (Visual C++) とは、Microsoft製のC++のための統合開発環境です。

0グッド

0クリップ

投稿2022/08/29 03:00

前提

文字列単位で英大文字を小文字に変換する関数を自作しましたが、今一つ自信がありませんのでご助言を賜りたいです。

実現したいこと

文字単位のtolower()関数の文字列版を作るのが目的です。

  • 入力する文字列をconst char *型の引数とする。
  • 出力する文字列をchar *char型の戻り値とする。

発生している問題・エラーメッセージ

いろいろstr関係のライブラリ関数の仕様を見ていて、なんとなく引数にconst修飾子をつけたのですが、出力文字列を受けるsoutの初期化でsout = sin;とすると、

異なるconst修飾子です。

という警告が出ました。そこでなんとなく、sout = (char *)sin;とキャストすると、警告なくコンパイルでき、実行結果も問題ありませんでした。
しかし、上記のように「なんとなく」で進んできたので気持ち悪く、今一つ自信がありません。
ポインタを返す関数を自作するのは初めてなので、いろいろ不安です。
オーソドックスというか、エレガントというか、問題のないコーディング流儀をご教授いただきたいです。
よろしくお願いいたします。

該当のソースコード

C

1#include <stdio.h> 2#include <stdlib.h> 3#include <string.h> 4#include <ctype.h> 5 6/* 文字列単位で英大文字を小文字に変換する関数 */ 7/* tolower()関数を使用する */ 8char *tolowerstr(const char *sin); 9 10int main(void) 11{ 12 char line[256]; 13 14 printf("文字列単位で英大文字を小文字に変換します。\n\n"); 15 printf("英文字列を入力してください。\n"); 16 fgets(line, sizeof line, stdin); 17 line[strlen(line) - 1] = '\0'; 18 19 printf("↓\n"); 20 printf("%s\n", tolowerstr(line)); 21 22 return EXIT_SUCCESS; 23} 24 25/* 文字列単位で英大文字を小文字に変換する関数 */ 26/* tolower()関数を使用する */ 27char *tolowerstr(const char *sin) 28{ 29 int i = 0; 30 char *sout; 31 sout = (char *)sin; 32 33 while(sin[i]) { 34 sout[i] = tolower(sin[i]); 35 i++; 36 } 37 38 return sout; 39}

実行結果

文字列単位で英大文字を小文字に変換します。 英文字列を入力してください。 ABC-Z ↓ abc-z

補足情報(FW/ツールのバージョンなど)

コンパイラ:Visual Studio 2022、OS:Windows10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

英大文字を小文字に変換する関数

これだけだと,ふわっとしすぎていて話が不十分.
…っていうのが本質というか根っこのところなんじゃないかな.
その関数の機能というのが,

  • 入力データそのものを書き換えてしまう
  • 入力データとは別に,結果データを作る

のどっちなのか?

前者側なのであれば「 const とか言っていること」が間違っているという話になるのだし,
後者側なのであれば,じゃあ結果データってのはどこに作るのか?っていう話が当然あるわけで,それと照らし合わせれば「sout = sin; とかいう実装は話としておかしくね?」っていう話になるよね.こっちの場合,入力データ側が const なのは正当だ.

投稿2022/08/29 05:58

fana

総合スコア11658

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2022/08/30 01:10 編集

> ポインタを返す関数を自作するのは初めて とか言ってるけど,そもそもその関数の戻り値は何なの?(何を指すポインタなの?)ってのがちゃんと定まっているのか? っていう. (入力データそのものを書きかえる関数なのであれば,戻り値は別に無くてもいいよね.「いやいや利便性のための戻り値なんです」とか言えるのであればそもそも「不安」なんて抱かないハズ)
fana

2022/08/29 06:12 編集

「入力データとは別に,結果データを作る」タイプの関数なのであれば結果の格納先が必要だよね. 少なくとも入力データの文字数を格納できるだけの出力バッファが要る. じゃあそれは誰が用意するのか? 関数の外側で用意するのであれば,そのバッファのことを関数にどうにかして「ここに結果を入れてね」って知らせる必要があるよね. そうではなくて関数が勝手に用意する? どうやって? 「メモリを動的に確保して返すぞ」とかいうならその旨をしっかり定めないといかんでしょ.
fana

2022/08/29 06:10

…つーわけで,引数やら戻り値やらのあるべき形ってのは,関数の仕様次第なのだから, 何はともあれ関数の仕様をしっかり固める(決める)ということをする → で,その仕様通りに実装する. っていう順序でやるべき. 実装の段になってから「なんとなくキャスト」とか言い出す余地はそもそもないハズ. (あと,キャストなんていう最上級危険物を「なんとなく」で扱っちゃダメです.)
sanshirou

2022/09/03 03:54

fanaさん、ご回答ありがとうございます。ベストアンサーをつけてから見ていなくて、ご返事が遅くなってしまいました。 > 引数やら戻り値やらのあるべき形ってのは,関数の仕様次第なのだから, > 何はともあれ関数の仕様をしっかり固める(決める)ということをする → で,その仕様通りに実装する. > っていう順序でやるべき. > 実装の段になってから「なんとなくキャスト」とか言い出す余地はそもそもないハズ. > (あと,キャストなんていう最上級危険物を「なんとなく」で扱っちゃダメです.) いろいろためになる知見をありがとうございました。まずは関数の仕様を明確にする、それからですね。よくわかりました。ありがとうございました。
guest

0

ベストアンサー

そもそも、constってのは変化させないという修飾子なので、そこにconstをつけるのは間違いです

投稿2022/08/29 03:23

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sanshirou

2022/08/29 05:43

constは必要なかった、ということですかね。ありがとうございました。
y_waiwai

2022/08/29 05:55

sin の内容を変換して変更するのですから、constをつけてはいけません
Zuishin

2022/08/29 11:02

> 入力する文字列をconst char *型の引数とする。 条件を満たさなくなるので、この回答は誤りです。
guest

0

strcpyみたいにchar* tolowerstr(chardst, char constsrc)にするか、strdupみたいにdstをmallocして返す関数にする話では。

投稿2022/08/29 03:11

matukeso

総合スコア1590

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sanshirou

2022/08/29 05:42

ご回答ありがとうございます。しかしながら、意味が理解できませんでした。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問