简体   繁体   English

除非我调用printf()函数,否则C代码会卡住

[英]C code gets stuck unless I call printf() function

I have a code that reads text file, tokenizes words in it, then selects only unique words from text, concatenates them and prints them using puts() function. 我有一个代码可以读取文本文件,对其中的单词进行标记,然后仅从文本中选择唯一的单词,然后将它们连接起来并使用puts()函数进行打印。 Here is full code: 这是完整的代码:

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

char str_array[100][100];
char output[100];

void concatenate(int index)
{
  // compares output with empty string
  if (!strcmp(output, "")) 
  {
    strcpy(output, str_array[index]);
  }

  else //else existing string is contcatenated
  {
    strcat(output, " "); // add space
    strcat(output, str_array[index]);
  }
}

void unique_selection(char file[])
{
  FILE *F = fopen(file, "r");
  char ch; char str[100];
  int i=0, j=0;

  while ((ch=getc(F)) != EOF) 
  {
    // if space or newline is detected i.e. word is finished
    if (ch == ' ' || ch == '\n') 
    {
      //traverse array of strings
      for(int x=0; x<j; x++)
      {
        //if current str is already in array, skip appending
        if (!strcmp(str_array[x], str)) goto ELSE; 
      }
      strcpy(str_array[j], str);
      j++;
    ELSE:
      i=0;
      memset(str, 0, strlen(str));
    }
    else //otherwise chars of a word get appended to string array
    {
      str[i] = ch;
      i++;
    }
  }

  for(int k=0; k<j; k++)
  {
    concatenate(k);
  }
  puts(output);
  fclose(F);
}

int main(void) {
  char file[] = "test.txt";
  //printf("Output:");
  unique_selection(file);
  return 0;
}

The code works perfectly, but I came across a weird issue, every time I tried printing the output string (using puts() or printf("%s") the program would get stuck, similarly to what happens when loop is iterating forever. And weirdly this issue was fixed by putting the printf before the function call. If I remove puts() from function, code runs like normal even with or without the printf in main() . 该代码可以正常工作,但是每次遇到尝试打印输出字符串(使用puts()printf("%s") ,程序都会卡住,这与循环永远迭代时发生的情况类似,但我遇到了一个奇怪的问题。奇怪的是,通过将printf放在函数调用之前解决了这个问题,如果我从函数中删除puts() ,即使main()有或没有printf,代码也可以正常运行。

Why is this happening? 为什么会这样呢?

This is where you go wrong: 这是您出问题的地方:

else //otherwise chars of a word get appended to string array
{
  str[i] = ch;
  i++;
}

When you first enter the main loop, str is uninitialized. 首次进入主循环时, str未初始化。 That means that when you append characters to str[i] there is no terminating null byte at the end of the string. 这意味着当您将字符追加到str[i]时,字符串末尾没有终止的空字节。 This causes string functions like strlen and strcpy to potentially read past the end of the array, invoking undefined behavior . 这会导致诸如strlenstrcpy类的字符串函数可能读取超出数组末尾的位置,从而调用未定义的行为

You can fix this by initializing str to all zeros: 您可以通过将str初始化为全零来解决此问题:

char str[100] = {0};

The memset call after copying the string clears it out for subsequent words. 复制字符串后的memset调用将其清除以清除后续单词。

Also, this is not the best use of goto : 另外,这不是goto的最佳用法:

  for(int x=0; x<j; x++)
  {
    //if current str is already in array, skip appending
    if (!strcmp(str_array[x], str)) goto ELSE; 
  }
  strcpy(str_array[j], str);
  j++;
ELSE:
  i=0;
  memset(str, 0, strlen(str));

It would be cleaner to set a flag if your search was successful and act on that when you exit the loop: 如果您的搜索成功,则设置一个标志会更干净,并在退出循环时对此进行操作:

  int found = 0;
  for(int x=0; x<j; x++)
  {
    //if current str is already in array, skip appending
    if (!strcmp(str_array[x], str)) {
        found = 1;
        break;
    }
  }
  if (found) {
    strcpy(str_array[j], str);
    j++;
  }
  i=0;
  memset(str, 0, strlen(str));
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM