Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/146.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ C++;:使用fgetc读取csv文件,并用分号“分隔单词”&引用;_C++_Arrays_Csv_Struct - Fatal编程技术网

C++ C++;:使用fgetc读取csv文件,并用分号“分隔单词”&引用;

C++ C++;:使用fgetc读取csv文件,并用分号“分隔单词”&引用;,c++,arrays,csv,struct,C++,Arrays,Csv,Struct,我必须读入一个csv文件,其中包含5个字段(int、char[],char[],char[],float),如下所示: 2345678;Meier;Hans;12.10.1985;2.4; 1234567;Müller;Fritz;17.05.1990;1.9; 我必须将字段放在结构中,然后在一行完成后将结构放在结构类型的数组中 对于学习效果,我们只允许使用低级编码,并且只允许使用像fgetc、strcpy这样的函数,而不允许使用字符串,只允许使用char[]。。。 现在,我制定了

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

2345678;Meier;Hans;12.10.1985;2.4;      
1234567;Müller;Fritz;17.05.1990;1.9;
我必须将字段放在结构中,然后在一行完成后将结构放在结构类型的数组中

对于学习效果,我们只允许使用低级编码,并且只允许使用像fgetc、strcpy这样的函数,而不允许使用字符串,只允许使用char[]。。。 现在,我制定了逐字读取文本文件的算法,但我无法正确地将它们分开,再次将它们放在一起,并将它们正确地分配给struct字段。这是我的密码:

  #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;
}

建议:使用
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
}
编辑
strok
方法:

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
}
sIndexCount=0;
煤焦温度[50];
而((cnr=fgetc(pFile))!=EOF){
偏移量=0;
温度=标准温度(cnr,,;);
对于(var=0;var<5;var+){
开关(var){
案例0:
螺柱材料=原子(温度);
打破
案例1:
strcpy(mystud[sIndexCount].vorname,strtok(NULL,;);
打破
等
案例4:
mystud[sIndexCount].note=atof(strtok(NULL,“\n'));
}
}
sIndexCount++;
if(sIndexCount==50)break;//如果输入文件比我们的结构长
}

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

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”时应该发生什么。

,因为你已经将其标记为C++,你应该考虑使用<代码> STD::GETLION>代码>从文件中读取行,使用<代码> STD::GETLIN(文件,TrimeByPosixIyCon,'';')//C>解析字段。
您还可以使用
std::istringstream
将文本行中的文本表示形式转换为内部数字格式。

一条建议:不要使用n、i和j等变量。相反,请使用较长的单词,如wordCounter、wordIndex和studentCounter。这将使您在调试所发生的事情时更加清楚。您可以将
char
(单个字符)和
char[]
(字符数组)混淆。您需要将输入的每个字符复制到输出-编写您自己的
stringCopy
函数,因为您不被允许(大概是这样)使用
strcpy
。如果它是
'\n'
';
,你可能想把
继续
。。否则,你将把分隔符复制到你保存的代码中。我被允许使用strcpy…我该怎么做?啊-好吧,看看我的代码示例,让你的生活简单一点。这不是一个简单的问题“完整的解决方案”,而不是“看看你能不能从这里走”的答案。你学习的方法更多…嗯,听起来很复杂,就像C++中的一个初学者一样……你在这行中做什么:偏移= CoptoStoMeCon(TeMp,CNR,Seffy)+ 1;StutsRoalnr= ATOI(TEMP);我实际上是想让它更简单一些。一点结构可以让你的代码保持干净。你可以使用
strtok
?我以为“没有字符串函数”,但可能我错了。我刚刚看到你可以使用
strcpy
。什么是“低级”…据我所知,我们只能使用strcpy,fgetc没有字符串类,只有char[],不知道我们是否可以使用strtok,但你可以告诉我它的优点…:)我为你写了
copyToSemicolon
。(在本例中)它比
strtok
更容易使用。在第一次调用中,你扫描
cnr
第一个分号,并将指向该字符串的指针传递到
temp
(实际上,要使其工作,您需要
char*temp;
而不是
char-temp[50]);
,然后
strtok
“记住“字符串,以及它到达的位置…因此您将它作为第一个参数传递
NULL
,它“继续运行”。它正是用于此应用程序的。查找它!使用缓冲区是个好主意,但我不允许使用字符串类…仅使用char[]类…什么是缓冲区类?你能给我一个例子吗?@user2774480你已经有了它。缓冲区是暂时保存一个值的东西。在你的例子中,你使用了
wort
作为缓冲区。你已经对我给你的所有伪代码进行了编码;我只是对它进行了重新排序以提高效率(并且更易于调试).好的,我用我的列表测试了我的新代码,我还没有应用你的版本,我仍然不明白为什么在我的测试文件的最后两行中,输出开始变得奇怪,在那之后,只是随机垃圾被填充到数组中,因为它没有达到最大数组大小,并且它填充了内存中的随机内容,我猜…我怎么能到达文件末尾(EOF)后“关闭”数组?@user2774480 sizeof(mystud)不完全是您想要的。这将给您50。您想要
sizeof(mystud)*sizeof(Stud)
,在大多数编译器上,这将为您提供50*68。因此,有效地说,您清除了50个字节,但随后用良好的数据填充它们。@user2774480-我建议您在填充数组时计算“有效”元素的数量,然后只打印
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
}
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
    }
}