당신은 다양한 유형의 데이터를 저장할 수있는 데이터 유형을 필요가 없습니다.
C의 일반적인 접근 방식은 union
을 사용하는 것으로 동일한 공간에서 여러 유형을 유지할 수 있습니다. 한 번에 하나의 유형 만 사용할 수 있으므로 enum
을 사용하여 활성화 된 유형을 나타내는 방법이 필요합니다. 그런 다음 enum
및 union
을 struct
에 포장하여 서로 가깝게 정리하십시오.
다음은 데이터 유형의 구현 예입니다.그것은 어떤 연산도하지 않으며, 단지 문자열을 파싱하고 토큰을 인쇄합니다.
예에서와 같이 모든 토큰은 공백으로 구분해야 strtok
을 찾을 수 있습니다. 5/2
을 세 개의 토큰으로 인식하려면 Serge Ballesta가 매우 체계적인 대답으로 제안한 것처럼 렉서를 작성할 수 있습니다. 아래 구현은 -1
과 같은 음수를 인식하지 못합니다. 오류 처리도 매우 기본입니다.
이 코드는 여전히 해결책을 출발점으로 서비스를 제공 할 수 :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
enum Type { /* enumeration of possible types */
Operator,
Integer,
Float,
Name,
Illegal
};
struct Token {
enum Type type; /* token type */
union { /* mutually exclusive data fields */
long long int l; /* ... for Integer */
double x; /* ... for Float */
char name[20]; /* ... for Name and Operator */
} data;
};
struct Token illegal(const char *str)
{
struct Token tk = {Illegal};
snprintf(tk.data.name, 20, "%s", str);
return tk;
}
struct Token parse(const char *str)
{
struct Token tk = {Illegal};
if (strchr("+-*/%", *str)) {
if (str[1]) return illegal("Overlong operator");
tk.type = Operator;
strcpy(tk.data.name, str);
return tk;
}
if (isdigit(*str)) {
double x;
long long l;
char *end;
l = strtoll(str, &end, 0);
if (end != str && *end == '\0') {
tk.type = Integer;
tk.data.l = l;
return tk;
}
x = strtod(str, &end);
if (end != str && *end == '\0') {
tk.type = Float;
tk.data.x = x;
return tk;
}
return illegal("Illegal number");
}
if (isalpha(*str)) {
const char *p = str;
while (*p) {
if (!isalnum(*p++)) return illegal("Illegal name");
}
tk.type = Name;
snprintf(tk.data.name, 20, "%s", str);
return tk;
}
return illegal("Illegal character");
}
int split(struct Token tk[], int max, char *str)
{
int n = 0;
char *p;
p = strtok(str, " \t\n");
while (p) {
struct Token curr = parse(p);
if (curr.type == Illegal) {
fprintf(stderr, "Parse error: %s.\n", curr.data.name);
return -1;
}
if (n < max) tk[n] = curr;
n++;
p = strtok(NULL, " \t\n");
}
return n;
}
void print(struct Token tk)
{
switch (tk.type) {
case Operator: printf("operator %c\n", tk.data.name[0]);
break;
case Integer: printf("integer %lld\n", tk.data.l);
break;
case Float: printf("float %g\n", tk.data.x);
break;
case Name: printf("name \"%s\"\n", tk.data.name);
break;
default: printf("illegal token\n");
}
}
int main()
{
char line[] = "- + 2 * alpha beta/12.0 6";
struct Token tk[20];
int i, n;
n = split(tk, 20, line);
for (i = 0; i < n; i++) {
print(tk[i]);
}
return 0;
}
당신은 하나에 2 개 개의 다른 질문을하고 있습니다 : 입력 문자열 및 숫자와 분리 문자 (텍스트의 첫 번째 질문)에서 구문 분석하는 방법과 배열에 저장하는 방법 (제목의 두 번째 질문). 그리고 첫 번째 질문에 올바르게 대답하기에 충분한 문맥을 제공하지 않습니다. 입력에 대한 ** 정확히 ** 귀하의 사양은 무엇입니까? 단 4 개의 연산자와 10 진수 정수? 다중 다중 함수 (1/x 또는 sqrt에 대한 'inv')? 모든 괄호 ('('')')? 소수 자리수 부동 (1.25)? 아니면 정말로 역 연산 4 정수 계산기입니까? 그리고 여러 개의 공백, 탭을 허용합니까? –
실제로 접두사 식 계산기와 같은 것을 구현하고 싶습니다. 난 괄호를 사용하고 싶지 않다. 단지 배열 인덱스를 사용하는 피연산자를 구분하기를 원할 뿐이다. 내 예제 12처럼 두 번째 마지막 인덱스에 저장해야하며 배열의 마지막 인덱스에 6 저장해야합니다. 지금은 그냥 정수를 고려하고 있지만 그것은 부동 소수점에 대한 방법을 제안 할 수 있으면 좋을 것이다. 예 저는 5 명의 연산자 만 사용하고 있습니다. + - * /와 % –