#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINE 1000
#define MAX_QUERY 100
int read_lines(char line[MAX_LINE]);
int print_lines(char query[MAX_LINE]);
int
main(int argc,char *argv[]){
char query[MAX_QUERY];
strcpy(query, argv[1]);
printf("SO: query = %s\n", query);
printf("---\n");
print_lines(query);
return 0;
}
int
read_lines(char line[MAX_LINE]){
int line_len = 0;
int c;
while ((c = getchar()) != EOF){
if(c == '\n'){
break;
}
else{
line[line_len] = c;
line_len ++;
}
}
line[line_len] = '\0';
if(c == EOF && line_len == 0)
return EOF;
printf("%s\n",line);
return line_len;
}
int
print_lines(char query [MAX_QUERY]){
int line_num = 0;
int query_len = strlen(query);
int line_len = 0,i,y,z = 0, position,c = 0;
int limit = query_len > line_len ? line_len : query_len;
double score = 0, maximum;
char score_list[15] = "";
char line[MAX_LINE];
while((line_len = read_lines(line)) != EOF){
c = 0;
line_num ++;
printf("S1: line %d, bytes = %d \n",line_num,line_len);
/* Loops through the query and line and compares the characters
* If it is the same, it adds to the score
* Once it gets to different character the score is reset
*/
for (i = 0; i < limit; i++){
for (y = 0; y < limit; y++){
if (query[i] == line[y]){
score++;
}
else if(score != 0 && query[i] != line[y]){
score_list[z] = score;
z++;
}
}
}
/* Finds the largest score in the array
*/
maximum = score_list[0];
for (position = 1; position < 15; position++){
if (score_list[position] > maximum){
maximum = score_list[position];
}
}
/* resets the score list back to zero
*/
while (c < 15){
score_list[c] = 0;
c++;
}
printf("S2: line %d, score = %f\n",line_num,maximum);
printf("---\n");
}
return 0;
}
代码读取一个查询,例如“fall down”,并检查它是否在行中,并根据匹配的字符数对它们进行评分。然而。我一直只打印出 0 分,当我通过循环打印字符串时,短语会在不应该出现的地方重复出现。我的 read_lines 函数逐行从 stdin 读取文本文件并返回字节大小。我怎样才能让评分工作并修复比较循环?
输出应该是
Down, down, down. Would the fall NEVER come to an end! 'I wonder how
S1: line 1, bytes = 68
S2: line 1, score = 5.000
---
many miles I've fallen by this time?' she said aloud. 'I must be getting
S1: line 2, bytes = 72
S2: line 2, score = 4.000
不管怎样
SO: query = fall down
---
Down, down, down. Would the fall NEVER come to an end! 'I wonder how
S1: line 1, bytes = 68
line 1, score = 0.000000
---
many miles I've fallen by this time?' she said aloud. 'I must be getting
S1: line 2, bytes = 72
: line 2, score = 0.000000
---
如果我通过添加 printf("%c",line[y]) 循环打印该行,我会得到这个输出。
SO: query = fall down
---
Down, down, down. Would the fall NEVER come to an end! 'I wonder how
S1: line 1, bytes = 68
Down, down, down. Would the fall NEVER come tDown, down, down. Would the fall NEVER come to an end! 'I wonder how °·) ⌠"" S2: line 1, score = 0.000000
---
many miles I've fallen by this time?' she said aloud. 'I must be getting
S1: line 2, bytes = 72
many miles I've fallen by this time?' shmany miles I've fallen by this time?' she said aloud. 'I must be getting °·) ⌠"" S2: line 2, score = 0.000000
---
int
print_lines(char query [MAX_QUERY]){
int line_num = 0;
int query_len = strlen(query);
int line_len = 0,i,y,z = 0, position,c = 0;
int limit = query_len > line_len ? line_len : query_len;
double score = 0, maximum;
char score_list[15] = "";
char line[MAX_LINE];
while((line_len = read_lines(line)) != EOF){
c = 0;
line_num ++;
printf("S1: line %d, bytes = %d \n",line_num,line_len);
/* Loops through the query and line and compares the characters
* If it is the same, it adds to the score
* Once it gets to different character the score is reset
*/
for (i = 0; i < limit; i++){
for (y = 0; y < limit; y++){
if (query[i] == line[y]){
score++;
}
else if(score != 0 && query[i] != line[y]){
score_list[z] = score;
z++;
}
}
}
/* Finds the largest score in the array
*/
maximum = score_list[0];
for (position = 1; position < 15; position++){
if (score_list[position] > maximum){
maximum = score_list[position];
}
}
/* resets the score list back to zero
*/
while (c < 15){
score_list[c] = 0;
c++;
}
printf("S2: line %d, score = %f\n",line_num,maximum);
printf("---\n");
}
return 0;
}
最佳答案
最大的问题在于您设计的 read_lines
和在 print_lines
中调用它的 while
循环。您不能在 while
循环中返回 (1) line_len
或 (2) EOF
并测试 EOF
因为两者不相互排斥。例如,您的文件经常在最后一行的文本后面没有 换行符
。 (POSIX 指定所有文件都应以 换行符
结尾,但许多编辑器会很乐意在没有它的情况下编写文件)。如果发生这种情况并且您正在循环中测试 EOF
,则您错过了整个最后一行文本。
此外,如果您在任何地方阅读了超过 MAX_LINE
个字符,您就不会测试。要解决此问题,您可以将 read_lines
重新设计为:
int read_lines (char line[MAX_LINE])
{
int line_len = 0;
int c;
while ((c = getchar ()) != '\n' && c != EOF) {
line[line_len] = c;
line_len++;
if (line_len == MAX_LINE - 1) break;
}
line[line_len] = 0;
if (line_len)
printf ("%s\n", line);
return line_len ? line_len : c == EOF ? EOF : line_len;
}
接下来,除了注释中给出的有关编译有 警告的所有充分理由之外,您还通过完全塞满代码而没有空格或注释来使代码无法阅读。你也没有处理你的循环限制是一种简洁的方式。当 query
的长度超过 line
时,您会在读取 line
中的最后一个字符后继续在外循环中循环,而无需执行任何操作。一个简单的:
int query_len = strlen (query);
...
int limit = query_len > line_len ? line_len : query_len;
将为您可以用来计算分数
等的单个循环设置限制。(注意您所有的长度int
变量,实际上应该是 size_t
或 unsigned
类型,因为你不能有负长度。对于只包含正值的计数器也是如此,比如你的循环计数器......)
然后对于实际处理,为了处理最后一行文本的所有情况,您可以将循环重组为类似以下内容:
// while ((line_len = read_lines (line)) != EOF)
for (;;)
{
line_len = read_lines (line);
c = 0; /* this is important */
if (line_len != EOF)
{
line_num++;
printf ("S1: line %d, bytes = %d \n", line_num, line_len);
for (i = 0; i < limit; i++)
{
... /* rest of your loop here */
}
}
if (line_len == EOF)
break;
}
你接下来有一个大问题归零 score_list
。它只发生在第一次循环迭代中。为什么?您永远不会在运行后重置 c = 0;
:
while (c < 15){
score_list[c] = 0;
c++;
}
意思是 score_list
在第一次通过时被重置,但是对于随后的每次通过,c
已经是 15
并且该代码永远不会执行。
如果您解决了这些问题,您可能可以让您的代码执行您想要的操作。值得再说一遍,编译的时候,在warnings enabled的情况下编译。至少 -Wall -Wextra
。然后修复所有警告。试一试,如果您有任何问题,请告诉我。
关于c - 通过 for 循环读取字符串时获取随机重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32675050/