簡體   English   中英

將值從數組分配給結構數組

[英]Assigning values from an array to an array of structs

我正在嘗試將包含所有字符串的數組中的值分配給結構體數組,其中某些結構體成員是整數。 不過,我嘗試的方式會導致一些未定義的行為。 像下面的代碼生成以下內容:

0 surname ▒▒
1 forename &
2 id 0

什么時候應該說

0 surname Boatswain
1 forename Michael Jr
2 id 109993267

我不完全確定我分配這些值的方式出了什么問題。

碼:

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

//There are 7 values for each student
#define VALUES 7

struct Students{
  int term;
  int id; // NEED TO GENERATE ERROR IF WRONG NUM OF CHARACTERS
  char surname[15];
  char forename[15];
  char subject[3];
  int catnum;
  char section[3];
};

int main(int argc, char *argv[]){

//Get contents of input file
  unsigned char filename;
  printf("Enter the input file name: \n");
  scanf("%s", &filename);
  FILE *file = fopen(&filename, "r");
  int filesize=0;
  fseek(file, 0L, SEEK_END);
  filesize = ftell(file);
  fseek(file, 0L, SEEK_SET);
  char *contents = malloc(filesize+1);
  size_t size=fread(contents,1,filesize,file);
  contents[size]=0;  // what does all this do exactly?

//Get number of lines in input file
  int total_line = 0;
  const char *str;
  for(str = contents; *str; ++str)
  total_line += *str == '\n';

//Tokenize string
  int n=0,nn;
  char *b[VALUES*total_line];
  char *ds=strdup(contents);
  b[n]=strtok(ds, ",=\"\r\n\"");
  while(b[n] && n<((VALUES*total_line)-1)) b[++n]=strtok(NULL, ",=\"\r\n\"");
  //for(nn=0; nn<=n; ++nn) printf("%s %d   ", b[nn], nn);
  //putchar('\n');
  free(ds);

  struct Students record[total_line];

  int i, j;
  for(i=0;i++;i<total_line){
    for(j=0;j++;j<VALUES){
      int n=(7*i)+j;
      record[i].term=atoi(b[n]);
      record[i].id=atoi(b[n]);
      strcpy(record[i].surname, b[n]);
      strcpy(record[i].forename, b[n]);
      strcpy(record[i].subject, b[n]);
      record[i].catnum=atoi(b[n]);
      strcpy(record[i].section, b[n]);
    }
  }

// try printing some values here
  printf("0 surname %s\n",record[0].surname); 
  printf("1 forename %s\n",record[1].forename);
  printf("2 id %d\n", record[2].id);

  free(contents);
  return 0;
}

輸入文件:

1301,107515018,"Boatswain","Michael R.",CSE, 230,="R01"
1301,109993269,"Castille","Michael Jr",CSE, 230,="R03"
1301,109993267,"Castille","Janice",CSE, 230,="R03"

預先感謝您的幫助!

編輯:像這樣更改for循環的問題是什么?

for(i=0;i<total_line;i++) { 
  record[i].term=atoi(b[(7*i)]);
  record[i].id=atoi(b[(7*i)+1]);
  strcpy(record[i].surname, b[(7*i)+2]);
  strcpy(record[i].forename, b[(7*i)+3]);
  strcpy(record[i].subject, b[(7*i)+4]);
  record[i].catnum=atoi(b[(7*i)+5]);
  strcpy(record[i].section, b[(7*i)+6]);
}

編輯:我得到它的工作。 只需要將for循環更改為while循環。 Edit2:哦,我有i ++和我total_line切換了。 DERP。 現在修復。 好吧,我想這解決了這個謎。

for(j=0;j++;j<VALUES)循環中,您多次轉換相同的b[n] 您很可能不需要此循環,而只需轉換b[n++]

作為初步介紹,此行(顯然您已經發現可疑)...

  contents[size]=0;  // what does all this do exactly?

...在從文件讀取的字節之后添加一個字符串終止符,因此整個內容可以安全地解釋為一個大的C字符串。

@DavetheSax對令牌的索引進行了有效觀察。 該問題不會導致未定義的行為,但是產生的行為肯定不是您想要的。

但是,您的程序中確實確實存在未定義的行為。 通過將contents復制到ds ,然后使用strtok() ds進行標記來填充數組b 這本身是可以的,但是僅當您需要保留最初讀取的contents時才需要,而您可能不需要。 但是,分詞后,您可以釋放ds 同樣,這本身並不是問題,但是它會使您剛才計算的所有令牌指針失效,因為它們指向先前為ds分配的內存(從中對其進行了令牌化)。 在分析完標記之前,您需要保留該標記。 在釋放令牌指針所指向的空間后,取消引用這些令牌指針會產生UB。

原則上,無法預測UB(否則將不會是UB)。 不過,您報告的特定結果似乎不太可能體現出來,因此這里可能還有更多事情要做。

暫無
暫無

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

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