如何使用C语言中的字符串填充动态数组

时间:2017-04-06 02:49:31

标签: c dynamic-arrays

我正在做一个项目,我必须从文件中读取文本,然后提取每个长度为4个字符的单词,并将其分配到动态数组中。我的方法是创建将获得4个字母单词数的int函数并返回该数字,然后创建另一个函数,该函数将获取该数字并创建由该多个元素组成的动态数组。这种方法的问题是如何用满足要求的单词填充该数组。

int func1(FILE *pFile){

    int counter = 0;
    int words = 0;
    char inputWords[length];
    while(fscanf(pFile,"%s",inputWords) != EOF){
    if(strlen(inputWords)==4){
          #counting 4 letter words
          counter++;
           }
      }
 }
      return counter;
 }

   int main(){
    #creating pointer to a textFile
    FILE *pFile = fopen("smallDictionary.txt","r");
    int line = 0;  
    #sending pointer into a function   
    func1(pFile);
    fclose(pFile);
    return 0;
}

1 个答案:

答案 0 :(得分:0)

我建议您使用fgets()阅读输入行,并使用strtok()将每行划分为令牌。找到每个标记后,可以检查长度,如果标记长度为四个字符,则可以使用strdup()将其保存到数组中。

在下面的代码中,存储分配给指向char的指针,该指针将存储四个字母单词的地址。 num_words包含找到的四个字母单词的数量,max_words包含当前可存储的最大单词数。当需要添加新单词时,num_words会递增,如果没有足够的存储空间,则会分配更多空间。然后使用strdup()复制令牌,并将地址分配给words中的下一个指针。

请注意strdup()不在C标准库中,而是在POSIX中。可能需要程序第一行中的功能测试宏来启用此功能。另请注意,strdup()为重复的字符串分配内存,该字符串必须由调用者释放。

#define _POSIX_C_SOURCE 200809L

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

#define BUF_SZ     1000
#define ALLOC_INC  100

int main(void)
{
    FILE *fp = fopen("filename.txt", "r");
    if (fp == NULL) {
        perror("Unable to open file");
        exit(EXIT_FAILURE);
    }

    char buffer[BUF_SZ];
    char **words = NULL;
    size_t num_words = 0;
    size_t max_words = 0;
    char *token;
    char *delims = " \t\r\n";

    while (fgets(buffer, sizeof buffer, fp) != NULL) {
        token = strtok(buffer, delims);

        while (token != NULL) {
            if (strlen(token) == 4) {
                ++num_words;
                if (num_words > max_words) {
                    max_words += ALLOC_INC;
                    char **temp = realloc(words, sizeof *temp * max_words);
                    if (temp == NULL) {
                        perror("Unable to allocate memory");
                        exit(EXIT_FAILURE);
                    }
                    words = temp;
                }
                words[num_words-1] = strdup(token);
            }
            token = strtok(NULL, delims);
        }
    }

    if (fclose(fp) != 0) {
        perror("Unable to close file");
        exit(EXIT_FAILURE);
    }

    for (size_t i = 0; i < num_words; i++) {
        puts(words[i]);
    }

    /* Free allocated memory */
    for (size_t i = 0; i < num_words; i++) {
        free(words[i]);
    }
    free(words);

    return 0;
}

更新

OP已提到在解决此问题时不允许使用非标准功能。虽然strdup()是POSIX,并且在这个意义上都是通用的和标准的,但它并不总是可用的。在这种情况下,通常只需实现strdup(),因为这样做很简单。以上代码经过修改,现在使用函数my_strdup()代替strdup()。代码保持不变,除了功能测试宏已被删除,对strdup()的调用已更改为my_strdup(),当然现在有一个函数原型和{{1}的定义}:

my_strdup()

最终更新

在编写上述解决方案时,OP未在问题中发布代码。发布的代码不会按原样编译。除了缺少#include <stdio.h> #include <stdlib.h> #include <string.h> #define BUF_SZ 1000 #define ALLOC_INC 100 char * my_strdup(const char *); int main(void) { FILE *fp = fopen("filename.txt", "r"); if (fp == NULL) { perror("Unable to open file"); exit(EXIT_FAILURE); } char buffer[BUF_SZ]; char **words = NULL; size_t num_words = 0; size_t max_words = 0; char *token; char *delims = " \t\r\n"; while (fgets(buffer, sizeof buffer, fp) != NULL) { token = strtok(buffer, delims); while (token != NULL) { if (strlen(token) == 4) { ++num_words; if (num_words > max_words) { max_words += ALLOC_INC; char **temp = realloc(words, sizeof *temp * max_words); if (temp == NULL) { perror("Unable to allocate memory"); exit(EXIT_FAILURE); } words = temp; } words[num_words-1] = my_strdup(token); } token = strtok(NULL, delims); } } if (fclose(fp) != 0) { perror("Unable to close file"); exit(EXIT_FAILURE); } for (size_t i = 0; i < num_words; i++) { puts(words[i]); } /* Free allocated memory */ for (size_t i = 0; i < num_words; i++) { free(words[i]); } free(words); return 0; } char * my_strdup(const char *str) { size_t sz = strlen(str) + 1; char *dup = malloc(sizeof *dup * sz); if (dup) { strcpy(dup, str); } return dup; } 和各种语法错误(额外的大括号,不正确的注释语法)之外,还有一些更重要的问题。在#include中,func1()变量未初始化使用。这应该足够大,以便length可以保留任何预期的单词。此外,宽度说明符应与inputWords[]格式字符串中的%s一起使用,以避免缓冲区溢出。并且,OP代码应检查文件是否成功打开。最后,scanf()返回一个值,但调用函数甚至不将此值赋给变量。

要完成任务,应使用func1()返回的值声明一个2d数组来存储四个字母的单词。该文件可以重绕,但这次func1()检索循环中的单词,如果单词的长度为fscanf(),则4用于将单词复制到数组中。

以下是OP代码的修改版本:

strcpy()