小文字を大文字に

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
さっかん

小文字を大文字に

#1

投稿記事 by さっかん » 18年前

ファイルの読み込みの課題で、小文字を大文字に変換して読み込みたいんですが、toupperの行でエラーが出てしまいます。文字列においての理解不足が原因だと思うのですが、ご教授お願いします。

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int main(void)
{
FILE *fp;
char s[256],ch[256];
int i;
if ((fp = fopen("smpl.txt", "r")) == NULL) {
printf("file open error!!\n");
exit(1);
}
while (fgets(s, 256, fp) != NULL) {
ch=toupper(s);
printf("%s\n",ch);
}
fclose(fp);
return 0;
}

box

Re:小文字を大文字に

#2

投稿記事 by box » 18年前

toupper()には、sの要素を1バイトずつ渡してください。

さっかん

Re:小文字を大文字に

#3

投稿記事 by さっかん » 18年前

for文でs[0]からs[1]、s[2]というように渡せばいいんですか?

box

Re:小文字を大文字に

#4

投稿記事 by box » 18年前

そうです。
今回の場合でしたら、whileループの中にforループを設けて、
sを1文字ずつ大文字に変換した結果をchに1文字ずつセットしていきます。

for (i = 0; s != '\0'; i++)
	ch = toupper(s);
ch = '\0';	// 文字列終端用の'\0'

この後、printf()でchを出力してください。

さっかん

Re:小文字を大文字に

#5

投稿記事 by さっかん » 18年前

うまく実行されました。
わかりやすい説明ありがとうございます!!

さっかん

Re:小文字を大文字に

#6

投稿記事 by さっかん » 18年前

もうひとつ疑問があります。指定したファイルの中身の小文字を大文字にして、別の指定したファイルに書き込むという課題なんですが、fscanfを使わずにこのような書き方にしてみたところ、エラーが出てしまいました。fscanfは絶対に使わなくてはいけないのでしょうか。あと、ファイルの書き込みは初めてなので、他にも書き方の間違えているところがあればご指摘お願いします。
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fp1,*fp2;
char s[256],ch[256];
int i,fname1,fname2;
printf("Input filename:");
scanf("%d",&fname1);
if ((fp1 =fopen("%d",fname1,"r"))==NULL){
printf("file open error!!\n");
exit(1);
}
while(fgets(s,256,fp1)!=NULL){
for (i = 0; s !='\0'; i++){
ch = toupper(s);
}
ch = '\0';
}
fclose(fp1);
printf("Output filename:");
scanf("%d",&fname2);
fp2=fopen("%d",fname2"a+");
for (i = 0; ch !='\0'; i++){
fputs(ch,fp2);
fputs("\n",fp2);
}
fclose(fp2);
return 0;
}

Hermit

Re:小文字を大文字に

#7

投稿記事 by Hermit » 18年前

fopen 関数は、
FILE *fopen(const char *, const char *);
です。
引数はふたつまでで、
引数は共に、文字列で無ければいけません。

fopen("%d",fname1,"r")
3個の引数は多すぎます。
fname1 は、int なので使用できません。

さっかん

Re:小文字を大文字に

#8

投稿記事 by さっかん » 18年前

Hermitさんの言う事を理解したつもりでこのように書き換えてみたのですが、セグメントエラーになってしまいます。全然的外れな事をしているかもしれませんが、ご指摘お願いします。
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fp1,*fp2;
char s[256],ch[256];
char fname1[20],fname2[20];
int i;
printf("Input filename:");
fscanf(fp1,"%s",&fname1);
if ((fp1 =fopen("fname1","r"))==NULL){
printf("file open error!!\n");
exit(1);
}
while(fgets(s,256,fp1)!=NULL){
for (i = 0; s !='\0'; i++){
ch = toupper(s);
}
ch = '\0';
}
fclose(fp1);
printf("Output filename:");
fscanf(fp2,"%s",&fname2);
fp2=fopen("fname2","a+");
for (i = 0; ch !='\0'; i++){
fputs("ch",fp2);
fputs("\n",fp2);
}
fclose(fp2);
return 0;
}

box

Re:小文字を大文字に

#9

投稿記事 by box » 18年前

>   fscanf(fp1,"%s",&fname1);

fscanf()ではなくscanf()で、fname1[/url]に入力ファイル名を格納してください。
fname1の頭にある&は不要です。
また、ここではfp1は不要です。

>   if ((fp1 =fopen("fname1","r"))==NULL){

fname1をダブルクォーテーションで囲むと、「fname1という名前の」ファイルを
オープンしようとします。
今回はそうではなく、fname1という変数に入っている名前のファイルを
オープンするのです。

>   fscanf(fp2,"%s",&fname2);
>   fp2=fopen("fname2","a+");

この2行は、上記と同様に修正してください。

>     fputs("ch",fp2);

ここのダブルクォーテーションも不要です。

さっかん

Re:小文字を大文字に

#10

投稿記事 by さっかん » 18年前

Boxさん、詳しい解説ありがとうございます!でも何故fname1の頭にある&が不要なんでしょうか?
あと、このように書き換えてみたのですが、fputの行でエラー警告があって、試しに実行してみたらOutput filenameでファイル名を入力した後にセグメントエラーになってしまいました。

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fp1,*fp2;
char s[256],ch[256];
char fname1[20],fname2[20];
int i;
printf("Input filename:");
scanf("%s",fname1);
if ((fp1 =fopen(fname1,"r"))==NULL){
printf("file open error!!\n");
exit(1);
}
while(fgets(s,256,fp1)!=NULL){
for (i = 0; s !='\0'; i++){
ch = toupper(s);
}
ch = '\0';
}
fclose(fp1);
printf("Output filename:");
scanf("%s",fname2);
fp2=fopen(fname2,"a+");
for (i = 0; ch !='\0'; i++){
fputs(ch,fp2);
fputs("\n",fp2);
}
fclose(fp2);
return 0;
}

box

Re:小文字を大文字に

#11

投稿記事 by box » 18年前

> 何故fname1の頭にある&が不要なんでしょうか?

配列の変数名は、その配列の先頭要素へのポインタと同義です。
scanf()の第2引数(以降)にchar型の配列(今回の例ではfname1[/url])を指定する場合、
単にfname1と書けば&fname1[0]と同じ意味になります。

>   for (i = 0; ch !='\0'; i++){
>     fputs(ch,fp2);
>     fputs("\n",fp2);
>   }

fputs()の第1引数はchar型へのポインタです。
ここではforループを回す必要はなく、単に
fputs(ch, fp2);
だけでよいのです。
ここでも、「配列の変数名は、その配列の先頭要素へのポインタと同義」を使っています。
上に引用したコードでは、fputs()の第1引数に配列の個別の要素であるchar型を
渡しているため、引数の本来の型と合わず、異常終了するのです。

また、fputs()は自動的に改行しますので、
fputs("\n", fp2);
は不要です。出力のたびに1行空白行をあけるという仕様ならば別ですけれど。

さっかん

Re:小文字を大文字に

#12

投稿記事 by さっかん » 18年前

おかげさまで&が不要な理由がよく理解できました!
fputsのところに気をつけて作り直してみたんですが、chの中身が一回ずつ変わってしまうため、最後に変更された中身しか記憶できてなくて、
読み込むファイルの中身が
pdg
buk
12a
だったとすると、書き込んだファイルの中身が
12A
だけになってしまいました。chは二次元配列にしなければならないのでしょうか?
ちなみに今の状態です↓

#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
int main()
{
FILE *fp1,*fp2;
char s[256],ch[256];
char fname1[20],fname2[20];
int i;
printf("Input filename:");
scanf("%s",fname1);
if ((fp1 =fopen(fname1,"r"))==NULL){
printf("file open error!!\n");
exit(1);
}
while(fgets(s,256,fp1)!=NULL){
for (i = 0; s !='\0'; i++){
ch = toupper(s);
}
ch = '\0';
}
fclose(fp1);
printf("Output filename:");
scanf("%s",fname2);
fp2=fopen(fname2,"a+");
for (i = 0; ch !='\0'; i++){
}
fputs(ch,fp2);
fclose(fp2);
return 0;
}

box

Re:小文字を大文字に

#13

投稿記事 by box » 18年前

こんな流れにしてみてください。
2次元配列を使う必要はありません。


入力ファイル名を得る
入力ファイルをオープンする
   オープンできなければ、エラーメッセージを出力して終了する

出力ファイル名を得る
出力ファイルをオープンする
   オープンできなければ、エラーメッセージを出力して終了する

読むデータがある間、入力ファイルから1行分を得る
   その1行分を大文字に変換する
   大文字に変換した結果を出力ファイルに書き込む

入力ファイルをクローズする
出力ファイルをクローズする
おしまい

さっかん

Re:小文字を大文字に

#14

投稿記事 by さっかん » 18年前

2つ一気にオープンすればよかったんですね!
おかげさまで完成しました♪
Hermitさん、boxさんありがとうございました!!

閉鎖

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