вытащить «firstword secondword» из текстового файла в один массив символов

0

Я получаю ошибку сегментации: ядро сбрасывает ошибку, когда я читаю в файле игроков. Я пытаюсь добавить оба "firstname lastname" в структуру игрока. Я пытаюсь получить доступ к "0-м" людям и увеличивать их имя, потому что мне нужны как первые, так и последние, я не могу просто fin >> people [i].name в просто для цикла, как я делаю для значения карты (не показано) "сердце два 2", например

// 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] != '\0')
            {
                length++;
            }
            //now add space after first name
            tempfName[length] = ' ';
            length++;
            while(templName[index] != '\0')
            {
                tempfName[length] = templName[index];
                length++;
                index++;
            }
            tempfName[length]='\0';
            int counter =0;
            while(templName[counter] != '\0')
            {
                people[0].name[counter] = templName[counter]; //testing program on "0th" people
                counter++;
            }
        }
    }
}
  • 0
    stackoverflow не будет копировать мое форматирование
  • 0
    Предположим, что это strcpy, а не strcopy. Разве вы не хотите использовать std :: string?
Показать ещё 3 комментария
Теги:

2 ответа

0
Лучший ответ

В вашей структуре name[] и hand[] имеют неопределенный размер. Поэтому трудно читать что-либо в них.

Затем, как только вы открыли поток, вы пытаетесь определить длину униалиализованного tempfName[]. Это нехорошо: вы не уверены, что он завершен, и вы выйдете за пределы! Это источник вашего 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:

Если количество игроков фиксировано, определите максимальную константу и вместо a используйте вместо a, чтобы читать ваши данные:

 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, рассмотрите использование векторов. Но эта другая история на данный момент.

  • 0
    tempfName инициализируется..tempfName [100];
  • 1
    @mattmowris: нет - это не инициализация , это просто декларация . Для инициализации вы можете использовать приведенное выше предложение или, например, char tempfName[100] = "";
Показать ещё 3 комментария
0

struct player определение вашего конструктора:

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

C строковые поля name и hand должны иметь длину, например,

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

Ваш компилятор должен дать вам ошибку для этого ("неполный тип").

Следует также отметить, что, так как вы пишете C++ код, то лучше было бы использовать std::string, а не C-стиль char * строки - это будет проще, надежнее, и вы не будете смешивания C и [CN10 ] идиомы.

  • 0
    Я должен использовать строки в стиле c для этого проекта, я постараюсь инициализировать их значениями. это единственная проблема? моя петля выглядит хорошо?
  • 0
    Есть несколько проблем - @Christophe рассмотрел некоторые из них в своем ответе - сначала исправьте проблемы, о которых вы знаете, а затем выполните еще один цикл компиляции / отладки, чтобы увидеть, что еще нужно исправить.
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню