Load variable from string - c++

How should i go about loading a variable from a string?:
for example, this is my text file:
int: 10
int: 25
int: 30
How could i load these into a array? this is the code i use to load the strings:
string loadedB[100];
ifstream loadfile;
loadfile.open("ints.txt");
if(!loadfile.is_open()){
MessageBoxA(0, "Could not open file!","Could not open file!", MB_OK);
return;
}
string line; int i = -1;
while(getline(loadfile, line)){ i++;
loadedB[i] = line;
}
loadfile.close();
for(int x = 0; x < count(loadedB); x++){
cout << loadedB[x] << endl;
}
I would like to do something like:
int intarray[100];
loadfromstringarray(loadedB, intarray);
That code would take the part of the string ( the numeric one ) and would put that value into the array, like intarray[0] = 10; and so on
EDIT: istringstream is the solution!

I personally like the good old std::istringstream object:
const std::string example = "int: 10";
std::string prompt;
int value;
std::istringstream parse_stream(example);
std::getline(parse_stream, prompt, ':');
parse_stream >> value;

I personally like the good old sscanf C function:
int intarray[100];
int i = 0;
while(getline(loadfile, line) && i < sizeof(intarray)/sizeof(*intarray))
{
sscanf(line.c_str(), "int: %d", intarray + i++);
}

Use stoi:
vector<int> ints;
ifstream loadfile("ints.txt");
string line;
while(getline(loadfile, line)) {
ints.push_back(stoi(line.substr(5))); // skip the first 5 chars of each line
}
for(int i : ints) {
cout << i << endl;
}
Output:
10
25
30

Related

c++ nested while loop runs only once

Please can you advise, why the inner loop runs only once?
I'd like to add suffix to each line of input file and then store the result in output file.
thanks
For example:
Input file contains:
AA
AB
AC
Suffix file contains:
_1
_2
Output file should contain:
AA_1
AB_1
AC_1
AA_2
AB_2
AC_2
My result is :
AA_1
AB_1
AC_1
Code:
int main()
{
string line_in{};
string line_suf{};
string line_out{};
ifstream inFile{};
ofstream outFile{"outfile.txt"};
ifstream suffix{};
inFile.open("combined_test.txt");
suffix.open("suffixes.txt");
if (!inFile.is_open() && !suffix.is_open()) {
perror("Error open");
exit(EXIT_FAILURE);
}
while (getline(suffix, line_suf)) {
while (getline(inFile, line_in))
{
line_out = line_in + line_suf;
outFile << line_out << endl;
}
inFile.close();
outFile.close();
}
}
IMHO, a better method is to read the files into vectors, then iterate through the vectors:
std::ifstream word_base_file("combined_test.txt");
std::ifstream suffix_file("suffixes.txt");
//...
std::vector<string> words;
std::vector<string> suffixes;
std::string text;
while (std::getline(word_base_file, text))
{
words.push_back(text);
}
while (std::getline(suffix_file, text))
{
suffixes.push_back(text);
}
//...
const unsigned int quantity_words(words.size());
const unsigned int quantity_suffixes(suffixes.size());
for (unsigned int i = 0u; i < quantity_words; ++i)
{
for (unsigned int j = 0; j < quantity_suffixes; ++j)
{
std::cout << words[i] << suffix[j] << "\n";
}
}
Edit 1: no vectors
If you haven't learned about vectors or like to thrash your storage device you could try this:
std::string word_base;
while (std::getline(inFile, word_base))
{
std::string suffix_text;
while (std::getline(suffixes, suffix_text))
{
std::cout << word_base << suffix_text << "\n";
}
suffixes.clear(); // Clear the EOF condition
suffixes.seekg(0); // Seek to the start of the file (rewind).
}
Remember, after the inner while loop, the suffixes file is at the end; no more reads can occur. Thus the file needs to be positioned at the start before reading. Also, the EOF state needs to be cleared before reading.

Parse (split) a txt file with a string and int in c++

im a Student and new to this site. I want to split my txt file with my highscore data back to my Highscore List.
The txt file stores my Highscore like name:score
My parsing is not working and i dont know why?
I just want to split it to name and score again and then put it in my HighscoreList.
If you have any question about the code just ask :)
#include "highscore.h"
highscore::highscore(){
}
struct highscore::Player{
string spielerName;
int score;
};
void highscore::writeHighscore(string name, int score ,int playerNumberx){
Player HighscoreListe[100];
for(int i=0;i<=99;i++){
HighscoreListe[i].score = {0};
}
for(int i=0;i<=99;i++){
HighscoreListe[i].spielerName = "leer";
}
HighscoreListe[playerNumberx].spielerName = name;
HighscoreListe[playerNumberx].score = score;
int i, j,temp;
string temp1;
ifstream myfile("scores.txt");
string line;
//heres the point where i need help!!
if (myfile.is_open()){
int z=0;
while(getline(myfile, line)){
string name1;
string score1;
int d = 20;
while(line[z] != ':'){
name1 += line[z];
z++;
}
z = z+2;
while(line[z] != '\0'){
score1 += line[z];
z++;
}
HighscoreListe[d].spielerName = name;
HighscoreListe[d].score = score;
d++;
}
myfile.close();
}else cout << "Unable to open file" << endl;
for(i = 0; i<100; i++) {
for(j = i+1; j<100; j++)
{
if(HighscoreListe[j].score < HighscoreListe[i].score) {
temp = HighscoreListe[i].score;
temp1 = HighscoreListe[i].spielerName;
HighscoreListe[i].score = HighscoreListe[j].score;
HighscoreListe[i].spielerName = HighscoreListe[j].spielerName;
HighscoreListe[j].score = temp;
HighscoreListe[j].spielerName = temp1;
}
}
}
ofstream myfilex("scores.txt");
if (myfilex.is_open()){
for(int i = 99;i>89;i--){
myfilex << HighscoreListe[i].spielerName << ":" << HighscoreListe[i].score<<endl;
}
myfilex.close();
}
else cout << "Unable to open file" << endl;
}
void highscore::readHighscore(){
string line;
ifstream myfile("scores.txt");
if (myfile.is_open()){
while(getline(myfile, line)){
cout << line << endl;
}
}
else cout << "Unable to open file" << endl;
}
Make a >> overload for highscore::Player.
In the >> overload
Use std::getline to read a line from the input stream.
Create a std::istringstream out of the line.
Use std::getline to read up to the : from the istringstream into a local string name;.
Use another std::getline to read the rest of the line into a string.
Convert the string into an int with std::stoi and store into a local int score;. Make sure you provide a pos argument.
Ensure that the entire string was converted by comparting the pos argument with the string's length.
If nothing went wrong, store name and score into the highscore::Player passed by the caller. Otherwise, set the failbit on the input stream with setstate
return the input stream.
Now the reading code should be something simple like
int scorecount = 0;
while (myfile >> HighscoreListe[scorecount])
{
scorecount++;
}

Trouble with pointers and reading information into an array

I'm having some issues when trying to read in some values to a dynamically allocated array. Everything looks okay to me, but when the code is run, only the last entry into the array is shown. The code is below. If you could give me some recommendations I would appreciate it.
ifstream infile;
infile.open("MovieStatistics.txt");
int numOfStudents = 0;
string first, last, line;
int movies;
int *numMovies = nullptr;
string *names = nullptr;
if (!infile) {
cout << "Error opening file";
} else {
while (getline(infile, line)) {
numOfStudents++;
stringstream ss(line);
ss >> first >> last >> movies;
}
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
}
for (int i = 0; i < numOfStudents; i++) {
names[i] = first + " " + last;
numMovies[i] = movies;
}
Your problem is you assign first and last inside the read loop but you don't store the values in an array or vector so they contain the last values.
To get it to work you could edit the code to:
ifstream infile;
infile.open("data.txt");
int numOfStudents = 0;
string first, last, line;
int movies;
int *numMovies = nullptr;
string *names = nullptr;
// get the number of students
while (getline(infile, line))
numOfStudents++;
numMovies = new int[numOfStudents];
names = new string[numOfStudents];
// clear the buffer
infile.clear();
infile.seekg(0, ios::beg);
int i = 0;
while(getline(infile, line)){
stringstream ss(line);
ss >> first >> last >> movies;
names[i] = first + " " + last;
numMovies[i] = movies;
++i;
}
for(int i = 0; i < numOfStudents; i++)
cout << names[i] << endl;
// don't forget to free memory:
delete[] movies;
delete[] names;
infile.close();
What I recommend is to use class vector:
std::ifstream infile("data.txt");
std::string sLine;
std::vector<std::string> vecNames;
while(getline(infile, sLine))
vecNames.push_back(sLine);
auto size = vecNames.size();
//for(auto x : vecNames)
// std::cout << x << std::endl;
for(int i(0); i != size; ++i)
std::cout << vecNames[i] << std::endl;
infile.close();
So you loop over the file, repeatedly reading data into first, last and movies — overwriting the previous values each time.
Much later, you take the current value of those variables, and write it to your dynamic arrays numOfStudents times.
You probably want to rewind the stream and loop over the file again so that you can pull out all the data; you never actually stored each sample the first time around.

Getting a line of string and converting into a float list

I need to achieve the following:
"4 5 1.3 0 3.1"
This is the input string that I will read from the user, after reading I need to turn this string into a float list according to the [0]th character's size for example the list will be
array[4] = [5.0,1,3,0.0,3.1]
How can I achieve it I tried using getline but didnt work. Thanks in advance.
string line = "4 5 1.3 0 3.1"; // input string
istringstream stream(line); // parser
unsigned count; // how many values
double* values;
if (stream >> count) {
values = new double[count];
for (unsigned ii = 0; ii < count; ++ii) {
stream >> values[ii]; // read one
if (!stream) {
throw std::runtime_error("not enough numbers");
}
}
} else {
throw std::runtime_error("no count at start of line");
}
// do something with values...
delete[] values;
First read the count into an unsigned integer, then loop from 0 to the count, reading into doubles. To read into an array, first allocate one dynamically with the correct size. Better, use a std::vector, which will handle the allocations for you.
#include <iostream>
#include <memory>
#include <sstream>
#include <string>
int main() {
std::string line;
std::getline(std::cin, line);
std::istringstream ss(line);
size_t num_values = 0;
if (! (ss >> num_values) ) {
std::cerr << "Could not read the integer number of values!\n";
return 1;
}
auto values = std::make_unique<double[]>(num_values);
double tmp;
for (size_t idx = 0; idx < num_values; ++idx) {
if (! (ss >> values[idx])) {
std::cerr << "Could not convert the " << idx << "th value!\n";
return 1;
}
}
// Validate solution: print the contents of the vector
for (size_t idx = 0; idx < num_values; ++idx) {
std::cout << values[idx] << " ";
}
std::cout << "\n";
}
[live example]
This solution uses a dynamically allocated array, and ensures that its memory is correctly cleaned up by wrapping it in a std::unique_ptr, created via a call to std::make_unique.

Reading Input From File and Storing into 2D Array

I need to read in a text file that contains only integers and each one is separated by new line. example would be:
0
1
2
...
64
repeating 0 to 64 64 times
Essentially the file is 64*64 lines long, containing an integer for each line.
I need to store each integer (line) in ldisk, my 2D array, but am having serious problems doing so. I understand my code has an error because I am trying to store a string in a char, but I am not sure how to get around this. By the way, ldisk must be a 2-D array of chars. I would love some advice/feedback on my current code posted below, or an alternative solution.
NOTE: I am a beginner at C++
PS:
I know similar topics exist, but mine is more to the problem of getting around the type conversion or just converting it properly so I can store more than a single digit integer into my 2D array, because I have it working where I can store only the first digit where I want in my 2D array, but run into problems if there is more than 1 digit.
int main(){
char **ldisk;
ldisk = new char*[64];
for (int i = 0; i<64; i++)
{
ldisk[i]= new char[64];
}
int counter = 0;
string line;
ifstream inFile("example2.txt");
while ( getline(inFile, line))
{
int first, second;
first = counter/64;
second = counter%64;
cout << line;
ldisk[first][second]= line;
}
return 0;
}
EDIT:
My apologies I have no idea how to do a table.
I want ldisk[0][0] to be 0,
then ldisk[0][1] to be 1,
then ldisk[0][2] to be 2,
etc,
etc,
then ldisk[0][63] to be 64
Eventually it will fill up such that ldisk[63][63] = 64
This is the problem:
ldisk[first][second]= line;
The type of ldisk[first][second] is char. You are trying to assign a std::string to it.
You can make your life a lot simpler by using a std::vector<std::string>.
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
using namespace std;
int main(){
vector<string> ldisk;
int counter = 0;
string line;
ifstream inFile("example2.txt");
while ( getline(inFile, line))
{
cout << line;
ldisk.push_back(line);
}
return 0;
}
Update
If you must have char** ldisk, you can change main to:
int main()
{
char **ldisk;
ldisk = new char*[64];
for (int i = 0; i<64; i++)
{
ldisk[i]= new char[64];
}
int counter = 0;
string line;
ifstream inFile("example2.txt");
while ( getline(inFile, line) && counter < 64 )
{
cout << line << endl;
if ( line.size() >= 64 )
{
cout << "Line is longer than 63 characters. Copying only 63 characters from it.\n";
strncpy(ldisk[counter], line.c_str(), 63);
ldisk[counter][63] = '\0';
}
else
{
strcpy(ldisk[counter], line.c_str());
}
++counter;
}
return 0;
}
Change your loop to:
for (counter = 0; counter < 64*64; ++counter)
{
int item;
if ( !(inFile >> item) )
{
cerr << "File only contained " << counter << "items.\n";
return 1;
}
if ( item < CHAR_MIN || item > CHAR_MAX )
{
cerr << "Item " << counter << " invalid value " << item << "\n";
return 2;
}
ldisk[counter/64][counter%64] = item;
}
The missing ingredient is that you were not trying to convert the string in your file into an integer value. You may need #include <climits>.