[英]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 . 这会导致诸如
strlen
和strcpy
类的字符串函数可能读取超出数组末尾的位置,从而调用未定义的行为 。
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.