【问题标题】:copying tokens to 2D array using malloc使用 malloc 将令牌复制到二维数组
【发布时间】:2016-11-24 06:16:11
【问题描述】:

努力将标记移动到二维数组。 这个想法是我正在读取一个包含多行的文件,获取行数,然后在此基础上创建一个 2D 数组以明智地使用内存(我不想无缘无故地创建一个 100 x 3 数组)。

我想我在一个单独的函数中初始化了二维数组,但是当我尝试输入从 strtok() 读取的数据时,我收到了错误:

error: 'arr' undeclared (first use in this function)
               strcpy(&arr[s2][c2],token);

这是我的代码:

#include <stdio.h>
#include <string.h>
int ch, lines;

int no_of_lines(char* fp)
{
    while(!feof(fp)) {
        ch = fgetc(fp);
        if(ch == '\n') {
            lines++;
        }
    }
    lines++;
    return lines;
}

void declare_space_array(int size)
{
    char* arr = (char*)malloc(size * 3 * sizeof(char));
    return;
}

int main(void)
{
    int c2 = 0;
    int s2 = 0;
    int len;
    // char data[10][4];
    static const char filename[] = "C:\\Users\\PC\\Documents\\Assignments\\stringops\\test.txt";
    FILE* file = fopen(filename, "r");

    no_of_lines(file);
    printf("No of lines in file = %d", lines);
    printf("\n");
    // Closing file because it was read once till the end of file
    fclose(file);
    // Opening file again to read for parsing 

    file = fopen(filename, "r");
    declare_space_array(lines);

    char* token;

    if(file != NULL) {
        char line[128];                               
        while(fgets(line, sizeof line, file) != NULL) 
        {
            len = strlen(line);
            printf("%d %s", len - 1, line);

            const char s = ",";

            token = strtok(line, ",");

            while(token != NULL) {
                strcpy(arr[s2][c2], token);
                // printf( "%s\n", token );

                token = strtok(NULL, ",");
                c2++;
            }
            s2++;
        }
        fclose(file);
    } else {
        perror(filename); /* why didn't the file open? */
    }

    for(r1 = 0; r1 < lines; r1++) {
        for(c1 = 0; c1 < 3; c1++) {
            printf("%s", &arr[r1][c1]);
        }
    }
    return 0;
}

文件是这样的:

A1,B1,C1
A2,B2,C2
A3,B3,C3

这样的预期输出:

A1
B1
C1
A2
B2
C2
A3
B3
C3

【问题讨论】:

  • 您的declare_space_array() 函数只是分配和泄漏内存。变量arr 是该函数的本地变量;在该函数之外无法访问它。
  • @JonathanLeffler 可以将 arr 设为全局吗?还是有其他方法?
  • 它 (arr) 可以设为全局但不应该。该函数应该返回一个char * 并且应该返回分配的指针(在检查分配是否成功之后)。然后您将拥有char *arr = declare_space_array(lines);,您可以在您的main() 中使用它,记住最后释放空间。我看到您正在尝试将其用作 2D 数组 - 尽管您分配了一个简单的 1D 向量。这更棘手。您将不得不担心每行末尾的换行符(以及逗号分隔符)。他们会把你的角色数排除在外。
  • 另一方面,您的内存分配远不足以支持这种结构(每行仅分配 3 个字节),并且您仅分配了char *。这不一定是一个无法克服的问题——但有多种方法可以解决它。您可以使用 C11(或 C99),还是坚持使用 C90?复习你的作业我会得到多少分?

标签: c arrays string pointers malloc


【解决方案1】:

在聊天等讨论后,您最终可能会得到这样的代码。这使用了一个全局变量 arr,它是一个指向包含 3 个 char * 值的数组的数组的指针。

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

static int lines = 0;
static char *(*arr)[3] = 0; // global definition.

static int no_of_lines(FILE *fp)
{
    lines = 0;
    int ch;
    while ((ch = fgetc(fp)) != EOF)
    {
        if (ch == '\n')
            lines++;
    }
    return ++lines;     // Allow for last line possibly not having a newline
}

static void declare_space_array(int size)
{
    arr = calloc(size, 3 * sizeof(char *)); // zeroed memory allocation
    if (arr == 0)
    {
        fprintf(stderr, "Failed to allocate memory\n");
        exit(1);
    }
}

int main(void)
{
    int c2 = 0;
    int s2 = 0;
    int len;
    // char data[10][4];
    // static const char filename[] = "C:\\Users\\PC\\Documents\\Assignments\\stringops\\test.txt";
    const char *filename = "data";
    FILE *file = fopen(filename, "r");
    if (file == 0)
    {
        fprintf(stderr, "Failed to open file '%s' for reading\n", filename);
        exit(1);
    }

    no_of_lines(file);
    printf("No of lines in file = %d\n", lines);
    rewind(file);

    declare_space_array(lines);

    const char delims[] = ",\n";

    char line[128];
    while (fgets(line, sizeof line, file) != NULL)
    {
        char *token;
        c2 = 0;
        len = strlen(line);
        printf("%d [%.*s]\n", len - 1, len - 1, line);

        token = strtok(line, delims);

        while (token != NULL)
        {
            arr[s2][c2] = strdup(token); // copy token (from strtok) into newly allocated string.
            token = strtok(NULL, delims);
            c2++;
        }
        s2++;
    }
    fclose(file);

    for (int r1 = 0; r1 < lines; r1++)
    {
        if (arr[r1][0] != 0)
        {
            for (int c1 = 0; c1 < 3; c1++)
                printf(" %-10s", arr[r1][c1]);
            putchar('\n');
        }
    }
    return 0;
}

它不会释放分配的内存——我很懒。

示例数据(注意名称超过 2 个字符且长度可变):

server1,Phoenix,Windows
server2,Dallas,Linux
server-99,London,z/OS

样本输出:

No of lines in file = 4
23 [server1,Phoenix,Windows]
20 [server2,Dallas,Linux]
21 [server-99,London,z/OS]
 server1    Phoenix    Windows   
 server2    Dallas     Linux     
 server-99  London     z/OS      

“文件中的行数 = 4”允许在最后一行的末尾没有换行符的可能性。打印循环中的代码允许末尾有换行符,因此计数被高估了。只要失败发生在行的第一个字段上,它就会发现来自strdup() 的内存分配。如果是第二个或第三个字段没有成功复制,它可能会崩溃。

【讨论】:

  • 天哪!必须详细研究这一点,以清楚了解 2D 指针数组的概念
猜你喜欢
  • 2014-06-25
  • 2018-03-20
  • 2011-10-30
  • 2021-12-31
  • 2020-04-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-13
相关资源
最近更新 更多