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

问题描述 投票:0回答:1

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

出现问题的部分“国王啊,请原谅”,输出:King -- 1; -- 1 所以在这里它解析 king 一个单词,然后 ," 通过 strip 函数并变成 ,然后我稍后的检查允许它通过??

输入:一个包含撇号和逗号的小故事(狮子岩。首先,狮子醒了)

//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 Arguments\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;
}
c scanf
1个回答
1
投票

我不太确定你的代码出了什么问题。我正在使用 GCC 6.3.0 的 macOS Sierra 10.12.3 上工作,并且本地

fscanf()
不支持
m
修饰符。因此,我修改了代码以使用 80 字节的固定大小字符串。当我这样做时(仅此而已),您的程序运行时不会出现明显问题(当然是在输入“狮子的岩石。首先,狮子醒了”)。

我还认为

while ('A')
循环(如果使用的话,应该按常规方式编写
while (1)
)是不可取的。 我编写了一个函数
read_word()
,它获取下一个“单词”,包括跳过空格、逗号和引号,并用它来控制循环。 我将
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 Arguments\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(尽管它可以处理逗号后跟一个撇号)。 修复这个问题比较麻烦;您可能最好使用带有
getc()
的循环来读取字符串。 您甚至可以使用该循环来去除非字母字符,而不需要单独的
strip_word()
函数。

我假设您还没有讨论过结构。 如果您有覆盖的结构,您可以使用诸如

struct Word { char *word; int count; };
之类的结构数组并分配一次内存,而不是需要两个并行数组。

© www.soinside.com 2019 - 2024. All rights reserved.