[英]Use of array of arrays of string in C for parsing text file
我想從N個文本文件中讀取(結構相似:幾行,每行具有相同的少量單詞),並將讀取的單詞存儲在字符串矩陣中,使得每個行(行,列)位置,我有一個字。
文件的一個簡單樣本(兩行,每行三個單詞)如下:
line1word1 line1word2 line1word3
line2word1 line2word2 line2word3
單詞的定界符是空格。
我嘗試了這段代碼:
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_STRING_LENGTH 1000
#define MAX_TOKS 100
#define DELIMITERS " "
// line parsing utility
int parseString(char* line, char*** argv) {
char* buffer;
int argc;
buffer = (char*) malloc(strlen(line) * sizeof(char));
strcpy(buffer,line);
(*argv) = (char**) malloc(MAX_TOKS * sizeof(char**));
argc = 0;
(*argv)[argc++] = strtok(buffer, DELIMITERS);
while ((((*argv)[argc] = strtok(NULL, DELIMITERS)) != NULL) &&
(argc < MAX_TOKS)) ++argc;
return argc;
}
int main() {
char S[MAX_STRING_LENGTH];
char **A;
int n,i,j,l;
FILE *f;
char file[50];
char ***matrix;
matrix = malloc(MAX_TOKS * sizeof(char**));
//memory allocation for matrix
for (i = 0; i < MAX_TOKS; i++)
{
matrix[i] = malloc(MAX_TOKS * sizeof(char *));
for (j = 0; j < MAX_TOKS; j++)
{
matrix[i][j] = malloc(MAX_TOKS * sizeof(char));
}
}
int NFILE = 10; // number of files to be read
for(i=0;i<NFILE;i++)
{
sprintf(file,"file%d.txt",i);
f = fopen(file,"r");
l=0; // line-in-file index
while(fgets(S,sizeof(S),f)!=NULL) {
n = parseString(S,&A);
for(j=0;j<n;j++) {
matrix[i][l]=A[j];
printf("%s\t%s\n",matrix[i][l],A[j]);
}
l++;
}
fclose(f);
}
free(matrix);
free(A);
return(0);
}
我無法解決的問題是,在檢查數組之間的對應關系時(為了確保我正確地存儲了單個單詞)使用
printf("%s\t%s\n",matrix[i][l],A[j]);
我發現無論文件號如何,每行的最后一個單詞(也只有最后一個)沒有存儲在matrix
。 也就是說, line1word1
和line1words
的file0
被正確地存儲在matrix[0][0][0]
和matrix[0][0][1]
,但在該領域matrix[0][0][2]
即使A[2]
有,也沒有line1word3
!
我在做什么呢? 有什么建議嗎?
預先非常感謝,歡呼
char ***matrix
沒有聲明三維數組。 您的矩陣需要像char *matrix[a][b]
來保存字符串指針的二維數組。 為了計算數組中的地址,編譯器需要知道除一個維之外的所有維。 如果您考慮一下,您可能會明白為什么...
如果您有兩個數組:
1 2 3 1 2 3 4 5 6 7
4 5 6 8 9 10 11 12 13 14
7 8 9 15 16 17 18 19 20 21
您可以看到item[1][1]
不是同一項目。 不管數組中的維數如何,元素通常在內存中順序排列,每一行都在上一行(或可能的列,我想這取決於語言)之后。如果您有一個指針數組,則實際的內容可能在其他地方,但是這些點的排列方式是這樣的。 因此,在上面的示例中,必須為編譯器提供列數,以便它可以找到成員( 行數可以是可變的。)在三維數組中,必須提供前兩個維,以便編譯器可以計算項目偏移量。
希望對您有所幫助。
編輯:您可以通過創建自己的函數來處理所有數組項訪問來擁有真正的動態數組尺寸。 該功能將需要知道動態尺寸和項目索引,以便可以計算適當的地址。
這看起來是錯誤的: buffer = (char*) malloc(strlen(line) * sizeof(char));
首先,不需要在C中強制轉換malloc。如果沒有強制轉換就無法編譯代碼,則可能有兩個原因:
int
,或者發生錯誤。 這可能會導致您的程序行為異常。 為了避免這種情況,請#include <stdlib.h>
。 其次,sizeof(char)始終為1。不需要乘以它。
第三,字符串是一個以第一個“ \\ 0”結尾的字符序列。 這意味着即使一個空字符串,它也總是至少占用1個字符。 strlen("")
返回什么? 什么是sizeof("")
? 您需要添加1來為'\\ 0'騰出空間: buffer = malloc(strlen(line) + 1);
。
這看起來有點不對勁: (*argv) = (char**) malloc(MAX_TOKS * sizeof(char**));
malloc返回一個指向對象的指針。 *argv
是一個char **
,這意味着它指向一個char *
。 但是,在這種情況下,malloc返回指向char **
對象的指針。 表示形式不必相同。 為了避免與此相關的可移植性問題,請遵循以下模式variable = malloc(n * sizeof *variable);
...在這種情況下, *argv = malloc(MAX_TOKS * **argv);
它變得越來越堅韌。 忘記您認為對代碼了解的一切; 假裝您將在24個月后回到這個問題。 您會怎么想呢?
argc = 0;
(*argv)[argc++] = strtok(buffer, DELIMITERS);
while ((((*argv)[argc] = strtok(NULL, DELIMITERS)) != NULL) &&
(argc < MAX_TOKS)) ++argc;
實際上,這里也一一提供。 假設argc == MAX_TOKS
,您的循環將嘗試分配給(*argv)[MAX_TOKS]
。 我認為這個循環是您的問題所在,解決方案是更清楚地表達您的意圖,而不是嘗試將盡可能多的代碼塞進一行。 您將如何重寫呢? 在這種情況下,我會這樣做:
char *arg;
size_t argc = 0;
do {
arg = strtok(buffer, DELIMITERS);
buffer = NULL;
(*argv)[argc] = arg;
argc++;
} while (argc < MAX_TOKS && arg != NULL);
問題是當strtok返回NULL時,解析循環不會增加。 因此,您的函數將返回最后一項的位置。 假設您有兩個標記,則解析函數將返回1。您的顯示循環將顯示以下項目,但不包括以下位置: for(j=0;j<n;j++)
。 您可以使用建議的改進,也可以更改循環: for (j = 0; j <= n; j++)
。 無論哪種方式,您都需要逐個修復。
出於好奇,您正在閱讀哪本書?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.