即使我处理该字符,也无法在解析它时消除我的数组中的一个字符

时间:2017-01-31 22:42:05

标签: c scanf

所以这是我第二次将我的代码调整到fscanf以获得我想要的东西。我在输出旁边写了一些评论。我遇到的主要问题是一个空字符或空格被添加到数组中。我试图检查null char和字符串变量中的空格,但它没有捕获它。我有点卡住了,想知道为什么我的代码让一个空字符通过?

它正在滑倒的部分“Pardon,O King”输出:King - 1; - 1 所以在这里它解析了一个单词然后,“通过条带功能并成为\ 0,然后我的检查后来在路上允许它通过??

输入:一个包含撇号和逗号的短篇小说(狮子的岩石。首先,狮子醒来)

//Output: Every unique word that shows up with how many times it shows up.
//Lion -- 1
//s - 12
//lion -- 8
//tree -- 2
//-- 1   //this is the line that prints a null char?
//cub -- //3 it is not a space! I even check if it is \0 before entering
         //it into the array. Any ideas (this is my 2nd time)?
         //trying to rewrite my code around a fscanf function.


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

//Remove non-alpha numeric characters
void strip_word(char* string)
{
    char* string_two = calloc(80, sizeof(char));
    int i;
    int c = 0;
    for(i = 0; i < strlen(string); i++)
    {
        if(isalnum(string[i]))
        {
            string_two[c] = string[i];
            ++c;
        }
    }
    string_two[i] = '\0';
    strcpy(string, string_two);
    free(string_two);
}

//Parse through file
void file_parse(FILE* text_file, char*** word_array, int** count_array, int* total_count, int* unique_count)
{
    int mem_Size = 8;
    int is_unique = 1;

    char** words = calloc(mem_Size, sizeof(char *)); //Dynamically allocate array of size 8 of char*
    if (words == NULL)
    {
        fprintf(stderr, "ERROR: calloc() failed!");
    }

    int* counts = calloc(mem_Size, sizeof(int)); //Dynamically allocate array of size 8 of int
    if (counts == NULL)
    {
        fprintf(stderr, "ERROR: calloc() failed!");
    }

    printf("Allocated initial parallel arrays of size 8.\n");
    fflush(stdout);

    char* string;

    while('A')
    {
        is_unique = 1;

        fscanf(text_file, " ,");
        fscanf(text_file, " '");

        while(fscanf(text_file, "%m[^,' \n]", &string) == 1) //%m length modifier 
        {
            is_unique = 1;
            strip_word(string);
            if(string == '\0') continue; //if the string is empty move to next iteration
            else
            {
                int i = 0;              
                ++(*total_count);
                for(i = 0; i < (*unique_count); i++)
                {
                    if(strcmp(string, words[i]) == 0)
                    {
                        counts[i]++;
                        is_unique = 0;
                        break;
                    }
                }
                if(is_unique)
                {
                    ++(*unique_count);
                    if((*unique_count) >= mem_Size)
                    {
                        mem_Size = mem_Size*2;
                        words = realloc(words, mem_Size * sizeof(char *));
                        counts = realloc(counts, mem_Size * sizeof(int));
                        if(words == NULL || counts == NULL)
                        {
                            fprintf(stderr, "ERROR: realloc() failed!");
                        }
                        printf("Re-allocated parallel arrays to be size %d.\n", mem_Size);
                        fflush(stdout);
                    }
                    words[(*unique_count)-1] = calloc(strlen(string) + 1, sizeof(char));
                    strcpy(words[(*unique_count)-1], string);
                    counts[(*unique_count) - 1] = 1;
                }
            }
            free(string);
        }
        if(feof(text_file)) break;
    }
    printf("All done (successfully read %d words; %d unique words).\n", *total_count, *unique_count);
    fflush(stdout);
    *word_array = words;
    *count_array = counts;

}

int main(int argc, char* argv[])
{
    if(argc < 2 || argc > 3) //Checks if too little or too many args
    {
        fprintf(stderr, "ERROR: Invalid Arguements\n");
        return EXIT_FAILURE;
    }

    FILE * text_file = fopen(argv[1], "r");
    if (text_file == NULL)
    {
        fprintf(stderr, "ERROR: Can't open file");

    }

    int total_count = 0;
    int unique_count = 0;
    char** word_array;
    int* count_array;

    file_parse(text_file, &word_array, &count_array, &total_count, &unique_count);

    fclose(text_file);

    int i;

    if(argv[2] == NULL)
    {
        printf("All words (and corresponding counts) are:\n");
        fflush(stdout);
        for(i = 0; i < unique_count; i++)
        {
            printf("%s -- %d\n", word_array[i], count_array[i]);
            fflush(stdout);
        }
    }

    else
    {
        printf("First %d words (and corresponding counts) are:\n", atoi(argv[2]));
        fflush(stdout);
        for(i = 0; i < atoi(argv[2]); i++)
        {
            printf("%s -- %d\n", word_array[i], count_array[i]);
            fflush(stdout);
        }
    }

    for(i = 0; i < unique_count; i++)
    {
        free(word_array[i]);
    }
    free(word_array);
    free(count_array);

    return EXIT_SUCCESS;
}

1 个答案:

答案 0 :(得分:1)

我不确定你的代码到底出了什么问题。我正在使用GCC 6.3.0处理macOS Sierra 10.12.3,而本地fscanf()不支持m修饰符。因此,我修改了代码以使用80字节的固定大小的字符串。当我这样做(并且只有那个)时,你的程序运行没有明显的问题(当然在输入&#34;狮子的摇滚。首先,狮子醒来&#34;)。

我还认为while ('A')循环(如果一直使用的话应该按常规编写while (1))是不可取的。我写了一个函数read_word()来获取下一个单词&#39;,包括跳过空格,逗号和引号,并使用它来控制循环。我在file_parse()中保留了内存分配。我确实摆脱了strip_word()中的内存分配(最终 - 它也写得很好)。

这让我失望:

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

static void strip_word(char *string)
{
    char string_two[80];
    int i;
    int c = 0;
    int len = strlen(string);
    for (i = 0; i < len; i++)
    {
        if (isalnum(string[i]))
            string_two[c++] = string[i];
    }
    string_two[c] = '\0';
    strcpy(string, string_two);
}

static int read_word(FILE *fp, char *string)
{
    if (fscanf(fp, " ,") == EOF ||
        fscanf(fp, " '") == EOF ||
        fscanf(fp, "%79[^,' \n]", string) != 1)
        return EOF;
    return 0;
}

static void file_parse(FILE *text_file, char ***word_array, int **count_array, int *total_count, int *unique_count)
{
    int mem_Size = 8;

    char **words = calloc(mem_Size, sizeof(char *));
    if (words == NULL)
    {
        fprintf(stderr, "ERROR: calloc() failed!");
    }

    int *counts = calloc(mem_Size, sizeof(int));
    if (counts == NULL)
    {
        fprintf(stderr, "ERROR: calloc() failed!");
    }

    printf("Allocated initial parallel arrays of size 8.\n");
    fflush(stdout);

    char string[80];

    while (read_word(text_file, string) != EOF)
    {
        int is_unique = 1;
        printf("Got [%s]\n", string);
        strip_word(string);
        if (string[0] == '\0')
            continue;
        else
        {
            int i = 0;
            ++(*total_count);
            for (i = 0; i < (*unique_count); i++)
            {
                if (strcmp(string, words[i]) == 0)
                {
                    counts[i]++;
                    is_unique = 0;
                    break;
                }
            }
            if (is_unique)
            {
                ++(*unique_count);
                if ((*unique_count) >= mem_Size)
                {
                    mem_Size = mem_Size * 2;
                    words = realloc(words, mem_Size * sizeof(char *));
                    counts = realloc(counts, mem_Size * sizeof(int));
                    if (words == NULL || counts == NULL)
                    {
                        fprintf(stderr, "ERROR: realloc() failed!");
                        exit(EXIT_FAILURE);
                    }
                    printf("Re-allocated parallel arrays to be size %d.\n", mem_Size);
                    fflush(stdout);
                }
                words[(*unique_count) - 1] = calloc(strlen(string) + 1, sizeof(char));
                strcpy(words[(*unique_count) - 1], string);
                counts[(*unique_count) - 1] = 1;
            }
        }
    }
    printf("All done (successfully read %d words; %d unique words).\n", *total_count, *unique_count);
    fflush(stdout);
    *word_array = words;
    *count_array = counts;
}

int main(int argc, char *argv[])
{
    if (argc < 2 || argc > 3)
    {
        fprintf(stderr, "ERROR: Invalid Arguements\n");
        return EXIT_FAILURE;
    }

    FILE *text_file = fopen(argv[1], "r");
    if (text_file == NULL)
    {
        fprintf(stderr, "ERROR: Can't open file");
        return EXIT_FAILURE;
    }

    int total_count = 0;
    int unique_count = 0;
    char **word_array = 0;
    int *count_array = 0;

    file_parse(text_file, &word_array, &count_array, &total_count, &unique_count);

    fclose(text_file);

    if (argv[2] == NULL)
    {
        printf("All words (and corresponding counts) are:\n");
        fflush(stdout);
        for (int i = 0; i < unique_count; i++)
        {
            printf("%s -- %d\n", word_array[i], count_array[i]);
            fflush(stdout);
        }
    }
    else
    {
        printf("First %d words (and corresponding counts) are:\n", atoi(argv[2]));
        fflush(stdout);
        for (int i = 0; i < atoi(argv[2]); i++)
        {
            printf("%s -- %d\n", word_array[i], count_array[i]);
            fflush(stdout);
        }
    }

    for (int i = 0; i < unique_count; i++)
        free(word_array[i]);
    free(word_array);
    free(count_array);

    return EXIT_SUCCESS;
}

在数据文件上运行时:

the lion's rock. First, the lion woke up
输出是:

Allocated initial parallel arrays of size 8.
Got [the]
Got [lion]
Got [s]
Got [rock.]
Got [First]
Got [the]
Got [lion]
Got [woke]
Got [up]
All done (successfully read 9 words; 7 unique words).
All words (and corresponding counts) are:
the -- 2
lion -- 2
s -- 1
rock -- 1
First -- 1
woke -- 1
up -- 1

当代码在您的文本上运行时,包括双引号,如下所示:

$ echo '"Pardon, O King,"' | cw37 /dev/stdin
Allocated initial parallel arrays of size 8.
Got ["Pardon]
Got [O]
Got [King]
Got ["]
All done (successfully read 3 words; 3 unique words).
All words (and corresponding counts) are:
Pardon -- 1
O -- 1
King -- 1
$

这需要一点点代码。如果没有字母字符,您的代码仍会对其进行计数(因为strip_word()中的细微问题)。这需要通过更仔细地检查strip_word()来处理;你测试if (string == '\0')检查(迟了)内存是否已经分配到需要if (string[0] == '\0')来测试字符串是否为空的地方。

请注意,read_word()中的代码会混淆报告EOF,如果一行中有两个逗号,或者后跟逗号的撇号(尽管它处理逗号后跟撇号OK)。修复是比较狡猾的;你可能最好使用getc()的循环来读取一串字符。您甚至可以使用该循环来删除非字母字符而无需单独的strip_word()函数。

我假设你还没有覆盖结构。如果你有覆盖结构,你可以使用struct Word { char *word; int count; };之类的结构数组并分配一次内存,而不是需要两个并行数组。