関数に引数について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
KTN19
記事: 23
登録日時: 8年前

関数に引数について

#1

投稿記事 by KTN19 » 8年前

入力するのは,大文字を含めた 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';


}

box
記事: 2002
登録日時: 13年前

Re: 関数に引数について

#2

投稿記事 by box » 8年前

こんな感じ?

コード:

#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;
}
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数に引数について

#3

投稿記事 by みけCAT » 8年前

普通に書けばいいです。

コード:

#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';


}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

KTN19
記事: 23
登録日時: 8年前

Re: 関数に引数について

#4

投稿記事 by KTN19 » 8年前

あえて関数 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';


}

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数に引数について

#5

投稿記事 by みけCAT » 8年前

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 ];
	}
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

かずま

Re: 関数に引数について

#6

投稿記事 by かずま » 8年前

みけ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: 関数に引数について

#7

投稿記事 by かずま » 8年前

かずま さんが書きました: 11行目の後に、dest = '\0'; が必要です。
5行目、i < strlen(str) のような馬鹿げたコードを書かずに src != '\0' にしているのは good です。
  • dest = '\0'; ⇒ dst = '\0';
  • i < strlen(str) ⇒ i < strlen(src)

すみません。送信してから、間違いに気づくとは。
もっとちゃんとプレビューしないといけませんね。

かずま

Re: 関数に引数について

#8

投稿記事 by かずま » 8年前

みけ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 しか渡さないから、あまり問題になって
いないのでしょう。

box
記事: 2002
登録日時: 13年前

Re: 関数に引数について

#9

投稿記事 by box » 8年前

かずま さんが書きました: 5行目、i < strlen(str) のような馬鹿げたコードを書かずに src != '\0' にしているのは good です。

ははっ。
これで、おたく >>>>> 当方
という優秀度の違いがあらためて証明されましたな。
すばらしい!
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: 関数に引数について

#10

投稿記事 by みけCAT » 8年前

ご指摘ありがとうございます。
修正版です。

符号付き整数に変換する時、値がその符号付き整数に収まらない場合の動作は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';
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

KTN19
記事: 23
登録日時: 8年前

Re: 関数に引数について

#11

投稿記事 by KTN19 » 8年前

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: 関数に引数について

#12

投稿記事 by かずま » 8年前

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>

閉鎖

“C言語何でも質問掲示板” へ戻る