簡體   English   中英

如何將動態字符串存儲在包含 char * 指針的結構 ** 中

[英]How to Store dynamic string in a struct ** containing char * pointer

我目前正在解決將輸入文件中的數據存儲到以下格式的結構中的問題:

typedef struct school_{
  char *name;
  char *state;
}School;

我從格式的輸入文件中讀取:

name1, state1
name2, state2

我想通過指針將每所學校的數據動態存儲在一個結構中,因為名稱的長度未知。 k 是文件中的行數。 到目前為止,這就是我所擁有的:

void input_schools(FILE *IN, School **Sch, int k) { 
  int i, j;
  char ch;

  for (i=0; i<k; i++)
{ fscanf(IN, "%c", &ch);
  Sch[i].name = (char *)malloc(sizeof (char));

  j = 0;
  Sch[i].name[j] = ch;

  while(ch != '-') {
    fscanf(IN, "%c", &ch);
    j++;
    Sch[i].name = (char *) realloc(Sch[i].name, sizeof(char)*(j+1));
    Sch[i].name[j] = ch;
  }

}
Sch[i].name[j-1] = '\0';

但是,我收到了一個段錯誤,我假設這是因為我在寫“Sch[i].name[j]”時試圖存儲“ch”的方式我也試過 Sch[i]->name[ j] 並沒有成功。 我很感激知道寫入地址以存儲數據的正確方法的任何幫助?

我調用函數使用: input_schools(school_info,TOP100,school_size); 其中 school info 是輸入文件 School *TOP100[school_size]; 是 top100 和 school_size 是文件中的行數

您的文件在形狀上與 csv 非常相似。 看看您是否可以使用任何 csv 解析庫或代碼

不是檢查每個字符,而是將整行讀入緩沖區並使用 strtok。 strtok 是一個用於通過分隔符分割字符串的函數。 ',' 在你的情況下。

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

const char* getfield(char* line, int num)
{
    const char* tok;
    for (tok = strtok(line, ",");
            tok && *tok;
            tok = strtok(NULL, ",\n"))
    {
        if (!--num)
            return tok;
    }
    return NULL;
}

int main()
{
    FILE* stream = fopen("in.md", "r");

    char line[1024];
    while (fgets(line, 1024, stream))
    {
        char* tmp1 = strdup(line);
        char* tmp2 = strdup(line);

        printf("Name is %s\n", getfield(tmp1, 1));
        printf("State is %s\n", getfield(tmp2, 2));
        // NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
        // Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
        free(tmp1);
        free(tmp2);
    }
}

您可以使用類似的方法從您提供的FILE*讀取一個 School 條目:

bool School_read(School* s, FILE* in) {

    int scan = fscanf(in, " %m[^,\n], %m[^\n]", &s->name, &s->state);

    // the fscanf format string:
    // <space> = skip leading whitespaces (like a newline from the line before)
    // %m[^,\n] = read a string until, but not including, "," or "\n"  m = allocate space for it
    // , = expect a comma and discard it
    // %m[^\n] = read a string until, but not including, "\n" and allocate space for it

    // just a debug print
    fprintf(stderr, " -- got %d hits, >%s< >%s<\n", scan, s->name, s->state);

    if(scan<2) {
        // not a complete scan, failure
        if(scan==1) {
            // apparently, we got one match, free it
            free(s->name);
            s->name = NULL;
        }
        return false;
    }
    return true;
}

我不知道對為字符串動態分配內存的“m”修飾符的支持有多廣泛。 無論如何,最近的 gcc 和 clang 編譯器都支持它。

您還可以創建用於創建和銷毀學校的函數:

School* School_create() {
    School* s = malloc(sizeof(School));
    if(s!=NULL) {
        s->name = NULL;
        s->state = NULL;
    }
    return s;
}

void School_destroy(School** sp) {
    if(sp) {
        School* s = *sp;
        if(s) {
            if(s->state) free(s->state);
            if(s->name) free(s->name);
            free(s);
        }
        *sp = NULL;
    }
}

..並將它們全部結合起來:

School* School_create_and_read(FILE* in) {
    School* s = School_create();
    if(s) {
        if(School_read(s, in)==false) {
            School_destroy(&s);
        }
    }
    return s;
}

因此,在您填充學校數組的函數中:

void input_schools(FILE* IN, School** Sch, int k) { 
    School* s;
    while( (s=School_create_and_read(IN)) ) {
        // s is a valid School pointer
        // store it in your array 
    }               
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM