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

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

新規登録して質問してみよう
ただいま回答率
85.37%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

1051閲覧

文字列の変換や連結など

Merrifield

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2020/08/31 13:06

編集2020/08/31 23:44

下の例の通りの関数を作りたいと思っています。return文の箇所の間違いがわからないので、教えてください。


accum("abcd") -> "A-Bb-Ccc-Dddd"
accum("RqaEzty") -> "R-Qq-Aaa-Eeee-Zzzzz-Tttttt-Yyyyyyy"
accum("cwAt") -> "C-Ww-Aaa-Tttt"

c

1 2#include <ctype.h> 3#include <string.h> 4#include <stdio.h> 5 6char *accum(const char *source) 7{ 8 int n; 9 char str1[255]; 10 char a = '-'; 11 12 for(n = 0; n < (int)strlen(source); n++) 13 { 14 15 sprintf(str1,"%c",toupper(source[n])); 16 17 if(n > 0) 18 { 19 for(int m =0; m < n; m++) 20 { 21 sprintf(str1,"%c",tolower(source[n])); 22 } 23 } 24 25 sprintf(str1,"%c",a); 26 } 27 28 return str1; 29}

エラーコード

solution.c:9:38: warning: 'sizeof source' will return the size of the pointer, not the array itself [-Wsizeof-pointer-div] for(n = 0; n < (int)(sizeof source / sizeof source[0]); n++) ~~~~~~~~~~~~~ ^ solution.c:12:5: warning: implicitly declaring library function 'sprintf' with type 'int (char *, const char *, ...)' [-Wimplicit-function-declaration] sprintf(str1,"%c",toupper(source[n])); ^ solution.c:12:5: note: include the header <stdio.h> or explicitly provide a declaration for 'sprintf' solution.c:25:11: warning: address of stack memory associated with local variable 'str1' returned [-Wreturn-stack-address] return str1; ^~~~ 3 warnings generated. 2 warnings and 6 errors generated.

修正版

c

1#include <ctype.h> 2#include <string.h> 3#include <stdio.h> 4 5char *accum(const char *source) 6{ 7 int n; 8 char str1[255]; 9 char a = '-'; 10 11 for(n = 0; n < (int)strlen(source); n++) 12 { 13 14 sprintf(str1,"%c",toupper(source[n])); 15 16 if(n > 0) 17 { 18 for(int m = 0; m < n; m++) 19 { 20 sprintf(str1,"%c",tolower(source[n])); 21 } 22 } 23 24 sprintf(str1,"%c",a); 25 } 26 27 return str1; 28}

修正版のエラー

solution.c:27:11: warning: address of stack memory associated with local variable 'str1' returned [-Wreturn-stack-address] return str1; ^~~~ 1 warning generated.

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

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

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

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

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

thkana

2020/08/31 23:03

エラーメッセージの部分もコードと同様に ``` ``` で囲ってください。
Merrifield

2020/08/31 23:44

エラーメッセージもコードのような書き方にするべきだったのですね。ありがとうございます。
guest

回答2

0

ベストアンサー

修正版のエラー

solution.c:27:11: warning: address of stack memory associated with local variable 'str1' returned [-Wreturn-stack-address]
return str1;
^~~~
1 warning generated.

char str1[255]; は関数 accum のローカル変数で自動変数です。
関数に入った時に領域が確保され、関数から出た時に領域は無効になります。
その無効になった領域へのポインタが返されても、関数の呼び出し元では
正しい結果を参照することができません。

結果を入れてほしい領域は、関数の呼び出し元で用意し、関数を呼び出すときに
それも渡すようにしましょう。

C

1#include <ctype.h> // toupper, tolower 2#include <string.h> // strlen 3#include <stdio.h> // printf 4 5char *accum(const char *source, char *str1, int size) 6{ 7 int n = strlen(source); 8 if (n*(n+3)/2 > size) return NULL; 9 char *p = str1; 10 for (int i = 0; i < n; i++) { 11 int c = (unsigned char)source[i]; 12 if (i > 0) *p++ = '-'; 13 *p++ = toupper(c); 14 for (int j = 0; j < i; j++) *p++ = tolower(c); 15 } 16 *p = '\0'; 17 return str1; 18} 19 20int main(void) 21{ 22 char buf[256]; 23 printf("[%s]\n", accum("abcd", buf, 256)); 24 printf("[%s]\n", accum("RqaEzty", buf, 256)); 25 printf("[%s]\n", accum("cwAt", buf, 256)); 26}

投稿2020/08/31 15:48

編集2020/08/31 23:46
kazuma-s

総合スコア8224

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

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

Merrifield

2020/09/01 00:04

お答えいただきありがとうございました。 n*(n+3)/2 というのは、どういう意味なのでしょうか?
Merrifield

2020/09/01 00:06 編集

続けての質問で申し訳ないですが、 char *str = (char*)malloc(len * (len + 1));とすれば return str; のように戻り値としてと書くことができますか?
kazuma-s

2020/09/01 00:22

"abcd" は 4文字、変換後の "A-Bb-Ccc-Dddd" は 13文字、文字列の終端の '\0' も含めると 14バイトの領域が必要です。n*(n+3)/2 は変換後に必要となるバイト数です。size がそれより小さいと変換結果を格納できません。 malloc で領域を確保すれば問題ありませんが、あとでどこかで free しないと、メモリをどんどん食いつぶしていきます。
Merrifield

2020/09/01 00:26

理解できました。答えていただきありがとうございました。
kazuma-s

2020/09/01 01:16

malloc(len * (len + 1)) では、len = 4 のとき、20バイト確保してしまいます。
Merrifield

2020/09/01 01:24

そうですね。教えていただいてありがとうございます。
guest

0

エラーメッセージを追いましょう。

warning: 'sizeof source' will return the size of the pointer,

source は、accum()の引数なので、const char * 配列のサイズは取得できません。ここでは、strlen()あたりを使うのが、よくある方法。

sprintf(str1,%c,toupper(source[n]));

こちらの警告では、stdin.hでは、int (char *, const char *, ...)となっていると言ってます。 2番目の引数を見ると、 %c となってます。ここは、const char * であるべき。
以下、ほぼ同様。

投稿2020/08/31 13:17

pepperleaf

総合スコア6385

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

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

Merrifield

2020/08/31 13:25 編集

回答ありがとうございます。 const char * 配列のサイズは取得できないというのは、なぜなのでしょうか? また、sprintfに関しての警告は、#include <stdio.h>を追加すれば問題ないでしょうか?
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.37%

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

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

質問する

関連した質問