プログラミング入門2 第6回 基本型、文字列

52
ププププププププププププ プププ プププププ ププ プ

Upload: gwen

Post on 04-Jan-2016

35 views

Category:

Documents


1 download

DESCRIPTION

プログラミング入門2 第6回 基本型、文字列. 情報工学科 篠埜 功. 今日の内容. 基本型、文字列について. 基本型. これまでに紹介した基本型は int 型、 double 型である。その他にもさまざまな基本型があり、整数型、浮動小数点型に分類できる。. 整数型. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: プログラミング入門2 第6回 基本型、文字列

プログラミング入門2第6回

基本型、文字列

情報工学科 篠埜 功

Page 2: プログラミング入門2 第6回 基本型、文字列

今日の内容• 基本型、文字列について

Page 3: プログラミング入門2 第6回 基本型、文字列

基本型• これまでに紹介した基本型は int

型、 double 型である。その他にもさまざまな基本型があり、整数型、浮動小数点型に分類できる。

Page 4: プログラミング入門2 第6回 基本型、文字列

整数型整数型は 、 char 型 , short int 型 , int 型 , long int 型の4種類に分かれる (C99 では long long int 型が加わり、5種類 ) 。 char 型が一番小さく、 long int型が一番大きい(具体的に何バイトかは定められておらず、処理系によって異なる)。それぞれの型は、符号付きと符号無しでそれぞれ2つずつある。 型指定子 (signed か unsigned)で指定する。 char 型以外は、型指定子を与えない場合は符号付きになる。 char 型は、型指定子を与えない場合は、符号付きか符号無しかのいずれかである(処理系依存)。扱う数の範囲に応じて適切な型を選択して用いる。

Page 5: プログラミング入門2 第6回 基本型、文字列

char 型が符号付きかどうか判定(打ち込んで確認)

#include <stdio.h>#include <limits.h>

int main (void) { printf (" この処理系の char 型は "); if (CHAR_MIN) printf(" 符号つきです。 \n"); else printf(" 符号無しです。 \n"); return 0;}

Page 6: プログラミング入門2 第6回 基本型、文字列

整数型整数型は、結局、– signed char 型– unsinged char 型– signed short int 型– unsigned short int 型– signed int 型– unsigned int 型– signed long int 型– unsigned long int 型

の8個となる。 (long long int を入れれば10個。 )

Page 7: プログラミング入門2 第6回 基本型、文字列

符号について(1)符号無し整数型 (unsigned char, unsigned short int, unsigned int, unsigned long int) においては、ビット列を普通の2進数として解釈する。

Page 8: プログラミング入門2 第6回 基本型、文字列

符号について(2)

符号付き整数型 (signed char, signed short int, signed int, signed long int,) においては、符号を表すために1ビットを用いる(これを符号ビットという)。符号ビットが 0 の場合には、残りのビットを普通の 2 進数として解釈する。符号ビットが 1 の場合の解釈は以下の 3 通りのいずれかである(処理系依存)。•  符号ビットを 0 に変えた場合のビット列が表

す数にマイナスを付けた数を表す•   2 の補数表現•   1 の補数表現

Page 9: プログラミング入門2 第6回 基本型、文字列

例外について演算の結果が、表現可能な値の範囲を超える場合( overflow )や、 0 での除算などの場合、例外 (exception) が発生する。

ただし、符号無し整数型の演算では、表現可能な値の範囲を超えた場合、表現可能な最大値 +1 で割った余りになると定められている(のでオーバーフローは発生しない)。

Page 10: プログラミング入門2 第6回 基本型、文字列

文字についてプログラム中では、 1 文字をクォートで囲むと、その文字に対応する int 型の数を表す。

(補足)文字は char 型で表すと無駄がないが、 int型で表しておくと、例えばファイルから文字を1文字ずつ読み取って変数に代入する場合、ファイルの終端に来た時に EOF(int 型、値はどの文字とも異なる。普通は -1 。 ) が返され、それを変数に代入し、その値が EOF と等しいかどうか判定するといったプログラムを書けるというメリットがある。(補足)文字列は char 型の並びである(後述)。

(例) ‘ a’ は a という文字に対応する int 型の数を表す。( char 型ではないことに注意。 C++ では char 型だが。)演習室の環境では、’ a’ は int 型の 97 を表す。

Page 11: プログラミング入門2 第6回 基本型、文字列

printf での文字の表示方法printf 関数で文字を表示する場合、変換指定子を %c にする。引数には int 型を受け取り、それを unsigned char 型に変換( 256 で割った非負の余りに変換)し、それに対応する文字を表示する。

#include <stdio.h>int main (void) { printf ("%c\n", 'a'); printf ("%d\n", 'a'); printf ("%c\n", 97); printf (“%c\n”, 97 + 256); printf (“%c\n”, 97 – 256); return 0;}

a97aaaが表示される。

Page 12: プログラミング入門2 第6回 基本型、文字列

文字の 8 進表記ある文字に対応する数が分かっているとき、その数で直接書きたい場合がある。その時に使うのが文字の 8 進表記である。例えば、’ a’ と書く代りに(演習室の環境では)’\141’ と書くことができる。ただし、プログラムの可搬性が低下するので使わない方がよい。よく使うのは、ヌル文字( null character 、値

は 0 、ナル文字と読む人もいる)を表す場合で、’ \0’ と書く。’ \0’ は、対応する数が 0 である文字に対応する数、つまり 0 を表している。0 と直接書いても同じ意味だが、 0 よりも’ \0’ の方が、文字を表している数だということが見た目に分かりやすいのでよく使う。

Page 13: プログラミング入門2 第6回 基本型、文字列

8 進逆斜線表記の構文(参考)\ octal-digit

\ octal-digit octal-digit

\ octal-digit octal-digit octal-digit

8 進逆斜線表記の構文 1

8 進逆斜線表記の構文 2

8 進逆斜線表記の構文 3

ただし、 octal-digit は 0 1 2 3 4 5 6 7 のいずれかを表す。つまり、バックスラッシュのあとに 1 桁から 3 桁の 8 進数を書いたものが 8 進逆斜線表記である。

8 進逆斜線表記はクォートおよびダブルクォートの中でのみ用いる。 8 進逆斜線表記をクォートで囲んだとき、それは、その 8 進数の表している数 (int 型 ) を表す。つまり、文字を表すための数であるということを見た目に分かりやすくするために用意されている構文である。

Page 14: プログラミング入門2 第6回 基本型、文字列

変数への格納#include <stdio.h>int main (void) { int x; x = 'a'; printf ("%c\n", x); printf ("%d\n", x); x = x+1; printf ("%c\n", x); printf (“%d\n”, x); return 0;}

文字はよく int 型の変数に格納される (EOF が格納できるようにするため ) 。 EOF を格納しない場合は char 型の変数に入れてよい。ただしあとで説明するように、文字列はchar 型の配列である。

1 を足したものを %c で表示すると b が表示される。

a97

b98

Page 15: プログラミング入門2 第6回 基本型、文字列

整数型の範囲について(打ち込んで確認)

C 言語の処理系は、 limits.h において、それぞれの型の最大値、最小値をマクロとして提供する。

#include <stdio.h>#include <limits.h>int main (void) { printf ("char : %d から %d まで \n", CHAR_MIN, CHAR_MAX); printf (“short int : %d から %d まで \n", SHRT_MIN, SHRT_MAX); printf ("int : %d から %d まで \n", INT_MIN, INT_MAX); printf ("long int : %ld から %ld まで \n", LONG_MIN, LONG_MAX); return 0;}

long int の変換指定子には %ld を用いる。

Page 16: プログラミング入門2 第6回 基本型、文字列

整数型のまとめ• 整数型はある一定の範囲の整数を表現す

るための型である。• 扱う数値が負にならないことが分かって

いれば、符号無しの型を使うと、同じビット数で、より大きな範囲の数を扱うことができる。

Page 17: プログラミング入門2 第6回 基本型、文字列

浮動小数点型浮動小数点型は小数を表すための型であり、– float 型– double 型– long double 型

の3つがある。この演習では説明しない。

Page 18: プログラミング入門2 第6回 基本型、文字列

文字列とは(1)char型の配列中の任意の場所から‘ \0’( ヌル文字 )までを文字列と言う。

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

‘\0’ ‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

これらは char 型の配列であるとする。(’ L’ や’ \0’ などは int 型だが、 char 型に変換されていると思って読んでください。) char 型の配列の中で、’\0’ が最後(だけ)にある部分を文字列という。

Page 19: プログラミング入門2 第6回 基本型、文字列

文字列とは(2)‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分は文字列である。

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分も文字列である。

一番右端が’ \0’ であり、それ以外に’ \0’ を含んでいなければそれは文字列である。

Page 20: プログラミング入門2 第6回 基本型、文字列

文字列とは(3)‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分は文字列である(空文字列という)。

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

この部分も文字列である。

一番右端が’ \0’ であり、それ以外に’ \0’ を含んでいなければそれは文字列である。

Page 21: プログラミング入門2 第6回 基本型、文字列

char 型の配列文字列は char 型の配列を宣言し、各要素に文字を 1 文字ずつ格納して最後にヌル文字を格納することによって作成できる。char 型の配列型の変数は char a [7];のように宣言する。これは char 型の要素を7 個持つ配列 a を宣言している。この宣言下で a[0] = ‘L’;という代入文が実行されると、’ L’(int 型の数 ) が暗黙の型変換 ( 第 1 回講義スライド参照 ) により char 型に変換されてから a[0]に代入される。

Page 22: プログラミング入門2 第6回 基本型、文字列

printf 関数での文字列の表示方法文字列の表示には、変換指定子に %s を用い、引数に char 型へのポインタ(後日説明)を与える。そのポインタが指しているところから、ヌル文字の手前までを画面に表示する。

#include <stdio.h>int main (void) { char a [7]; a[0] = ‘L’; a[1] = ‘i’; a[2] = ‘n’; a[3] = ‘\0’; a[4] = ‘u’; a[5] = ‘x’; a[6] = ‘\0’; printf (“%s\n”, &a[0]); return 0;}

&a[0] は配列 a の先頭要素へのポインタを表す。先頭要素は’ L’ であり、 Lin が表示される。

Page 23: プログラミング入門2 第6回 基本型、文字列

printf 関数での文字列の表示方法(打ち込んで確認)

#include <stdio.h>int main (void) { char a [7]; a[0] = ‘L’; a[1] = ‘i’; a[2] = ‘n’; a[3] = ‘\0’; a[4] = ‘u’; a[5] = ‘x’; a[6] = ‘\0’; printf (“%s\n”, &a[1]); return 0;}

&a[1] は配列 a の 2 番目の要素へのポインタを表す。 2 番目の要素は’ i’ であり、 in が画面に表示される。

Page 24: プログラミング入門2 第6回 基本型、文字列

注意• 文字列の表示には printf の変換指定子とし

て %s を使う。このとき、引数に与えられるポインタが指す先は char 型であることが前提なので、もし int 型の配列に文字列を入れていた場合には正常に表示されなくなる。

Page 25: プログラミング入門2 第6回 基本型、文字列

間違った例このプログラムだと、意図した通りには表示されない。(具体的にどう表示されるかは int型の表現に依存。)

#include <stdio.h>int main (void) { int a [7]; a[0] = ‘L’; a[1] = ‘i’; a[2] = ‘n’; a[3] = ‘\0’; a[4] = ‘u’; a[5] = ‘x’; a[6] = ‘\0’; printf (“%s\n”, &a[0]); return 0;}

( さらに補足 )&a[0] は int へのポインタ型であり、 char 型へのポインタではないので、$ gcc -W -Wall test.cのようにオプションを付けてコンパイルすれば warning が出る。

Page 26: プログラミング入門2 第6回 基本型、文字列

解説この演習室の環境では、’ L’ は int 型の 76 であり、さきほどの int 型の配列 a は、メモリ上では

76 0 0 0 105 0 0 0 110 …

のように並んでいる。すなわち、a[0] a[1] …

‘L’ ‘\0’ ‘\0’ ‘\0’ ‘i’ ‘\0’ ‘\0’ ‘\0’ ‘n’ …

ということである。つまり、この演習室の環境では’ L’ しか表示されなくなる。

Page 27: プログラミング入門2 第6回 基本型、文字列

ポインタについて(後日、ポインタの回にも説明する)

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

&a[0] は配列 a の先頭要素へのポインタであり、 &a[0] の値は、配列 a の先頭要素の番地である。この場合、 100 である。&a[1] は配列 a の 2 番目の要素へのポインタであり、 101 である。 &a[2] は 102である。以下同様。

100 101 102 103 104 105 106番地

Page 28: プログラミング入門2 第6回 基本型、文字列

printf 関数における変換指定子の %s について

‘L’ ‘i’ ‘n’ ‘\0’ ‘u’ ‘x’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

printf (“%s”, &a[1]);が実行されると、 101 番地から、ヌル文字の 1 つ手前までの文字が画面に出力される。つまり、 in が表示される。 printf (“%s”, &a[4]);だと、 ux が表示される。

100 101 102 103 104 105 106番地

Page 29: プログラミング入門2 第6回 基本型、文字列

補足

(参考) printf の変換指定子で float 型用のものがないのも規定の実引数拡張による。

printf 関数において変換指定子として %c を使う場合、引数の型は int 型と書いたが、 char 型でもよい。もしchar 型の式が与えられた場合は、規定の実引数拡張(default argument promotion) により、自動的に int 型に変換される (printf の引数の個数は可変なので ) 。これは本講義の範囲外とし、説明はしない。

Page 30: プログラミング入門2 第6回 基本型、文字列

改行文字改行文字は’ \n’ で表す。‘\n’自体は int 型の数だが、 char 型の変数やchar 型の配列の要素に代入するときは自動的にchar 型の数に変換されてから代入される(暗黙の型変換)。

Page 31: プログラミング入門2 第6回 基本型、文字列

文字列リテラルダブルクォート ” で囲んだものを文字列リテラルという。(例) ” abc” など。これは、 char 型の配列であり、最後にヌル文字が追加されたものである。

‘a’ ‘b’ ‘c’ ‘\0’ ‘d’ ‘e’ ‘\0’

(例) “ abc\0de” は文字列リテラルである。最後にヌル文字が追加されるので、以下のような長さ 7 の char 型の配列である。

Page 32: プログラミング入門2 第6回 基本型、文字列

例(打ち込んで確認)

#include <stdio.h>int main (void) { printf ("abc\0de"); return 0;}

これを実行すると、 abc が表示される( de は表示されない)。

Page 33: プログラミング入門2 第6回 基本型、文字列

文字の読み込み1 文字の読み込みは、 scanf 関数で変換指定子として %c を用いて行う。

#include <stdio.h>int main (void) { char a; printf ("Input characters: "); scanf ("%c", &a); printf ("%c\n", a); return 0;}

%d や %s の場合と違い、 %c の場合は入力文字が改行、空白、タブなどの場合も読み込まれる。

Page 34: プログラミング入門2 第6回 基本型、文字列

文字列の読み込み文字列の読み込みは、 scanf 関数で変換指定子として %s を用いて行う。

#include <stdio.h>int main (void) { char a[7]; printf ("Input characters: "); scanf ("%s", &a[0]); printf ("%s\n", &a[0]); return 0;}

入力文字中に空白文字があると、空白文字の手前までが配列に格納される。

Page 35: プログラミング入門2 第6回 基本型、文字列

scanf 関数における変換指定子の %s について

‘a’ ‘b’ ‘c’ ‘d’ ‘e’ ‘\0’

a[0] a[1] a[2] a[3] a[4] a[5] a[6]

scanf (“%s”, &a[0]);が実行されると、例えば abcde をキーボードから入力した場合、100 番地から 104 番地まで a,b,c,d,e が順番に格納され、 105 番地にヌル文字が格納される。最後にヌル文字が格納されるので、配列のサイズ -1 の長さを超えて入力してはいけない。それ以上入力したらあふれた部分も書きこまれる(これをバッファーオーバーフローという)。 サーバープログラム等でこのようなコードが用いられていると攻撃の対象になるので対処が必要だが、本講義の範囲外とする。

100 101 102 103 104 105 106番地

Page 36: プログラミング入門2 第6回 基本型、文字列

gets 関数空白がある文字列は gets 関数を用いると読み込ませることができる。 gets 関数は改行文字まで読み込み、改行文字をヌル文字に置き換えて配列に格納する。これも配列のサイズを超えた場合にも書きこまれる。 (fgets 関数を用いるとこれに対処できるが、本講義の範囲外とする。)gets が使われていると gcc が警告を出すが、本講義では無視することとする。

#include <stdio.h>int main (void) { char a[10]; gets (&a[0]); printf ("%s\n", &a[0]); return 0;}

Page 37: プログラミング入門2 第6回 基本型、文字列

printf によるデバッグプログラム実行時にセグメントエラー等で停止した場合、gdb などのデバッガを使ってデバッグをするのが一般的だが、もっと原始的なやり方として、 printf を何カ所かに挿入することによってどの位置で停止したかを突き止めるというやり方もある。その際、停止する場所の範囲を半分ずつ狭めていくと効率がよい。場所が特定されたら、次に何が間違っているのかを考えていくことになる。

printf でデバッグする際の注意事項を次のページに記載する。

Page 38: プログラミング入門2 第6回 基本型、文字列

Printf によるデバッグの注意事項

printf が実行されても、すぐ画面に文字が出力されるとは限らず、内部に文字列が溜まったままになる場合がある。対処法としては、 printfの後に、 fflush(stdout);を入れればよい。これにより、内部に溜まった文字列が(あれば)画面に出てくる。次のページに具体例を示す。

Page 39: プログラミング入門2 第6回 基本型、文字列

例#include <stdio.h>int main (void) { printf ("abc"); while (1); return 0;}

左のようなプログラムを実行したとき、 abc という文字列が画面に表示されない場合がある。そのような場合、 fflush(stdout); という関数呼び出しを下のプログラムのように追加すると、強制的に画面に書き出される。

#include <stdio.h>int main (void) { printf ("abc"); fflush(stdout); while (1); return 0;}

Page 40: プログラミング入門2 第6回 基本型、文字列

基本課題1英文をキーボードから入力し、その英文の長さを表示するプログラムを作成せよ。ただし、英字以外の文字(空白やピリオド等)も文字数にカウントする。 gets 関数を使ってよいものとするが、参考課題 1のようにしてもよい。配列を使う場合は十分な長さの配列を宣言して使用せよ。[実行例 ]$ ./a.out英文を入力して下さい : This is a pen.あなたが入力した英文の文字数は 14 です。$

Page 41: プログラミング入門2 第6回 基本型、文字列

基本課題2キーボードから英文を読み取り、逆順に表示するプログラムを書け。十分な長さの配列を宣言して使用せよ。

[実行例 ]$ ./a.out英文を入力してください : This is a pen..nep a si sihT$

Page 42: プログラミング入門2 第6回 基本型、文字列

発展課題1英文をキーボードから入力し、その英文中の単語の数を表示するプログラムを作成せよ。英字以外の文字(空白、ピリオド、コンマ、クエスチョンマーク等)は区切り文字とし、単語数にはカウントしないこととする。

[実行例 ]% ./a.out英文を入力してください : This is a pen.単語数は 4 です。% ./a.out英文を入力してください : Is this a pen?単語数は 4 です。% ./a.out英文を入力してください : How are you? --- I'm fine, thank you.単語数は 8 です。

Page 43: プログラミング入門2 第6回 基本型、文字列

発展課題2

英文をキーボードから読み取り、英字の大文字だけを表示するプログラムを書け。

[実行例 ]$ ./a.out文字列を入力 : Unidentified Flying ObjectUFO$

Page 44: プログラミング入門2 第6回 基本型、文字列

発展課題3キーボードから英文を読み取り、それが回文かどうかを判定するプログラムを作成せよ。ただし、英字 a-z の大文字小文字は区別せず、かつ英字以外の記号(空白、エクスクラメーションマーク等)は無視するものとする。

[実行例 ]英文を入力してください : So many dynamos!So many dynamos! は回文です。

(参考) dynamo は発電機。 dynamos は dynamo の複数形(注意)十分な長さの配列を宣言して用いること。

Page 45: プログラミング入門2 第6回 基本型、文字列

発展課題4

[実行例 1]1 つ目の文字列 : def2 つ目の文字列 : abcdefgdef は abcdefg の部分文字列です。[実行例 2]1 つ目の文字列 : cef2 つ目の文字列 : abcdefgcef は abcdefg の部分文字列ではありません。

文字列を 2 つキーボードから読み取り、 1 つ目の文字列が 2 つ目の文字列の連続した部分文字列になっているかどうかを判定するプログラムを作成せよ。ただし、入力文字列中に空白やタブはないものとする。

Page 46: プログラミング入門2 第6回 基本型、文字列

アルファベットの文字の判定

アルファベットの文字の大小の判定は、 islower, isupper 関数で行う。アルファベット文字かどうかは、islower, isupper のいずれも偽になるかどうかで判定できる。

#include <ctype.h>#include <stdio.h>void hantei (int c) { if (islower(c)) printf ("%c は小文字です \n", c); else if (isupper (c)) printf ("%c は大文字です \n", c); else printf ("%c はアルファベットではありません。\n", c);}

/* 続き */int main (void) { hantei ('a'); hantei ('A'); hantei ('+'); return 0;}

Page 47: プログラミング入門2 第6回 基本型、文字列

大文字から小文字への変換大文字から小文字への変換は tolower 関数を用いる。tolower 関数は、 int 型を引数に受け取り、それが大文字に対応する数の場合、その小文字に対応するint 型の数を返す。大文字以外の場合はそれをそのまま返す。ctype.h を読み込む必要がある。

#include <ctype.h>#include <stdio.h>int main (void) { printf ("%c\n", tolower ('A')); printf ("%c\n", tolower ('a')); printf ("%c\n", tolower ('+')); return 0;}

Page 48: プログラミング入門2 第6回 基本型、文字列

(補足) char 配列の初期化について

char a [1000] = {‘\0’}; char b [1000] = {‘\0’};のように char 配列の初期化をすることによって、すべての要素がヌル文字で初期化されるので便利がよい。(文字列のコピーなどの場合に最後のヌル文字の扱いがやりやすくなるので)

Page 49: プログラミング入門2 第6回 基本型、文字列

参考課題1空白がある(かもしれない)文字列をキーボードから読み取り、表示するプログラムを gets 関数を使用せずに作成せよ。[実行例 ][sasano@localhost 2011]$ ./a.out文字列を入力してください : This is a pen.入力した文字列は This is a pen. です。(ヒント ) 配列を使って、 scanf で変換指定子の %c を用いてwhile 文の中で改行文字を読むまで 1 文字ずつ順番に配列の各要素に格納し、改行文字をヌル文字に置き換えればよい。その後、 printf で変換指定子の %s を使って表示させればよい。(表示部分も 1 文字ずつ while 文で表示させることもできる。)

Page 50: プログラミング入門2 第6回 基本型、文字列

参考課題1 解答例#include <stdio.h>int main (void) { char s[100], c; int i; printf(" 文字列を入力してください : "); for (i=0; i<99; i=i+1) { scanf ("%c", &s[i]); if (s[i] == '\n') break; } s[i] = '\0'; printf (" 入力した文字列は %s です。 \n", &s[0]); return 0;}

Page 51: プログラミング入門2 第6回 基本型、文字列

参考課題2

キーボードから英語の文字列を 1 つ読み取り、その中の英字の大文字をすべて小文字に変換したものを画面に表示するプログラムを作成せよ。英語の大文字以外の文字はそのまま表示せよ。

[実行例 ]文字列を入力してください : This is a pen.this is a pen.

(注意)十分な長さの配列を宣言して用いること。

Page 52: プログラミング入門2 第6回 基本型、文字列

参考課題2 解答例#include <stdio.h>int main (void) { char s[100], c; int i; printf(" 文字列を入力してください : "); for (i=0; i<99; i=i+1) { scanf ("%c", &s[i]); if (s[i] == '\n') break; if (isupper(s[i])) s[i] = tolower (s[i]); } s[i] = '\0'; printf ("%s\n", &s[0]); return 0;}