ページ 1 / 1
関数に引数について
Posted: 2015年12月17日(木) 00:10
by KTN19
入力するのは,大文字を含めた December 25th Merry Christmas.という文なのです.
これを関数を用いて大文字の部分のみ小文字に変換したいのですが,上手く引数をかけないのですが,どのように書けばよいのでしょうか?
コード:
#include <stdio.h>
void get_line(char buff[], int size);
void str_lcopy(char dst[], char src[]);
int main (void)
{
char src[128], dst[128];
printf("Key in a string>> ");
get_line(src, 128);
printf("src: %s\n", src);
printf("dst: %s\n", dst);
return 0;
}
void get_line(char buff[], int size)
{
int i, c;
for (i=0; i<size-1; i++)
{
c = getchar();
if (c == EOF || c == '\n') break;
buff[i] = c;
}
buff[i] = '\0';
str_lcopy( , buff );
}
void str_lcopy(char dst[], char src[])
{
int i;
for( i = 0; src[ i ] != '\0'; i++ )
{
src[ i ] = dst[ i ];
if( dst[ i ] >= 'A' && dst[ i ] >= 'Z' )dst[ i ] = dst[ i ] + 20;
}
dst[ i ] = '\0';
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 00:20
by box
こんな感じ?
コード:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define N (256)
void convertToLower(char *src, char *dest)
{
int i;
for (i = 0; i < strlen(src); i++) {
dest[i] = isupper(src[i]) ? tolower(src[i]) : src[i];
}
dest[i] = '\0';
}
int main(void)
{
char src[N], dest[N];
printf("Key in a string>> ");
fgets(src, N, stdin);
src[strlen(src) - 1] = '\0';
convertToLower(src, dest);
printf("%s\n", dest);
return 0;
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 00:24
by みけCAT
普通に書けばいいです。
コード:
#include <stdio.h>
#include <ctype.h>
void get_line(char buff[], int size);
void str_lcopy(char dst[], const char src[]);
int main (void)
{
char src[128], dst[128];
printf("Key in a string>> ");
get_line(src, 128);
str_lcopy(dst, src);
printf("src: %s\n", src);
printf("dst: %s\n", dst);
return 0;
}
void get_line(char buff[], int size)
{
int i, c;
for (i=0; i<size-1; i++)
{
c = getchar();
if (c == EOF || c == '\n') break;
buff[i] = c;
}
buff[i] = '\0';
}
void str_lcopy(char dst[], const char src[])
{
int i;
for( i = 0; src[ i ] != '\0'; i++ )
{
dst[ i ] = src[ i ];
if( isupper(dst[ i ]) )dst[ i ] = tolower(dst[ i ]);
}
dst[ i ] = '\0';
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 00:49
by KTN19
あえて関数 tolower( ) を使わないでするとするとどうしたらよいでしょうか
コード:
void get_line(char buff[], int size)
{
int i, c;
for (i=0; i<size-1; i++)
{
c = getchar();
if (c == EOF || c == '\n') break;
buff[i] = c;
}
buff[i] = '\0';
}
void str_lcopy(char dst[], char src[])
{
int i;
char a;
for( i = 0; src[ i ] != '\0'; i++ )
{
if( dst[ i ] >= 'A' && dst[ i ] <= 'Z' ){
dst[ i ] = a;
a = 'a' + 20;
}
else dst[ i ] = src[ i ];
}
dst[ i ] = '\0';
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 01:19
by みけCAT
KTN19 さんが書きました:あえて関数 tolower( ) を使わないでするとするとどうしたらよいでしょうか
変換表を用意するのがいいでしょう。
アルファベットの文字コードは連続しているとは限らないことに注意してください。
コード:
int oomozi_de_aru(char c) {
static const char oomozi[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
const char *p;
for (p = oomozi; *p != '\0'; p++) {
if (*p == c) return 1;
}
return 0;
}
char komozi_ni_suru(char c) {
static const char oomozi[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char komozi[] = "abcdefghijklmnopqrstuvwxyz";
int i;
for (i = 0; oomozi[i] != '\0'; i++) {
if (oomozi[i] == c) return komozi[i];
}
return c;
}
void str_lcopy(char dst[], const char src[])
{
int i;
for( i = 0; src[ i ] != '\0'; i++ )
{
if( oomozi_de_aru(src[ i ]) ){
dst[ i ] = komozi_ni_suru(src[ i ]);
}
else dst[ i ] = src[ i ];
}
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 02:06
by かずま
みけCAT さんが書きました:コード:
void str_lcopy(char dst[], const char src[])
{
int i;
for( i = 0; src[ i ] != '\0'; i++ )
{
if( oomozi_de_aru(src[ i ]) ){
dst[ i ] = komozi_ni_suru(src[ i ]);
}
else dst[ i ] = src[ i ];
}
}
7, 9, 10行目は不要でしょう。
11行目の後に、dest
= '\0'; が必要です。
5行目、i < strlen(str) のような馬鹿げたコードを書かずに src != '\0' にしているのは good です。
KTN19さん、前のトピック 「配列を表示させたい!」 を放置しないでください。
Re: 関数に引数について
Posted: 2015年12月17日(木) 02:11
by かずま
かずま さんが書きました:
11行目の後に、dest = '\0'; が必要です。
5行目、i < strlen(str) のような馬鹿げたコードを書かずに src != '\0' にしているのは good です。
- dest = '\0'; ⇒ dst = '\0';
- i < strlen(str) ⇒ i < strlen(src)
すみません。送信してから、間違いに気づくとは。
もっとちゃんとプレビューしないといけませんね。
Re: 関数に引数について
Posted: 2015年12月17日(木) 03:08
by かずま
みけCAT さんが書きました:普通に書けばいいです。
コード:
void str_lcopy(char dst[], const char src[])
{
int i;
for( i = 0; src[ i ] != '\0'; i++ )
{
dst[ i ] = src[ i ];
if( isupper(dst[ i ]) )dst[ i ] = tolower(dst[ i ]);
}
dst[ i ] = '\0';
}
7.4.2.1 tolower関数
JIS X 3010-2003 さんが書きました:
7.4.2大文字小文字変換関数
7.4.2.1tolower関数
形式
#include <ctype.h>
int tolower(int c);
機能 tolower 関数は,大文字を対応する小文字に変換する。
返却値 実引数が,isupper 関数に対して真となる文字であって,かつ islower
関数が真となる 1 個以上の対応する文字(その時点のロケールの指定に従う。)
がある場合,tolower関数はその対応する文字のいずれか一つを返す(同じロケー
ルに対しては必ず同じ文字。)。そうでない場合,その実引数を変換せずにその
まま返す。
すなわち、tolower を呼び出す前に isupper は不要ということです。
7.4 文字操作<ctype.h>
JIS X 3010-2003 さんが書きました:
7.4 文字操作<ctype.h> ヘッダ<ctype.h>は,文字の分類及び文字の変換に
有用な幾つかの関数を宣言する(166)。この中で宣言されるすべての関数は,int 型
の一つの実引数をもつ。その値は unsigned char で表現可能であるか,又はマクロ
EOF の値に等しくなければならない。実引数がその他の値をもつ場合,その動作は
未定義とする。
すなわち、引数は -1~255 の範囲でなければならないのに、char を渡すと
-128~127 の値が渡ることになり、未定義の動作となることがあります。
もっとも、通常は、ASCII文字の 0~127 しか渡さないから、あまり問題になって
いないのでしょう。
Re: 関数に引数について
Posted: 2015年12月17日(木) 06:59
by box
かずま さんが書きました:
5行目、i < strlen(str) のような馬鹿げたコードを書かずに src != '\0' にしているのは good です。
ははっ。
これで、おたく >>>>> 当方
という優秀度の違いがあらためて証明されましたな。
すばらしい!
Re: 関数に引数について
Posted: 2015年12月17日(木) 08:03
by みけCAT
ご指摘ありがとうございます。
修正版です。
符号付き整数に変換する時、値がその符号付き整数に収まらない場合の動作はimplemented-definedなので、それを避けるためにisupper()によるチェックを残しました。
コード:
void str_lcopy(char dst[], const char src[])
{
size_t i;
for( i = 0; src[ i ] != '\0'; i++ )
{
dst[ i ] = src[ i ];
if (isupper((unsigned char)dst[ i ]))
{
dst[ i ] = tolower((unsigned char)dst[ i ]);
}
}
dst[ i ] = '\0';
}
コード:
char komozi_ni_suru(char c) {
static const char oomozi[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char komozi[] = "abcdefghijklmnopqrstuvwxyz";
size_t i;
for (i = 0; oomozi[i] != '\0'; i++) {
if (oomozi[i] == c) return komozi[i];
}
return c;
}
void str_lcopy(char dst[], const char src[])
{
size_t i;
for( i = 0; src[ i ] != '\0'; i++ )
{
dst[ i ] = komozi_ni_suru(src[ i ]);
}
dst[ i ] = '\0';
}
Re: 関数に引数について
Posted: 2015年12月17日(木) 14:33
by KTN19
boxさん、みけCATさん、かずまさん、ご教授ありがとうございました!
新たに関数を用いて参照するというのは思いつきませんでした!!
大変役に立ちました!!
コード:
#include <stdio.h>
void get_line(char buff[], int size);
void str_lcopy(char dst[], char src[]);
char turn( char c );
int main (void)
{
char src[128], dst[128];
printf("Key in a string>> ");
get_line(src, 128);
str_lcopy( dst, src );
printf("src: %s\n", src);
printf("dst: %s\n", dst);
return 0;
}
void get_line(char buff[], int size)
{
int i, c;
for (i=0; i<size-1; i++)
{
c = getchar();
if (c == EOF || c == '\n') break;
buff[i] = c;
}
buff[i] = '\0';
}
char turn( char c )
{
char big[ 26 ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char small[ 26 ] = "abcdefghijklmnopqrstuvwxyz";
int i;
for( i = 0; big[ i ] != '\0'; i++ ){
if( big[ i ] == c ) return small[ i ];
}
return c;
}
void str_lcopy(char dst[], char src[])
{
int i, j;
char a;
for( i = 0; src[ i ] != '\0'; i++ )
{
dst[ i ] = turn( src[ i ] );
}
dst[ i ] = '\0';
}
Re: 関数に引数について
Posted: 2015年12月18日(金) 06:41
by かずま
KTN19 さんが書きました:
コード:
char turn( char c )
{
char big[ 26 ] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char small[ 26 ] = "abcdefghijklmnopqrstuvwxyz";
int i;
for( i = 0; big[ i ] != '\0'; i++ ){
if( big[ i ] == c ) return small[ i ];
}
return c;
}
turn() ですが、1文字ごとに for文でループを回るのは、
ちょっと効率が悪いと思います。
次のように書けば、文字コードが EBCDIC のように、
'A' から 'Z' までが連続していなくても OK です。
コード:
char turn( char c )
{
switch (c) {
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
case 'V': case 'W': case 'X': case 'Y': case 'Z': return c - 'A' + 'a';
}
return c;
}
コンパイル結果もリーズナブルです。
コード:
C:\tmp>gcc -c -O2 turn.c
C:\tmp>objdump -d turn.o
turn.o: file format pe-x86-64
Disassembly of section .text:
0000000000000000 <turn>:
0: 8d 51 bf lea -0x41(%rcx),%edx
3: 8d 41 20 lea 0x20(%rcx),%eax
6: 80 fa 19 cmp $0x19,%dl
9: 0f 47 c1 cmova %ecx,%eax
c: c3 retq
d: 90 nop
e: 90 nop
f: 90 nop
C:\tmp>cl -c -O2 turn.c
Microsoft(R) C/C++ Optimizing Compiler Version 18.00.31101 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
turn.c
C:\tmp>dumpbin -disasm turn.obj
Microsoft (R) COFF/PE Dumper Version 12.00.31101.0
Copyright (C) Microsoft Corporation. All rights reserved.
Dump of file turn.obj
File Type: COFF OBJECT
_turn:
00000000: 8A 4C 24 04 mov cl,byte ptr [esp+4]
00000004: 8D 41 BF lea eax,[ecx-41h]
00000007: 3C 19 cmp al,19h
00000009: 77 07 ja 00000012
0000000B: 0F BE C1 movsx eax,cl
0000000E: 83 C0 20 add eax,20h
00000011: C3 ret
00000012: 8A C1 mov al,cl
00000014: C3 ret
Summary
10 .debug$F
60 .debug$S
2F .drectve
15 .text$mn
C:\tmp>