ページ 11

初心者です.

Posted: 2013年2月20日(水) 13:43
by べっち
超がつくほどC言語の初心者です.あるプログラムで困っています.
"151"が入力されるまでの任意の数字を入力して,逆順に出力するというプログラムというものなのですが,
for文でもwhile文でも移植性のないポインタ関数と警告が出てしまいます.
NULLなら問題はないのですが終了データが数値の場合どのようにすればよいのでしょうか.ご教授のほどよろしくお願いします.

Re: 初心者です.

Posted: 2013年2月20日(水) 13:53
by zxc
  言葉だけで説明するよりも、コードを載せたほうが絶対に分かりやすいですよね。警告なんかも識別できるナンバーごとコピーペーストするのがベターだと思います。  コードを載せる場合はコードタグをご利用ください。

Re: 初心者です.

Posted: 2013年2月20日(水) 17:03
by 初級者
参考になるかどうかは不明です。

コード:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void printReverseNumber(char *s)
{
    if (!*s) {
        return;
    }
    else if (isdigit(*s)) {
        printReverseNumber(s + 1);
        putchar(*s);
    }
}

int main(void)
{
    char str[80];   // サイズは適切に定義すること

    while (1) {
        printf("数字列を入力(151を入力すると終了) > ");
        scanf("%s", str);
        if (strcmp(str, "151") == 0) {
            break;
        }
        printReverseNumber(str);
        putchar('\n');
    }
    return 0;
}

Re: 初心者です.

Posted: 2013年2月20日(水) 19:02
by バグ
うーん・・・いまいち何をしたいのかよくわからないけど、こういうことかな?

コード:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

void printReverseNumber(char* str, int len)
{
	if (--len >= 0)
	{
		char c = *(str + len);
		if (isdigit(c)) putchar(c);
		printReverseNumber(str, len);
		return;
	}
	putchar('\n');
}

int main(void)
{
	char str[80];   // サイズは適切に定義すること

	while (1)
	{
		printf("数字列を入力(151を入力すると終了) > ");
		scanf("%s", str);
		if (strcmp(str, "151") == 0) break;
		printReverseNumber(str, strlen(str));
	}
	return 0;
}

Re: 初心者です.

Posted: 2013年2月21日(木) 09:52
by べっち
ソースも載せるべきでした.申し訳ありません.string.hは使わないように組みたいです.
このプログラムで改善したいところは,①ここのNULLを数値にしたい(151で終了)②入力した文字(数値)を並べて最後にすべて逆順に表示する
という2点です.このままこのプログラムを使うと最後に入力した文字のみが反転されます.
当方C言語初めてまもなくなので変なことを言っているかもしれませんが,ご教授よろしくお願いします.

コード:

# include <stdio.h>

main()
{
	char s[80];
	int i,n=0;

	printf("入力文字:");
	while(gets(s) != NULL){
		printf("入力文字:");
		n++;
    }
	
    for(i=n;i>-1;i--){
	printf("%c",s[i]);
    }
	
    return(0);
}

Re: 初心者です.

Posted: 2013年2月21日(木) 10:18
by みけCAT
NULLの代わりに0を使えば数値にできます。
151で終了するには、

コード:

if(s[0]=='1' && s[1]=='5' && s[2]=='1' && s[3]==0)
という条件文を使えばできます。

文字列を反転するには
1.文字列を走査して最後のNUL文字まで行く
2.そこから1文字戻る
3.その位置の文字を出力し、1文字戻る
4.先頭の文字を出力したら終了
これで半角文字しか入力されないのならいけます。全角の文字が含まれるとちょっと複雑です。
これをgetsしているwhileループの中で実行します。

コード:

#include <stdio.h>

int main(void) {
	char s[80];
	int i;

	printf("入力文字:");
	while(fgets(s,sizeof(s),stdin) != 0) {
		for(i=0;s[i];i++) {
			if(s[i]=='\n') {
				s[i]=0;
				break;
			}
		}
		if(s[0]=='1' && s[1]=='5' && s[2]=='1' && s[3]==0)break;
		for(i--;i>=0;i--)putchar(s[i]);
		putchar('\n');
		printf("入力文字:");
	}

	return 0;
}

Re: 初心者です.

Posted: 2013年2月21日(木) 10:28
by box
べっち さんが書きました:

コード:

	while(gets(s) != NULL){
		printf("入力文字:");
		n++;
    }
1回の文字列入力でnは1しか増えていないです。
string.hを使いたくない(という、私からすれば奇妙な制約)のでしたら、
何とかして自力で文字数をカウントする必要があります。
と書いているうちに、みけCATさんから「自力で文字数をカウントするバージョン」が
出ていましたね。

Re: 初心者です.

Posted: 2013年2月21日(木) 10:33
by みけCAT
べっち さんが書きました:string.hは使わないように組みたいです.
自分でstrcmpを実装するのも手です。

コード:

#include <stdio.h>

int mystrcmp(const char* a,const char* b) {
	while(*a && *b && *a==*b){a++;b++;}
	if(*a>*b)return 1;
	if(*a<*b)return -1;
	return 0;
}

int main(void) {
	char s[80];
	int i;

	printf("入力文字:");
	while(fgets(s,sizeof(s),stdin) != 0) {
		for(i=0;s[i];i++) {
			if(s[i]=='\n') {
				s[i]=0;
				break;
			}
		}
		if(mystrcmp(s,"151")==0)break;
		for(i--;i>=0;i--)putchar(s[i]);
		putchar('\n');
		printf("入力文字:");
	}

	return 0;
}

Re: 初心者です.

Posted: 2013年2月21日(木) 10:37
by みけCAT
ついでに他の関数も実装すると、勉強になるかもしれません。

コード:

#include <stdio.h>

int mystrcmp(const char* a,const char* b) {
	while(*a && *b && *a==*b){a++;b++;}
	if(*a>*b)return 1;
	if(*a<*b)return -1;
	return 0;
}

char* mystrchr(const char* s,int c) {
	while(*s && *s!=c)s++;
	return (*s || c==0)?s:NULL;
}

int mystrlen(const char* s) {
	int count;
	for(count=0;*s;count++)s++;
	return count;
}

int main(void) {
	char s[80];
	int i;

	printf("入力文字:");
	while(fgets(s,sizeof(s),stdin) != 0) {
		char* c=mystrchr(s,'\n');
		if(c)*c=0;
		if(mystrcmp(s,"151")==0)break;
		for(i=mystrlen(s)-1;i>=0;i--)putchar(s[i]);
		putchar('\n');
		printf("入力文字:");
	}

	return 0;
}

Re: 初心者です.

Posted: 2013年2月21日(木) 10:39
by みけCAT
わざわざ実装しなくても、プロトタイプ宣言をすればstring.hをインクルードすることなく関数を利用できます。

コード:

#include <stdio.h>

size_t strlen(const char* s);
int strcmp(const char* s,const char* t);
char* strchr(const char* s,int c);

int main(void) {
	char s[80];
	int i;

	printf("入力文字:");
	while(fgets(s,sizeof(s),stdin) != 0) {
		char* c=strchr(s,'\n');
		if(c)*c=0;
		if(strcmp(s,"151")==0)break;
		for(i=strlen(s)-1;i>=0;i--)putchar(s[i]);
		putchar('\n');
		printf("入力文字:");
	}

	return 0;
}
オフトピック
推奨されませんが、C言語ならプロトタイプ宣言をしなくても関数を利用できるはずです。

Re: 初心者です.

Posted: 2013年2月21日(木) 10:56
by みけCAT
もしかして、やりたいことはこれですか?

コード:

#include <stdio.h>

char* safer_gets(char* s,int size) {
	int i;
	if(!fgets(s,size,stdin))return NULL;
	for(i=0;s[i];i++) {
		if(s[i]=='\n') {
			s[i]=0;
			break;
		}
	}
	return s;
}

char* mystrcat(char* s,const char* t) {
	char* return_s=s;
	while(*s)s++;
	while(*t) {
		*(s++)=*(t++);
	}
	*s=0;
	return return_s;
}

size_t mystrlen(const char* s) {
	size_t len;
	for(len=0;*s;s++)len++;
	return len;
}

int main(void) {
	char s[80]={0};
	char buf[80];
	int i;
 
	printf("入力文字:");
	while(safer_gets(buf,sizeof(buf)) != 0) {
		if(buf[0]=='1' && buf[1]=='5' && buf[2]=='1' && buf[3]==0)break;
		mystrcat(s,buf);
		printf("入力文字:");
	}

	for(i=mystrlen(s)-1;i>-1;i--) {
		printf("%c",s[i]);
	}
	putchar('\n');

	return 0;
}

Re: 初心者です.

Posted: 2013年2月21日(木) 11:20
by べっち
非常に詳細に教えていただきありがとうございます.
このプログラムは教材の問題で(string.hを使わないのもそのためです.)答えがないので悩んでおりました.
やりたいことは,みけCATさんの最後に書かれたものです.うまく伝えられなくて申し訳ありませんでした.
教材は基礎のものなのでまさかこんなに長いプログラムになるとは思いませんでした.C言語は奥が深いですね.

答えていただいた皆様ありがとうございました.