在另一个malloc中重写数据

ffvjumwh  于 2023-03-29  发布在  其他
关注(0)|答案(2)|浏览(105)

我试图得到一个名为“konferencnyZoznam”的文件,按行排序到separete动态数组中,然后将它们返回到main函数(这样我就可以将它们用于anotherfunctions).我不确定是什么原因导致了这个问题,但我从调试器和输出中看到,malloc函数分配的空间太近了,而且每次调用该函数时,其中的数据都会被重写。

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

void n(char ***pid,char ***ptitle,char ***pname,char ***pdate,FILE **pFile);
void s(char **id);

int main() {
    int k=0;
    char c;
    char *id=NULL,*title=NULL,*name=NULL,*date=NULL;
    char **pid=&id,**ptitle=&title,**pname=&name,**pdate=&date;
    FILE *file,**pFile=&file;
    file= fopen("KonferencnyZoznam.txt","r");
    while(k==0) {
    printf("which function you want to call ?:\n");
    scanf(" %c",&c);
        if (c == 'v') {

        }
        else if (c == 'p') {

        }
        else if (c == 'n') {
            n(&pid,&ptitle,&pname,&pdate,pFile);
            s(id);
            k=0;  //for some reason it even changes k, so i need to change it back here, so program wont end!!
        }
        else if (c == 'k') {
            k=1;
        }
        else{
            printf("function not recognized, try again\n");
        }
    }
    /*for (int i=0;i<strlen(id);i++){
        free(id[i]);
    }*/
    return 50;
}

void n(char ***pid,char ***ptitle,char ***pname,char ***pdate,FILE **pFile){
    char f[100];
    int pr=1,i=0;
    int ni=0,nn=0,nt=0,nd=0;
    while (fgets(f,100,*pFile)){
        pr++;
    }
    printf("pr: %d\n",pr);
    rewind(*pFile);
    (**pid)=(char**) malloc(pr*sizeof (char*));
    (**ptitle)=(char**) malloc(pr*sizeof (char*));
    (**pname)=(char**) malloc(pr*sizeof (char*));
    (**pdate)=(char**) malloc(pr*sizeof (char*));
    for (int m=0;m< (pr/5);m++){
        (*pid)[m]=(char*)malloc(sizeof (char*));
        (*ptitle)[m]=(char*)malloc(sizeof (char*));
        (*pname)[m]=(char*)malloc(sizeof (char*));
        (*pdate)[m]=(char*)malloc(sizeof (char*));
    }

    do {
        fgets(f,100,*pFile);
        printf("f: %s",f);
        if (i % 5 == 0) {
            //(*pid)[ni] = (char *) realloc((*pid)[ni],(strlen(f)+1) * sizeof(char));
            strcpy((*pid)[ni],f);
            printf("%s", (*pid)[ni]);
            ni++;
        } else if (i % 5 == 1) {
            //(*ptitle)[nt] = (char *) realloc((*pid),(strlen(f)+1) * sizeof(char));
            strcpy((*ptitle)[nt], f);
            printf("%s", (*ptitle)[nt]);
            nt++;
        } else if (i % 5 == 2) {
            //(*pname)[nn] = (char *) malloc((strlen(f)+1) * sizeof(char));
            strcpy((*pname)[nn], f);
            printf("%s", (*pname)[nn]);
            nn++;
        } else if (i % 5 == 3) {
            //(*pdate)[nd] = (char *) malloc((strlen(f)+1) * sizeof(char));
            strcpy((*pdate)[nd], f);
            printf("%s", (*pdate)[nd]);
            nd++;
        } else {
            printf("\n");
        }
        for (int j=0;j<100;j++) {
            f[j] = '\0';
        }
        i++;
    } while (i<pr);

    for (int p=0;p<5;p++){
        printf("%s",*pid[p]);
    }
}

// this function is here for me to see which data i can later acces in other functions down the line
void s(char **id){
    printf("%s\n",id[0]);
}

这就是txt文件的样子

UP12345678
Zaklady proceduralneho programovania 2
Jan Zelenka#A#
202004050800

UP12457896
Deep learning
Jozko Mrkvicka#A#
202004051120

UD12365478
Cloud computing
Jana Mrkvickova#A#Jozko Mrkvicka#K#
202004051030

UP98632541
Metody inspirovane prirodou
Jan Oriesok#A#Jozko Mrkvicka#A#
202004051520

PP96385214
Spracovanie obrazu
Jozko Mrkvicka#A#
202004051200

好吧,我几乎尝试了所有我能做的。我试着cahnging malloc的大小,添加或删除 * 和指针,甚至重写整个n函数5或6次,好吧,我已经不知道该怎么做了...
我在最后期待的是4个不同的数组(id,title,name和date),这些值应该在那里:id [[UP12345678][UP12457896][UP12457896][UP98632541][PP96385214]] title[[Zaklady proceduralneho programovania 2][Deep learning][Cloud computing][Metody inspirovane prirodou][Spracovanie obrazu]] you get the point ... oh,and i cannot use the global variables:D
谢谢你能给予我的任何帮助,我真的在这件事上失去了理智……

dgiusagp

dgiusagp1#

你的动态内存分配是完全错误的,当你超过1-2层的间接性时,这很容易做到。我知道你使用了三层,因为你想使用out参数来返回指向char *的动态分配数组的指针,但有更好的策略可用。
然而,在我们讨论替代方案之前,以下是当前计划失败的主要方式:

  • 分配的数组指针存储在错误的位置,因为使用了错误的间接级别。例如,这个...
(**pid)=(char**) malloc(pr*sizeof (char*));

...应该是:

*pid = malloc(pr * sizeof(**pid));  // main difference: *pid instead of **pid on LHS
  • 为单个字符串分配的内存不足。例如,此...
(*pid)[m]=(char*)malloc(sizeof (char*));

。。。应该是这样的:

(*pid)[m] = malloc(MAX_STRING_LENGTH);

但是为什么你要使用一堆单独的char *数组呢?这段代码绝对是在乞求一个结构来表示文件中的条目。沿着这些行的东西会更容易使用:

struct person {
    char id[16];
    char title[64];
    char name[64];
    char date[16];
};

struct person *n(FILE *file, size_t *num_entries) {
    size_t pr;
    // ... compute number of entries and store in pr ...

    // Just one allocation:
    struct person *entries = calloc(pr, sizeof(*entries));  // zero-fills the space
    if (!entries) return NULL;  // always check for allocation failure

    char buffer[100];

    size_t line_counter = 0;
    *num_entries = 0;

#   define WRITE_FIELD(field) do { \
        strncpy(entries[*num_entries].field, buffer, sizeof(entries[*num_entries].field) - 1); \
        printf("%s\n", entries[*num_entries].field); \
    } while (0)

    while (fgets(buffer, sizeof(buffer), file)) {
        switch (line_counter % 5) {
            case 0:
                WRITE_FIELD(id);
                break;
            case 1:
                WRITE_FIELD(title);
                break;
            case 2:
                WRITE_FIELD(name);
                break;
            case 3:
                WRITE_FIELD(date);
                break;
            default:  // 4
                *num_entries += 1;
        }

        line_counter += 1;
    }

#   undef WRITE_FIELD

    return entries;
}

这比原来的代码更清晰,更清晰,但它并不像原来的代码那样健壮。像原来的代码一样,如果文件包含任何超过99字节的行,它就会被抛出。修复这个问题(在两个版本中)作为练习。

qlzsbp2j

qlzsbp2j2#

太复杂了!当你试图编写一些功能时,编写简单的代码并测试它们是否符合你的要求会更容易,然后(* 递增 *)增加一点复杂性,直到你实现你的目标。
下面是一个“精简”的原型供你考虑。它演示了如果你只是将整个文件加载到一个动态内存块中,你可能会做什么。这里的块是“硬编码”为一个编译时字节数组。
看起来目标是将这些字节分割成5个字符串的部分。注意,不需要strcpy()已经存在于这个数组中的字符串(或从文件加载的动态分配的缓冲区)。
整个块中的行数被计数,然后“四舍五入”到5的倍数,因为源数据的每个部分都存储在5行中。(OP承担数据验证的责任。)分配一个指针数组,每个指针都被设置为指向适当的字符串(包括“填充”最后一个块)。
在这里,行被显示,分组在一起,like with like。在这里,OP可以编写代码为每种“类型”的字符串分配单独的数组,并根据需要填充这些数组。
这并不是OP问题的完整解决方案,而是指向一个解决方案,该解决方案不涉及比可能吞下的堆分配呈指数级增加的堆分配。

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

int countLines( char *s ) {
    int cnt = 0;
    while( (s = strchr( s, '\n' ) ) != NULL)
        cnt++, s++;
    return cnt;
}

void show( int n, char *arr[], int max ) {
    for( int out = n; out < max; out += 5 )
        puts( arr[ out ] );
    puts( "" );
}

int main( void ) {
    char buffer[] = // Simulate buffer bulk-loaded from file with `fread()`
        "UP12345678\n"
        "Zaklady proceduralneho programovania 2\n"
        "Jan Zelenka#A#\n"
        "202004050800\n"
        "\n"
        "UP12457896\n"
        "Deep learning\n"
        "Jozko Mrkvicka#A#\n"
        "202004051120\n"
        "\n"
        "UD12365478\n"
        "Cloud computing\n"
        "Jana Mrkvickova#A#Jozko Mrkvicka#K#\n"
        "202004051030\n"
        "\n"
        "UP98632541\n"
        "Metody inspirovane prirodou\n"
        "Jan Oriesok#A#Jozko Mrkvicka#A#\n"
        "202004051520\n"
        "\n"
        "PP96385214\n"
        "Spracovanie obrazu\n"
        "Jozko Mrkvicka#A#\n"
        "202004051200\n";

    int i = countLines( buffer );
    printf( "%d lines\n", i );

    if( i%5 ) i = (i/5 + 1) * 5; // round up to nearest multiple. could be simpler.
    printf( "%d lines\n", i );

    char **arr = calloc( i, sizeof *arr ); // one array of pointers

    int use = 0;
    // assign pointers and chop into string(s)
    for( char *cp = buffer; *cp; *cp++ = '\0' ) {
        arr[ use++ ] = cp;
        cp = strchr( cp, '\n' );
        if( !cp) break;
    }
    while( use < i ) arr[ use++ ] = "empty";
    printf( "%d pointers\n\n", use );

    show( 0, arr, i );
    show( 1, arr, i );
    show( 2, arr, i );
    show( 3, arr, i );

    free( arr );

    return 0;
}

结果:

24 lines
25 lines
25 pointers

UP12345678
UP12457896
UD12365478
UP98632541
PP96385214

Zaklady proceduralneho programovania 2
Deep learning
Cloud computing
Metody inspirovane prirodou
Spracovanie obrazu

Jan Zelenka#A#
Jozko Mrkvicka#A#
Jana Mrkvickova#A#Jozko Mrkvicka#K#
Jan Oriesok#A#Jozko Mrkvicka#A#
Jozko Mrkvicka#A#

202004050800
202004051120
202004051030
202004051520
202004051200

通过检测并跳过每个区域的第五行,可以只使用4个指针来表示一个“区域”。

相关问题