如何避免使用全局变量?
How can I avoid using a global variable?
可以使用全局变量吗?我正在使用一个全局变量,我知道这并不理想。看起来像这样
int result2 = 0;
void setresult2(int a) {
result2 = a;
}
我在我的自定义语法中使用了变量 shell:
expr(A) ::= IF LSBR expr(B) RSBR SEMICOLON THEN expr(C) SEMICOLON FI. { setresult2(B); A=C; }
现在我想知道是否有比使用全局变量更好的方法?
完整代码可在 my github 上获得。全局变量的目的是处理 shell 扩展和 shell 脚本中的 if 语句,以便我的 shell 可以读取和执行 if 语句。
context 中的代码是对使用更新全局变量的语法的 if 语句的解析,这是语法与我的 C:
之间进行通信的唯一方式
char *if_execute(char *shellcommand) {
char mystring[CMD_LEN];
void *pParser;
char *c;
int reti;
shellcommand = str_replace(shellcommand, ";", " ; ");
reti = regcomp(®ex, "[0-9]==[0-9]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, shellcommand, 0, NULL, 0);
if (!reti) {
shellcommand = str_replace(shellcommand, "==", " == ");;
}
else if (reti == REG_NOMATCH) {
/* puts("No match"); */
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
char *line = strcpy(mystring, shellcommand);
pParser = (void *) ParseAlloc(malloc);
if (line) {
char *buf[64];
struct SToken v[32];
int value;
char **ptr1 = str_split(buf, line, ' ');
int j = 0;
for (j = 0; ptr1[j]; j++) {
c = ptr1[j];
char *c2 = strdup(c);
if (c2 == NULL) {
perror("strdup");
exit(EXIT_FAILURE);
}
v[j].token = c2;
switch (*c2) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (value = 0; *c2 && *c2 >= '0' && *c2 <= '9'; c2++)
value = value * 10 + (*c2 - '0');
v[j].value = value;
Parse(pParser, INTEGER, &v[j]);
continue;
}
if (!strcmp("if", c)) {
Parse(pParser, IF, NULL);
}
else if (!strcmp("true", c)) {
Parse(pParser, TRUE, NULL);
}
else if (!strcmp("then", c)) {
Parse(pParser, THEN, NULL);
char *token = "then ";
const char *p1 = strstr(shellcommand, token) + strlen(token);
const char *p2 = strstr(p1, ";");
if (p2 == NULL) {
// TODO: Handle it
}
size_t len = p2 - p1;
char *res = (char *) malloc(sizeof(char) * (len + 1));
if (res == NULL) {
fprintf(stderr, "malloc failed!\n");
}
strncpy(res, p1, len);
res[len] = '[=11=]';
if (result2)
shellcommand = res;
else
shellcommand = "echo";
}
else if (!strcmp("[", c)) {
Parse(pParser, LSBR, NULL);
}
else if (!strcmp("]", c)) {
Parse(pParser, RSBR, NULL);
}
else if (!strcmp(";", c)) {
Parse(pParser, SEMICOLON, NULL);
}
else if (!strcmp("fi", c)) {
Parse(pParser, FI, NULL);
}
else if (strlen(c) > 0 && strstr(c, "==")) {
v[j].token = c;
Parse(pParser, EQEQ, &v[j]);
}
else {
Parse(pParser, FILENAME, NULL);
}
}
Parse(pParser, 0, NULL);
}
return shellcommand;
}
我不是专家,但通常答案很简单。
如果您不想使用全局变量(这通常是个好主意),那么您需要将局部变量作为对要在其中使用它的函数的引用并更新调用函数
(通常在 main() 中)。
我会说 "member variables" 在您的代码的非通用部分可能没问题。例如。
static int member_var1 = 0;
int get_var1(void)
{
return member_var1;
}
"static" 关键字将确保您的成员变量保持为成员变量,而不是成为 global 变量。
那么下一个问题就是如何识别什么是泛型代码,什么不是。我不确定是否有任何防弹方法。您的主文件很少有重用或超载的意义。 (所以继续将 member 变量放入其中。)
对于其他任何事情,我更喜欢这样的东西:
struct my_state
{
int var1;
}
int do_some_function(struct my_state* state, int some_value)
{
state->var1 = 0;
}
可以使用全局变量吗?我正在使用一个全局变量,我知道这并不理想。看起来像这样
int result2 = 0;
void setresult2(int a) {
result2 = a;
}
我在我的自定义语法中使用了变量 shell:
expr(A) ::= IF LSBR expr(B) RSBR SEMICOLON THEN expr(C) SEMICOLON FI. { setresult2(B); A=C; }
现在我想知道是否有比使用全局变量更好的方法?
完整代码可在 my github 上获得。全局变量的目的是处理 shell 扩展和 shell 脚本中的 if 语句,以便我的 shell 可以读取和执行 if 语句。
context 中的代码是对使用更新全局变量的语法的 if 语句的解析,这是语法与我的 C:
之间进行通信的唯一方式char *if_execute(char *shellcommand) {
char mystring[CMD_LEN];
void *pParser;
char *c;
int reti;
shellcommand = str_replace(shellcommand, ";", " ; ");
reti = regcomp(®ex, "[0-9]==[0-9]", 0);
if (reti) {
fprintf(stderr, "Could not compile regex\n");
exit(1);
}
/* Execute regular expression */
reti = regexec(®ex, shellcommand, 0, NULL, 0);
if (!reti) {
shellcommand = str_replace(shellcommand, "==", " == ");;
}
else if (reti == REG_NOMATCH) {
/* puts("No match"); */
}
else {
regerror(reti, ®ex, msgbuf, sizeof(msgbuf));
fprintf(stderr, "Regex match failed: %s\n", msgbuf);
exit(1);
}
char *line = strcpy(mystring, shellcommand);
pParser = (void *) ParseAlloc(malloc);
if (line) {
char *buf[64];
struct SToken v[32];
int value;
char **ptr1 = str_split(buf, line, ' ');
int j = 0;
for (j = 0; ptr1[j]; j++) {
c = ptr1[j];
char *c2 = strdup(c);
if (c2 == NULL) {
perror("strdup");
exit(EXIT_FAILURE);
}
v[j].token = c2;
switch (*c2) {
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
for (value = 0; *c2 && *c2 >= '0' && *c2 <= '9'; c2++)
value = value * 10 + (*c2 - '0');
v[j].value = value;
Parse(pParser, INTEGER, &v[j]);
continue;
}
if (!strcmp("if", c)) {
Parse(pParser, IF, NULL);
}
else if (!strcmp("true", c)) {
Parse(pParser, TRUE, NULL);
}
else if (!strcmp("then", c)) {
Parse(pParser, THEN, NULL);
char *token = "then ";
const char *p1 = strstr(shellcommand, token) + strlen(token);
const char *p2 = strstr(p1, ";");
if (p2 == NULL) {
// TODO: Handle it
}
size_t len = p2 - p1;
char *res = (char *) malloc(sizeof(char) * (len + 1));
if (res == NULL) {
fprintf(stderr, "malloc failed!\n");
}
strncpy(res, p1, len);
res[len] = '[=11=]';
if (result2)
shellcommand = res;
else
shellcommand = "echo";
}
else if (!strcmp("[", c)) {
Parse(pParser, LSBR, NULL);
}
else if (!strcmp("]", c)) {
Parse(pParser, RSBR, NULL);
}
else if (!strcmp(";", c)) {
Parse(pParser, SEMICOLON, NULL);
}
else if (!strcmp("fi", c)) {
Parse(pParser, FI, NULL);
}
else if (strlen(c) > 0 && strstr(c, "==")) {
v[j].token = c;
Parse(pParser, EQEQ, &v[j]);
}
else {
Parse(pParser, FILENAME, NULL);
}
}
Parse(pParser, 0, NULL);
}
return shellcommand;
}
我不是专家,但通常答案很简单。 如果您不想使用全局变量(这通常是个好主意),那么您需要将局部变量作为对要在其中使用它的函数的引用并更新调用函数 (通常在 main() 中)。
我会说 "member variables" 在您的代码的非通用部分可能没问题。例如。
static int member_var1 = 0;
int get_var1(void)
{
return member_var1;
}
"static" 关键字将确保您的成员变量保持为成员变量,而不是成为 global 变量。
那么下一个问题就是如何识别什么是泛型代码,什么不是。我不确定是否有任何防弹方法。您的主文件很少有重用或超载的意义。 (所以继续将 member 变量放入其中。)
对于其他任何事情,我更喜欢这样的东西:
struct my_state
{
int var1;
}
int do_some_function(struct my_state* state, int some_value)
{
state->var1 = 0;
}