繁体   English   中英

在C中使用字符串数组数组来解析文本文件

[英]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 也就是说, line1word1line1wordsfile0被正确地存储在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。如果没有强制转换就无法编译代码,则可能有两个原因:

  1. 没有malloc的原型。 显然,这可能会引起问题,因为没有原型意味着函数将返回默认类型: int ,或者发生错误。 这可能会导致您的程序行为异常。 为了避免这种情况,请#include <stdlib.h>
  2. 您正在使用C ++编译器。 停止。 使用C ++程序(停止使用malloc)或使用C编译器。 如果要在C ++项目中使用此项目,请使用C编译器编译C代码,并在C ++编译器中链接到它。

其次,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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM