0

我想从 N 个文本文件中读取(具有相似的结构:几行,每行具有相同的少量单词)并将读取的单词存储在字符串矩阵中,这样每个 (row, col)立场我一句话。

文件的一个简单(两行,每行三个字)样本如下:

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. 也就是说,line1word1and line1wordsoffile0正确存储在matrix[0][0][0]andmatrix[0][0][1]中,但是字段matrix[0][0][2]中没有line1word3,即使A[2]有!

我在做什么错?有什么建议吗?

非常感谢提前,干杯

4

2 回答 2

0

这看起来不对: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是 a char **,这意味着它指向 a 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++). 无论哪种方式,您都需要逐个修复这些问题。

出于好奇,你在看哪本书?

于 2013-03-15T11:26:28.633 回答
0

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]不是同一个项目。无论数组中的维度如何,元素通常在内存中按顺序排列,每一行都在前一个(或可能的列,我想取决于语言)之后。如果你有一个指针数组,实际内容可能在其他地方,但点会这样排列。因此,在我上面的示例中,您必须向编译器提供列数,以便它可以找到成员(数可以是可变的。)在三维数组中,您必须提供前两个维度,以便编译器可以计算项目偏移量。

我希望这会有所帮助。

编辑:您可以通过创建自己的函数来处理所有数组项访问,从而获得真正的动态数组维度。该函数需要知道动态维度和项目索引,以便它可以计算适当的地址。

于 2013-03-15T10:56:10.397 回答