Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/72.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C Printf in循环在没有初始print语句的情况下不工作_C - Fatal编程技术网

C Printf in循环在没有初始print语句的情况下不工作

C Printf in循环在没有初始print语句的情况下不工作,c,C,我正在尝试用C编写一个非常基本的lexer,并拥有以下代码,该代码应该只执行以下操作: 输入:“12 142 123” 输出: NUMBER -- 12 NUMBER -- 14 NUMBER -- 123 但是,我遇到了一个问题,如果在循环输入之前没有包含初始的printf(“”语句,那么我将得到如下输出: 输出: 其中第一个数字为空。我真的很困惑,为什么会发生这种情况,我真的很感谢一些帮助 我有以下代码(省略了一些不相关的函数) 在number中,arr是一个局部变量。局部变量在其函数结束

我正在尝试用C编写一个非常基本的lexer,并拥有以下代码,该代码应该只执行以下操作:

输入:
“12 142 123”

输出:

NUMBER -- 12
NUMBER -- 14
NUMBER -- 123
但是,我遇到了一个问题,如果在循环输入之前没有包含初始的
printf(“”
语句,那么我将得到如下输出: 输出:

其中第一个数字为空。我真的很困惑,为什么会发生这种情况,我真的很感谢一些帮助

我有以下代码(省略了一些不相关的函数)


number
中,
arr
是一个局部变量。局部变量在其函数结束时被销毁,其内容不可预测。尽管如此,您的程序还是使用
标记中的指针打印其值

打印的值不可预测。额外的
printf(“”)
语句可能会导致编译器重新排列代码,使变量不会被覆盖,或者类似的情况。你不能依赖它

您还有几个其他选项可以为每个令牌分配内存:

  • token
    中更改
    str
    ,使其成为字符数组而不是指针。然后每个令牌都有自己的空间来存储字符串
  • 使用
    malloc
    分配字符串。然后它会一直保持分配状态,直到您释放它
  • main
    中创建数组,使其对
    next
    print\u-tok
    都有效。您必须给
    next
    一个指向数组的指针,以便它知道应该将字符串存储在哪里。这将一次只存储一个令牌的字符串
  • 基本上,除了在
    next
    中将数组作为局部变量之外,还可以使用任何其他方法创建数组
  • 使指针指向标记在原始字符串中的位置。在
    Token
    中添加另一个变量,用于存储令牌的长度

我认为第一个选项最简单,最后一个选项使用的内存最少,但为了完整性,我还包括了一些其他选项。

number
中,
arr
是一个局部变量。局部变量在其函数结束时被销毁,其内容不可预测。尽管如此,您的程序还是使用
标记中的指针打印其值

打印的值不可预测。额外的
printf(“”)
语句可能会导致编译器重新排列代码,使变量不会被覆盖,或者类似的情况。你不能依赖它

您还有几个其他选项可以为每个令牌分配内存:

  • token
    中更改
    str
    ,使其成为字符数组而不是指针。然后每个令牌都有自己的空间来存储字符串
  • 使用
    malloc
    分配字符串。然后它会一直保持分配状态,直到您释放它
  • main
    中创建数组,使其对
    next
    print\u-tok
    都有效。您必须给
    next
    一个指向数组的指针,以便它知道应该将字符串存储在哪里。这将一次只存储一个令牌的字符串
  • 基本上,除了在
    next
    中将数组作为局部变量之外,还可以使用任何其他方法创建数组
  • 使指针指向标记在原始字符串中的位置。在
    Token
    中添加另一个变量,用于存储令牌的长度

我认为第一个选项最简单,最后一个选项使用的内存最少,但为了完整性,我还包括了一些其他选项。

Token ret={NUMBER,(char*)arr}您正在使用指向局部变量的指针。您需要
malloc
string+term的空格并进行复制。您描述的内容到处都是未定义的行为。
Token ret={NUMBER,(char*)arr}您正在使用指向局部变量的指针。您需要
malloc
string+term的空格并进行复制。您描述的内容都有未定义的行为。谢谢,这很有意义。解决方案是为结构分配非本地内存,然后返回指针吗?或者在这种情况下还有其他首选方法吗?@mlz7您可以:(1)“malloc”字符数组(并将其释放到其他地方),(2)在main中局部声明arry(或作为全局变量…),并将其作为参数传递给
number
,(3)也许最快的解决方案就是使用
static
存储在
number
中,这样阵列的生命周期就是整个生命周期中的一个program@mlz7第一种解决方案更“通用”,因为它也适用于多线程环境。无论如何,如果您的应用程序是单线程的,那么解决方案2和解决方案3可以成为第三个最快的解决方案。@mlz7不客气。Ps:这个答案会很好,如果它还包含一些关于如何解决问题的建议(代码部分似乎与OP的代码完全相同),那么它将获得我的UV。如果你愿意,你可以修改我的评论。谢谢,这很有意义。解决方案是为结构分配非本地内存,然后返回指针吗?或者在这种情况下还有其他首选方法吗?@mlz7您可以:(1)“malloc”字符数组(并将其释放到其他地方),(2)在main中局部声明arry(或作为全局变量…),并将其作为参数传递给
number
,(3)也许最快的解决方案就是使用
static
存储在
number
中,这样阵列的生命周期就是整个生命周期中的一个program@mlz7第一种解决方案更“通用”,因为它也适用于多线程环境。无论如何,如果您的应用程序是单线程的,那么解决方案2和解决方案3可以成为第三个最快的解决方案。@mlz7不客气。附言:这个答案会很好,如果它也包含一些糖,我的紫外线会增加
NUMBER --
NUMBER -- 14
NUMBER -- 123
#define MAX_LEN 400

char* input;
char* ptr;

char curr_type;
char curr;

enum token_type {
  END,
  NUMBER,
  UNEXPECTED
};

typedef struct {
  enum token_type type;
  char* str;
} Token;
  
void print_tok(Token t) {
  printf("%s -- %s\n", token_types[t.type], t.str);
}

char get(void) {
  return *ptr++;
}

char peek(void) {
  return *ptr;
}

Token number(void) {
  char arr[MAX_LEN];
  arr[0] = peek();
  get();
  int i = 1;
  while (is_digit(peek())) {
    arr[i] = get();
    ++i;
  }
  arr[++i] = '\0';
  Token ret = {NUMBER, (char*)arr};
  return ret;
}

Token unexpected(void) {
  // omitted
}

Token next(void) {
  while (is_space(peek())) get();

  char c = peek();
  switch (peek()) {
    case '0':
    // omitted
    case '9':
      return number();
    default: 
      return unexpected();
  }
}

int main(int argc, char **argv) {
  printf(""); // works fine with this line

  input = argv[1];
  ptr = input;

  Token tokens[MAX_LEN];
  Token t;
  int i = 0;
  do {
    t = next();
    print_tok(t);
    
    tokens[i++] = t;

  } while (t.type != END && t.type != UNEXPECTED);

  return 0;
}