简体   繁体   中英

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. 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() .

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. That means that when you append characters to str[i] there is no terminating null byte at the end of the string. This causes string functions like strlen and strcpy to potentially read past the end of the array, invoking undefined behavior .

You can fix this by initializing str to all zeros:

char str[100] = {0};

The memset call after copying the string clears it out for subsequent words.

Also, this is not the best use of 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));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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