|
「かなりの初心者」に出す問題ではないような。。。
まあでも、
>・つくる関数はmainのみ
ということは初心者向きのつもりなのかな。
#何か邪悪な意図があるのかもしれないけど
#実際は関数に分けた方が簡単だし。
というわけで関数に分けると↓になりました。
と言っても最初全部main()に書いてたのをバラしただけなので、
再びmain()に入れ直すのはそんなに難しくないと思います。
gotoだらけになるかもしれませんが(ヒントだよ)、それはこんな問題を出す方が悪いのです。
#include <stdio.h>
#include <string.h>
#include <ctype.h>
/*
* スペースやタブを詰める
*/
void delete_space(char *dest, const char *src)
{
int i, j;
for (i = j = 0; i < strlen(src) + 1; i++, j++) {
while (isspace(src[i])) {
i++;
}
dest[j] = src[i];
}
}
/*
* 変数かどうか調べる
*/
int isidentifier(char *token)
{
int i;
if (!isalpha(token[0]))
return 0;
for (i = 1; i < strlen(token); i++) {
if (!isalnum(token[i]))
return 0;
}
return 1;
}
/*
* 数字かどうか調べる
*/
int isnumberstr(char *token)
{
int i, pointflg = 0, len = strlen(token);
if (!isdigit(token[0]) || !isdigit(token[len-1]))
return 0;
for (i = 1; i < len - 1; i++) {
if (!isdigit(token[i])) {
if (!pointflg && token[i] == '.') {
pointflg = 1;
} else {
return 0;
}
}
}
return 1;
}
/*
* 最初の演算子までの長さを求める
*/
int get_token_len(char *str, char *separator)
{
if (strpbrk(str, separator) != NULL) {
return strpbrk(str, separator) - str;
} else {
return strlen(str);
}
}
int main(void)
{
char buf[1024];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
char buf_clone[1024] = "";
char *token_head = buf_clone, *flg_end_key;
int operator_idx;
if ((flg_end_key = strstr(buf, "END")) != NULL) {
*flg_end_key = '\0';
}
delete_space(buf_clone, buf);
printf("\n");
for (token_head = buf_clone ; token_head[0] != '\0'; token_head
+= operator_idx + 1) {
char token[100] = "", operator[] = "+-*/";
int ch;
operator_idx = get_token_len(token_head, operator);
/* (演算子以外の)トークンを切り出す */
strncpy(token, token_head, operator_idx);
/* 演算子以外のトークンを処理 */
if (strlen(token) > 0) {
if (isnumberstr(token)) {
printf("NUMBER");
} else if (isidentifier(token)) {
printf("IDENT");
} else {
break;
}
printf(" %s\n", token);
}
/* 演算子の名前を表示する */
ch = token_head[operator_idx];
printf(ch == '+' ? "PLUS\n" :
ch == '-' ? "MINUS\n" :
ch == '*' ? "ASTERISK\n" :
ch == '/' ? "SLASH\n" : "");
}
if (token_head[0] != '\0') {
fprintf(stderr, "\nerror\n\n");
continue;
}
printf("%s\n\n", flg_end_key == NULL ? "BN" : "END");
}
return 0;
}
>ただしキーワードとして「END」が来れば終了。
>すべて処理したら次の行を入力。
>* TAB,スペースは無視
は、解釈に困りましたが、
1.空白がある場合は、空白がない−ほかの部分は同じ−文字列の場合と全く同じ結果になる
2.ENDが来た時点で処理を終えて(ENDと出力して)入力待ち
としています。
あと、
(例) 1.0 + a - [Return]
はエラーにならないようですので、
エラーになるのは、一つのトークンでエラーが見つかったときだけにしました。だから、
////**
のような入力はエラーになりません。
#strtok()を使っていないのはこういうことがやりにくいから
間違ってたらその辺もなおしてください
|