0

我必须读取一个包含 5 个字段(int、char[]、char[]、char[]、float)的 csv 文件,如下所示:

2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;

我必须将字段放入结构中,然后在一行完成后将结构放入结构类型的数组中......

为了学习效果,我们只允许使用LOW-LEVEL编码,并且只使用fgetc,strcpy之类的函数并且没有字符串,只有char []......现在我做了我的算法来逐字符读取文本文件,但是我无法正确分离它们,将它们重新组合在一起并将它们正确分配给结构字段。这是我的代码:

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

using namespace std;

int main(int argc, char **argv)
{
    struct Stud{
        long matrnr;
        char vorname[30];
        char name[30];
        char datum[30];
        float note;
    };

    const int MAX = 30;
    Stud stud;  
    Stud mystud[30]; // <<-- Array of "Stud" type
    //memset((void*)mystud,0,sizeof(mystud) * sizeof(Stud));
    int wordCounter(0);
    int i(0); //thats the charCounter or index
    int studentCounter(0);
    char wort[MAX];
    //int matrnr;
    //char vorname[MAX];
    //char name[MAX];
    //char datum[MAX];
    //float note;


  FILE * pFile;
  int cnr(0); 


  pFile=fopen("studentendaten.txt","r");  
  if (pFile==nullptr) 
  {
      perror ("Fehler beim öffnen der Datei");
  }

  else
  {       
    while (cnr != EOF) 
    {       
        (cnr=fgetc(pFile)) ;


        if ((char)cnr == '\n') {
            mystud[studentCounter] = stud;
            studentCounter++;                       
            continue;           
        }

        if ((char)cnr == ';') { 

            wort[i] = '\0'; 

            switch (wordCounter % 5) {

                case 0:             
                stud.matrnr = atol(wort);
                break;

                case 1:
                strcpy(stud.name, wort);
                break;

                case 2:
                strcpy(stud.vorname, wort);
                break;

                case 3:
                strcpy(stud.datum,wort);
                break;

                case 4:
                stud.note = atof(wort); 
                break;
            }       

            wordCounter++;          
            i = 0;
            continue;
        }

        if (wordCounter %  5 == 0 && (char)cnr != ';') {        
        wort[i] = (char)cnr;
        i++;
        //stud.matrnr = atol(wort);
        }           

        if (wordCounter % 5 == 1) {
            wort[i] =  (char)cnr;
            i++;
        //strcpy(stud.name, wort);
        }

        if (wordCounter % 5 == 2) {
            wort[i] = (char)cnr;
            i++;
            //strcpy(stud.vorname, wort);
        }

        if (wordCounter % 5 == 3) {
            wort[i] = (char)cnr;
            i++;
            //strcpy(stud.datum,wort);
        }

        if (wordCounter % 5 == 4) {
            wort[i] = (char)cnr;
            i++;
            //stud.note = atof(wort);                       
        }

    }   


    fclose (pFile);
}
for (int i(0) ; i <= studentCounter; i++) {
cout <<mystud[i].matrnr << "    " << mystud[i].name << "    " << mystud[i].vorname <<"    " 
<< mystud[i].datum <<"    " << mystud[i].note << endl;
  //printf("%5ld        %5s      %5s     %5s     %5f     \n",mystud[i].matrnr,mystud[i].name,mystud[i].vorname,mystud[i].datum,mystud[i].note);

}

    return 0;
}

我不确定它是否与错误的增量变量有关,或者我没有在我的 wort[] 数组的末尾放置一个 '\0' ..因此无法识别我的数组的结尾?如果是这样,我该怎么做而不知道到底在哪里......?(我不知道单词的长度..)

编辑:我再次更新了我的代码,唯一让我感到奇怪的是最后一行没有被正确解析,它显示了一些垃圾,我在我的代码中看不到错误......

2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;
8392019;Thomas;Kretschmer;28.3.1920;2.5;
3471144;Mensch;Arbeit;29.2.2013;4.5;
2039482;Test;Test;30.20.2031;2.0;
7584932;Bau;Maschine;02.02.2010;2.3;
4

3 回答 3

1

建议:使用case结构进行解析,并让自己成为一个“copyToSemicolon”函数:然后你可以写像

sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
  offset = 0;
  for(var = 0; var < 5; var++ {
    switch(var) {
    case 0:
      offset = copyToSemicolon(temp, cnr, offset) + 1;
      stud.matrnr = atoi(temp);
      break;
    case 1:
      offset = copyToSemicolon(mystud[sIndexCount].vorname, cnr, offset) + 1;
      break;
    ... etc
    }
  }
  sIndexCount++;
  if(sIndexCount == 50) break;  // in case the input file is longer than our structure
}

而且您需要一个函数,该函数copyToSemicolon将两个char*指针作为输入,并从第二个字符串(从 开始offset)复制字符,直到它到达分号或行尾 - 并返回它到达的偏移量(最后一个字符读取)。

int copyToSemicolon(char* dest, char* source, int offset) {
  while(source[offset] != ';' && source[offset] != '\n') {
    *dest = source[offset++];
    dest++;
  }
  return offset;
} 

编辑 strtok方法:

sIndexCount = 0;
char temp[50];
while((cnr=fgetc(pFile)) != EOF) {
  offset = 0;
  temp = strtok(cnr, ';');
  for(var = 0; var < 5; var++ {
    switch(var) {
    case 0:
      stud.matrnr = atoi(temp);
      break;
    case 1:
      strcpy(mystud[sIndexCount].vorname, strtok(NULL, ';'));
      break;
    ... etc
    case 4:
      mystud[sIndexCount].note = atof(strtok(NULL, '\n'));
    }
  }
  sIndexCount++;
  if(sIndexCount == 50) break;  // in case the input file is longer than our structure
}
于 2013-11-04T20:50:12.173 回答
0

我看到的一个问题是您的代码一次复制或解析一个字符,这样当您阅读时,2345678;Meier;Hans;12.10.1985;2.4;您首先设置stud.matrnr为 2,然后是 23,然后是 234,然后是 2345,然后是 23456,然后是 234567,然后是 2345678。同样,对于stud.name,您首先将其设置为 M,然后设置为 Me,然后设置为 Mei,等等。我建议您以不同的方式思考问题。我会给你一些伪代码:

while (!eof) {
    get character from file
    if (character isn't ';' and isn't '\n') {
        copy character into buffer (increment buffer index)
    } else if (character is ';') {
        it's the end of a word.  Put it in its place - turn it to an int, copy it, whatever
        reset the buffer
    } else if (character is '\n') {
        it's the end of the last word, and the end of the line.  Handle the last word
        reset the buffer
        copy the structure
    }
}

这应该会让你的生活更轻松。您几乎不会更改您的数据,如果您需要调试,您可以单独关注每个部分。

一般来说,在编程中,第一步是确保你能用你的母语说出你想做的事情,然后把它翻译成代码就更容易了。你已经接近你的实施,你可以让它工作。只要确保你能解释当你看到';'时应该发生什么 或'\n'。

于 2013-11-04T21:00:58.617 回答
0

由于您已将其标记为 C++,因此您应该考虑std::getline用于从文件中读取行,std::getline(file, text_before_semicolon, ';')用于解析字段。

您还可以std::istringstream用于将文本行中的文本表示形式转换为内部数字格式。

于 2013-11-04T22:20:32.227 回答