こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

大学のプログラミング課題について

大学でプログラミングの課題が出たのですが、よくわからないので
詳しく教えてほしいです。

問題
99文字までの文字列を入力し,アルファベットの小文字は大文字に,アルファベットの大文字は小文字に,またアルファベット以外の文字はアスタリスク’*’に変換した文字列を出力するプログラムを作成せよ
実行結果は
99文字以下の文字列を入力してください.abcABC123sDFgh#"x32YY=
変換された文字列はABCabc***SdfGH**X**yy*です.

というようになるはずなのですが、うまくいきません。

私が考えたのは
#include <stdio.h>
int main(void)
{
int i,j;
char t[100],u;
printf("99文字以下の文字列を入力してください");
scanf("%s",t);

printf("変換された文字列は");

for(i=0;t[i]>0;i++);
{
}
for(j=0;j<=i;j++);
{
if(t[j]>=65 && t[j]<=90)
{
u=t[j]+32;
printf("%c",u);
}
else if(t[j]>=97 && t[j]<=122)
{
u=t[j]-32;
printf("%c",u);
}
else
{
u='*';
printf("%c",u);
}
}
printf("です\n");

}

というものです。
ちなみに、他のライブラリ関数は使わないで作らないといけません。

どこが間違っているのかも含めて
教えていただけると嬉しいです。

投稿日時 - 2010-12-01 17:12:45

QNo.6356162

困ってます

質問者が選んだベストアンサー

「どこが間違っているのかも含めて教えていただけると嬉しいです。」

↓、for()にセミコロンが付いているんでここで区切ってしまってます。これで完結してますよ。また、{} が離れちゃって別物になり下がってます。 意味ないですね。
  for(i=0;t[i]>0;i++);
  {
  }


それから10進コードもいいですが、これじゃ作ったあなた自身も後でアスキー一覧表見なきゃわからんでしょ?
  if(t[j]>=65 && t[j]<=90)
  {


それから、手間暇かけて if()毎に1字出力するのも良いけど、見づらくありませんか。見づらいということは思考にも影響し、考えにくくするものです。
  if(t[j]>=65 && t[j]<=90){
   u=t[j]+32;
   printf("%c",u);
  }


これを踏まえて、習った for()文を使って処理を「入力~処理~出力」に別けて見易いプログラムにします。

#include <stdio.h>
#define SIZE 100 //プログラム本体をいじらなくて済みますよね

int main(void)
{
int i,c;
char t[SIZE];

//入力
printf("%d文字以下の文字列を入力してください ", SIZE-1);
scanf("%s",t);

//処理
for(i=0;i<SIZE;i++){ //文字配列内を添字i が移動するようにします
c=t[i]; //1文字取り出します。
if(c=='\0'){ //ただし、その文字が終わりなら for()文を脱出します。
break;
}
if(c>='A' && c<='Z'){ //文字がA~Zなら小文字に
t[i]=t[i]+32;
}else if(c>='a' && c<='z'){ //文字がa~zなら大文字に
t[i]=t[i]-32;
}else{
t[i]='*';
}
}

//結果の出力(変更を加えた文字列をまとめて出力)
printf("変換された文字列は「 %s 」です。\n",t);

return 0;
}




for()文の文字配列の意味がわかったら、ポインターも考えてみてください。

/* 回答2.ポインター版 */
#include <stdio.h>
#define SIZE 100

int main(void)
{
int i,c;
char t[SIZE],*p;

printf("%d文字以下の文字列を入力してください ", SIZE-1);
scanf("%s",t);

//処理
p=t;
while((c=*p)!='\0'){ //while(c=*p){
if(c>='A' && c<='Z'){
*p+=32;
}else if(c>='a' && c<='z'){
*p-=32;
}else{
*p='*';
}
p++;
}

//結果の出力
printf("変換された文字列は「 %s 」です。\n",t);

return 0;
}

投稿日時 - 2010-12-04 19:34:18

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(12)

ANo.11

>#10

分かってますって。
ツッコミじゃなくて、VCは対応してないってことを言いたかっただけだから許して^^;

投稿日時 - 2010-12-02 13:10:37

ANo.10

もちろん VC でダメなのはわかりきっています>#7.
質問文中「stdio.h」とあることから (C++ や C# などではなく) C を対象としているところ, 処理系を特定していない以上 JIS C の範囲が許容されるだろうことを前提に書いたものなので.

投稿日時 - 2010-12-02 12:34:20

ANo.9

>どこが間違っているのかも含めて教えていただけると嬉しいです。

 たった1ヶ所、十数行目の

for(j=0;j<=i;j++);

の末尾、; をとるだけで、お望みの動作をするプログラムとなります。
; があると for 構文はそこで完結です。

直前の

for(i=0;t[i]>0;i++);
{
}
の for 構文も最初の行で完結し、i という「入力文字列長」が求まっています。
ここの( ; の後ろの){ } は、コンパイラにとって「空白」みたいなもんです。

投稿日時 - 2010-12-02 06:09:36

ANo.8

>for(i=0;t[i]>0;i++);
この書き方はひどい

投稿日時 - 2010-12-02 01:06:01

> #6

VC++ 2010 はダメみたい。 C99

投稿日時 - 2010-12-02 00:37:43

ANo.6

例えば
#include <stdio.h>
#include <limits.h>

int main()
{
char t[100];
printf("99文字以下の文字列を入力してください");
scanf("%99s",t);

printf("変換された文字列は");
for (const char *p = t; *p; ++p) {
static const char translate[1u << CHAR_BIT] = {
['a'] = 'A', ['b'] = 'B', ... /* 以下略 */
};
char ch;
printf("%c", (ch = translate[*p]) ? ch : '*');
}
printf("です\n");
return 0;
}
で OK... かな?

投稿日時 - 2010-12-01 23:42:38

ANo.5

#4です。
頭が抜けていた。

#include <stdio.h>
//#include <ctype.h>/*ほかの関数を使ってよければ*/

これを頭につけて。

投稿日時 - 2010-12-01 20:34:08

ANo.4

「他のライブラリ関数は使わないで」
というし、演習で、実用的なものでもないので、scanfで練習するするから、
下記でいいでしょう。

自分のと比べれば理解できるでしょう。

int main(void)
{
int i;
char t[100];

printf("99文字以下の文字列を入力してください");
scanf("%99s",t);/*文字数制限?*/


for(i=0;i<100;i++){
if(t[i]=='\0')/*文字列の終わりなら抜ける*/
break;
//else if(isupper(t[i]))/*ここから4行のほかの関数を使えば、文字コードは関係ない/*
//t[i]=tolower(t[i]);
//else if(islower(t[i]))
//t[i]=toupper(t[i]);

if(t[i]>=65 && t[i]<=90)/*上の関数を使うなら、ここから4行はコメントアウトにする*/
t[i]+=32;
else if(t[i]>=92 && t[i]<=122)
t[i]-=32;
else
t[i]='*';

printf("%d %c\n",i,t[i]);
}

printf("変換された文字列は");
printf("%sです\n",t);

return 0;/*mainがintを返すから

}

投稿日時 - 2010-12-01 20:31:57

ANo.3

Wr5

>for(i=0;t[i]>0;i++);
の空ループと、その直後の空ブロックって必要ですか?

文字を精査するループの継続条件を t[i] != '\0'(ループカウンタに使う変数がiの場合)にすればイイだけかと。

で、掲示されたコードでは……
「変換された文字列は*です。」
としか表示されませんね?
何を入力したとしても。(文字列終端の'\0'を'*'に変換した結果です。)
>for(j=0;j<=i;j++);
は空ループになっていますから…。

>if(t[j]>=65 && t[j]<=90)

マジックナンバーは避けた方がいいかと思われます。
# ASCIIコード以外の環境では正しく動作しません。
scanf()でASCII以外(日本語とか全角な記号とか)を入力した場合も壊れますかね…

>scanf("%s",t);

何文字でも入力できてしまいます。(バッファオーバーランになります)
せめて
scanf("%99s",t);
くらいにはしましょう。

投稿日時 - 2010-12-01 17:46:19

ANo.2

 
 文字コードの決め打ちはよくない。
 
 A~Z、a~zの文字コードがこの順に並んでいること、
大文字と小文字のコードの差が32であることは、
保証されていない。
 

投稿日時 - 2010-12-01 17:39:10

ANo.1

で、どんな結果になるのですか?
それが判らないとコメントのしようがないです。

投稿日時 - 2010-12-01 17:16:11

あなたにオススメの質問