将"firstword secondword"从文本文件拉入单个字符数组

pull "firstword secondword" from text file into single char array

本文关键字:单个 数组 字符 文本 firstword secondword 文件      更新时间:2023-10-16

我在读取播放器文件时遇到分段错误:核心转储错误。。我正在尝试将"firstname lastname"添加到播放器结构中。我正在尝试访问"第0"个人并增加他们的名字,因为我需要第一个和最后一个,我不能像我对卡片值(未显示)"heart two 2"(例如)那样简单地在循环中fin>>people[I].name

// deck of cards
// below are initializations
#include <iostream>
#include <fstream>
#include <ctime>
#include <stdlib.h>
#include <string>
using namespace std;
//globals
const int maxCards = 52;
//Structs
struct card {
    char suit[8];
    char rank[6];
    int cvalue;
    char location;
};
struct player {
    char name[];
    int total;
    card hand[];
};
//program
int main()
{
    char tempfName[100];
    char templName[100];
    //create struct array(s)
    card deck[52];
    card shuffledDeck[52];
    player people[4];
    //set defalt values
    for(int i=0;i<4;i++)
    {
        strcopy(people[i].name,"first last");
    }
    //open player names file
    ifstream fin2;
    string fin2Name;
    //get file name from user
    cout << "Enter player file name...(Players.txt)" << endl;
    getline(cin,fin2Name);
    fin2.open(fin2Name.c_str());
    //check if Players.txt opens correctly
    if(!fin2.good())
    {
        cout << "Error with player file!" << endl;
        return 0;
    }
    else
    {
        int j =0;
        //fin2 >> people[j].name;  //prime file
        while(fin2.good())
        {
            //find the length
            int index =0, length=0;
            while(tempfName[length] != '')
            {
                length++;
            }
            //now add space after first name
            tempfName[length] = ' ';
            length++;
            while(templName[index] != '')
            {
                tempfName[length] = templName[index];
                length++;
                index++;
            }
            tempfName[length]='';
            int counter =0;
            while(templName[counter] != '')
            {
                people[0].name[counter] = templName[counter]; //testing program on "0th" people
                counter++;
            }
        }
    }
}

在结构中,name[]hand[]的大小不确定。因此,很难从中解读出任何东西。

然后,一旦打开流,就要尝试确定单元化tempfName[]的长度。这不好:你不确定它是null终止的,你会越界的!这就是你的segfault的起源。

考虑通过将它们声明为:来初始化它们

char tempfName[100]{};
char templName[100]{};

一旦修复了这一问题,您的代码仍然会在while (fin2.good())上永远循环,而不会读取任何内容,并勇敢地在tempfName中添加一个空格,直到超出限制。

现在,假设您已经解决了所有这些问题,为name设置一个长度,并取消对读取fin2 >> people[j].name;的流的注释,那么您仍然会遇到非常危险的情况:如果数据比您之前看到的更长,它将被截断,并且名称不会有终止的"\0"。

建议1:

每当考虑存储字符串时,请考虑使用std::string而不是char[]。示例:

struct player {
    string name = "first last" ;   // initialisation value: no strcpy() needed !! 
    int total;
    card hand[5];  // length ?
};

建议2:

循环使用流读取作为循环条件:

    while (fin2 >> people[j].name) { ///!!!
         ...
         j++;  // don't foget to increment your counter 
    }   

但是要小心,因为>>一次读取一个字符串,该字符串以第一whilespace结尾(所以只有名字)。

如果你采用建议1,那么写起来就很容易了:

    while (fin2 >> tempfName >> templName) {  ///!!!
        people[j++].name = tempfName + " " + templName; 
     }    

它应该执行与循环几乎相同的事情,但指令和风险要少得多。

建议3:

如果你的玩家数量是固定的,定义最大常数,并使用for而不是一段时间来读取你的数据:

 const int max_player = 4; 
 player people[max_player];
 ... 
 for (j=0; j<max_player && (fin2 >> people[j].name); j++)  // instead of the former while

如果你的4的极限是arbirary,考虑使用向量。但现在这是另一回事了。

您的struct player定义无效:

struct player {
    char name[];
    int total;
    card hand[];
};

C字符串字段namehand需要具有长度,例如

struct player {
    char name[32];
    int total;
    card hand[32];
};

您的编译器应该为此给出一个错误("不完整类型")。

还要注意的是,由于您正在编写C++代码,因此最好使用std::string而不是C风格的char *字符串——这将更容易、更健壮,而且您不会混合使用C和C++习惯用法。