c - 通过 for 循环读取字符串时获取随机重复

标签 c arrays string comparison iteration

#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_tunsigned 类型,因为你不能有负长度。对于只包含正值的计数器也是如此,比如你的循环计数器......)

然后对于实际处理,为了处理最后一行文本的所有情况,您可以将循环重组为类似以下内容:

    // 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/

相关文章:

c - c 中 '(' token 之前的预期标识符错误

c - 进程卡在等待中

c - 未找到 string.h 文件

asp.net - DB 中的 Oracle 字符串大于 UI 中的

c++ - #if 0 后面到底可以放什么?

指针代码

javascript - 如何自定义这个已经自定义的 jQuery 排序解决方案?

python - 在任意轴上迭代体积的更多 pythonic 方法?

php - 数组中的重复键

c - '\0' evaluates false, "\0"评估为真