error: invalid conversion from 'char*' to 'char' on lines 26,36 - c++

I am working on reading a file and formatting array so I can work on them with other stuff but I am stuck in the beginning. It says I can't change from char* to char but my token is not char*.
#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <string>
#include <stdio.h>
using namespace std;
void get_input(string teams[][2]) {
string infile;
double value;
char buffer[100];
char token;
stringstream ss;
cout << "Enter the input file: ";
cin >> infile;
ifstream file;
file.open (infile.c_str());
if (file.is_open()) {
int teamcounter = 0;
while (file.getline (buffer, 100)) {
int counter = 0;
token = strtok (buffer, ",");
while (token) {
if (counter == 0) {
teams[teamcounter][counter] = token;
}
else if ((counter == 1) || (counter == 2)) {
ss << token;
ss >> value;
teams[teamcounter][counter] = value;
}
token = strtok (NULL, ",");
counter++;
}
teamcounter++;
}
file.close();
}
else {
cout << "Unable to open file";
}
for (int i = 0; i< 7; i++){
for (int j = 0; j<2;j++){
cout << teams[i][j] << " ";
}
cout << endl;
}
}
Is making my array into string make me unable to put float or double values to them?
int main() {
cout << "Welcome to the football bracket game!" << endl;
string teams[7][2];
get_input(teams);
}
My input text format is like this:
Trojans, 0.80, 0.60
Bruins, 0.20, 0.30
Bears, 0.60, 0.50
Trees, 0.50, 0.40
Ducks, 0.40, 0.80
Beavers, 0.50. 0.10
Huskies, 0.80, 0.40
Cougars, 0.10, 0.90

char token;
token = strtok (buffer, ",");
token is of type char, strtok returns a char*. They are not of the same type and the compiler is complaining (logically) about it. strtok returns the pointer to the next token of the processed input char* so indeed there's no sense in assigning it to a single character.
Compiler is indeed unable to find a way to convert from the returnd char* to char, there's nothing strange in the error.

You defined variable token as having type char
char token;
while function strtok returns an obhect of type char * .So these statements
token = strtok (buffer, ",");
and
token = strtok (NULL, ",");
are invalid. I think you meant
char *token;
Also you defined array teams as an array of elements of type std::string
string teams[7][2];
However in function get_input you try to assign a value of type double to an object of type std::string
double value;
//...
teams[teamcounter][counter] = value;
Also it would be more correct if the function had second parameter that specifies the size of the first dimension of the array
void get_input(string teams[][2], int n );
and would be called as
get_input(teams, 7);
You should check how many lines of the file you entered.

strtok() returns a char* but your token variable is declared as char. It needs to be declared as char* instead.
Update: Since you are using C++, I strongly suggest you use C++, don't mix C and C++ together. Ignore strtok() even exists, eg:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
struct Team
{
std::string Name;
double Value1;
double Value2;
};
void get_input(std::vector<Team> &teams)
{
std::string infile;
std::ifstream file;
std::cout << "Enter the input file: ";
std::cin >> infile;
file.open (infile.c_str());
if (!file.is_open())
{
std::cout << "Unable to open file";
return;
}
std::string line;
while (std::getline(file, line))
{
Team team;
std::istringstream ss(line);
std::string token;
int counter = 0;
while (std::getline(ss, token, ","))
{
switch (counter)
{
case 0:
team.Name = token;
break;
case 1:
std::stringstream(token) >> team.Value1;
break;
case 2:
std::stringstream(token) >> team.Value2;
break;
}
++counter;
}
teams.push_back(team);
}
}
int main()
{
std::cout << "Welcome to the football bracket game!" << std::endl;
std::vector<Team> teams;
get_input(teams);
for (std::vector<Team>::iterator iter = teams.begin(); iter != teams.end(); ++iter)
{
std::cout << iter->Name << ": " << iter->Value1 << " " iter->Value2 << std::endl;
}
}

Related

Trouble with cin.getline and strstr

Im trying to write a simple program that will read in a list of names and allow you to search through them. Im having a problem with my cin.getline and my strstr. Im new to c++ and im have a hard time getting my head around c string and its functions.
The error I get from the cin.getline is cannot convert parameter 1 from 'std::ifstream' to 'char *'
and cannot convert parameter 1 from 'char' to 'char *'
The error I get from the strstr is error C2665: 'strstr' : none of the 2 overloads could convert all the argument types
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 50;
int size = 0;
// Array of product descriptions
char phoneDirectory[SIZE];
char name; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail())
{
cin.getline(inFile,phoneDirectory[size]);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
cin.getline(name, SIZE);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index], name);
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}
I cant seem to fix the cin.getline's and the strstr.
char name doesn't represent a string, but 1 single character. The getline function accepts a character pointer and an integer, and in your case you're feeding it a character and an integer.
Also, in c++ I'd suggest using std::string instead of characters array. It's much easier to handle and less error prone.
I've corrected your code to do what I think you're looking for. let me know if that's not what you're looking for:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int SIZE = 50;
int size = 0;
// Array of product descriptions
string phoneDirectory[SIZE];
string name; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail())
{
getline(inFile, phoneDirectory[size]);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
getline(cin, name);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index].c_str(), name.c_str());
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}
If you really want to stick with the characters array, here's what your code should look like:
#include <iostream>
#include <string>
#include <fstream>
#include <cstring>
using namespace std;
int main()
{
const int DIRECTORY_SIZE = 50;
const int STRING_SIZE = 50;
int size = 0;
// Array of product descriptions
char phoneDirectory[DIRECTORY_SIZE][STRING_SIZE];
char name[STRING_SIZE]; // For user input
char *strPtr = NULL; // Result from strstr
ifstream inFile;
inFile.open("phonebook");
while (!inFile.fail() && size < DIRECTORY_SIZE)
{
inFile.getline(phoneDirectory[size], STRING_SIZE);
size++;
}
inFile.close();
// Get user input
cout << "Enter a name to search for: ";
cin.getline(name, STRING_SIZE);
// Search for the string
int index = 0;
while(index < size)
{
strPtr = strstr(phoneDirectory[index], name);
if (strPtr != NULL)
break;
index++;
}
// Output the result of the search
if (strPtr == NULL)
cout << "No matching names were found.\n";
else
cout << phoneDirectory[index] << endl;
return 0;
}

How do you parse a c-string?

Hi I'm trying to take a c-string from a user, input it into a queue, parse the data with a single space depending on its contents, and output the kind of data it is (int, float, word NOT string).
E.g. Bobby Joe is 12 in 3.5 months \n
Word: Bobby
Word: Joe
Word: is
Integer: 12
Word: in
Float: 3.5
Word: months
Here's my code so far:
int main()
{
const int maxSize = 100;
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
std::cin.getline(cstring, maxSize, '\n');
//Keyboard Buffer Function
buffer::keyboard_parser(cstring);
return EXIT_SUCCESS;
}
Function:
#include <queue>
#include <string>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <vector>
namespace buffer
{
std::string keyboard_parser(char* input)
{
//Declare Queue
std::queue<std::string> myQueue;
//Declare String
std::string str;
//Declare iStringStream
std::istringstream isstr(input);
//While Loop to Read iStringStream to Queue
while(isstr >> str)
{
//Push onto Queue
myQueue.push(str);
std::string foundDataType = " ";
//Determine if Int, Float, or Word
for(int index = 0; index < str.length(); index++)
{
if(str[index] >= '0' && str[index] <= '9')
{
foundDataType = "Integer";
}
else if(str[index] >= '0' && str[index] <= '9' || str[index] == '.')
{
foundDataType = "Float";
break;
}
else if(!(str[index] >= '0' && str[index] <= '9'))
{
foundDataType = "Word";
}
}
std::cout << "\n" << foundDataType << ": " << myQueue.front();
std::cout << "\n";
//Pop Off of Queue
myQueue.pop();
}
}
}
Right now with this code, it doesn't hit the cout statement, it dumps the core.
I've read about using the find member function and the substr member function, but I'm unsure of how exactly I need to implement it.
Note: This is homework.
Thanks in advance!
UPDATE: Okay everything seems to work! Fixed the float and integer issue with a break statement. Thanks to everyone for all the help!
Your queue is sensible: it contains std::strings. Unfortunately, each of those is initialised by you passing cstring in without any length information and, since you certainly aren't null-terminating the C-strings (in fact, you're going one-off-the-end of each one), that's seriously asking for trouble.
Read directly into a std::string.
std::istreams are very useful for parsing text in C++... often with an initial read of a line from a string, then further parsing from a std::istringstream constructed with the line content.
const char* token_type(const std::string& token)
{
// if I was really doing this, I'd use templates to avoid near-identical code
// but this is an easier-to-understand starting point...
{
std::istringstream iss(token);
int i;
char c;
if (iss >> i && !(iss >> c)) return "Integer";
}
{
std::istringstream iss(token);
float f;
char c; // used to check there's no trailing characters that aren't part
// of the float value... e.g. "1Q" is not a float (rather, "word").
if (iss >> f && !(iss >> c)) return "Float";
}
return "Word";
}
const int maxSize = 100; // Standard C++ won't let you create an array unless const
char cstring[maxSize];
std::cout << "\nPlease enter a string: ";
if (std::cin.getline(cstring, maxSize, '\n'))
{
std::istringstream iss(cstring);
std::string token;
while (iss >> token) // by default, streaming into std::string takes a space-...
token_queue.push(token); // ...separated word at a time
for (token_queue::const_iterator i = token_queue.begin();
i != token_queue.end(); ++i)
std::cout << token_type(*i) << ": " << *i << '\n';
}

Strange behaviour assigning value from file to unsigned char variable

I have been looking for an error in a code that I am using for finite element methods. The point is that I have to get some data from a file to identify the material of a cell. The type of this material_id is unsigned char , and here is the problem.
When reading the data from the file, different ways to assign the value to a unsigned char variable gives different result. I have fixed the problem, but I am still wondering why it is working in a different way. Here you have a sample code reproducing the different behavior:
#include <map>
#include <sstream>
#include <fstream>
#include <string>
#include <iostream>
#include <vector>
#include <stdlib.h>
namespace types
{
//typedef unsigned int material_id;
typedef unsigned char material_id;
}
namespace Utilities
{
int string_to_int(const std::string & str)
{
return atoi(str.c_str());
}
}
template<typename Number>
void parseVector_1(std::ifstream & myfile,
std::vector<Number> & mat_id)
{
Number num;
std::string line, bin;
if (myfile.is_open())
{
getline (myfile,line);
std::istringstream iss(line);
while ( iss.good() )
{
iss >> bin; // option 1
num = Utilities::string_to_int(bin); // option 1
mat_id.push_back(num);
}
}
else std::cout << "Unable to open file";
}
template<typename Number>
void parseVector_2(std::ifstream & myfile,
std::vector<Number> & mat_id)
{
Number num;
std::string line, bin;
if (myfile.is_open())
{
getline (myfile,line);
std::istringstream iss(line);
while ( iss.good() )
{
iss >> num; // option 2
mat_id.push_back(num);
}
}
else std::cout << "Unable to open file";
}
int main()
{
unsigned int n_mat;
std::vector<types::material_id> mat_id_1;
std::vector<types::material_id> mat_id_2;
std::map<types::material_id, double> D1v;
D1v[0] = 0.0;
D1v[1] = 1.0;
D1v[2] = 2.0;
D1v[3] = 3.0;
D1v[4] = 4.0;
std::ifstream myfile1 ("materials.dat");
parseVector_1(myfile1, mat_id_1);
myfile1.close();
std::ifstream myfile2 ("materials.dat");
parseVector_2(myfile2, mat_id_2);
myfile2.close();
n_mat = mat_id_1.size();
std::cout << "option 1: ";
for (unsigned int i = 0; i < n_mat; ++i)
std::cout << "mat["<<i<<"]=" << D1v[mat_id_1[i]] << " ";
std::cout << std::endl;
n_mat = mat_id_2.size();
std::cout << "option 2: ";
for (unsigned int i = 0; i < n_mat; ++i)
std::cout << "mat["<<i<<"]=" << D1v[mat_id_2[i]] << " ";
std::cout << std::endl;
return 0;
}
The content of the "materials.dat" file is the following line:
0 1 2 3 4
And here is the output of the execution:
$ unsignedchar_problem.exe
option 1: mat[0]=0 mat[1]=1 mat[2]=2 mat[3]=3 mat[4]=4
option 2: mat[0]=0 mat[1]=0 mat[2]=0 mat[3]=0 mat[4]=0 mat[5]=0
Can anyone give some insight why option 1 is working fine, but option 2 is not? Is it dependent on the compiler/platform of it is always like that?
As an additional information, the problem was because the material_id type was defined as unsigned int by the other user in his computer, so it was working without any problem.
Extracting unsigned char from an istream reads a single character and stores that character's numeric value into the destination variable. So mat_id_2[0] will contain the numeric value of '0', which is probably 48 (if your system is ASCII).
Extracting a non-chararacter integral type will read an integer and store the value of that integer, as you were expecting.

Storing a variable in C++

The problem is that file won't be read...Apparently there's a problem with an array but I don't really know how fix this issue...I'm a beginner to C++ 'arrays' and 'strings'...
My file should read the code, then translate the file, then output the text into a new file..
#include <iostream>
#include <iomanip>
#include <string>
#include <sstream>
#include <fstream>
#include <math.h>
#include <stdio.h>
#include <string>
#include <string.h>
using namespace std;
int main()
{
// Declarations
string reply;
string inputFileName;
ifstream inputFile;
ofstream outFile;
char character;
cout << "Input file name: ";
getline(cin, inputFileName);
// Open the input file.
inputFile.open(inputFileName.c_str());
// Check the file opened successfully.
if ( ! inputFile.is_open()) {
cout << "Unable to open input file." << endl;
cout << "Press enter to continue...";
getline(cin, reply);
return 1;
}
// This section reads and echo's the file one character (byte) at a time.
while (inputFile.peek() != EOF) {
inputFile.get(character);
//cout << character;
//Don't display the file...
char cipher[sizeof(character)];
//Caesar Cipher code...
int shift;
do {
cout << "enter a value between 1-26 to encrypt the text: ";
cin >> shift;
}
while ((shift <1) || (shift >26));
int size = strlen(character);
int i=0;
for(i=0; i<size; i++)
{
cipher[i] = character[i];
if (islower(cipher[i])) {
cipher[i] = (cipher[i]-'a'+shift)%26+'a';
}
else if (isupper(cipher[i])) {
cipher[i] = (cipher[i]-'A'+shift)%26+'A';
}
}
cipher[size] = '\0';
cout << cipher << endl;
}
cout << "\nEnd of file reached\n" << endl;
// Close the input file stream
inputFile.close();
cout << "Press enter to continue...";
getline(cin, reply);
return 0;
}
To make it short: You're on c++ so just don't use the whole C stuff.
Don't use character arrays, use std::string
Don't use islower(char) but use std::islower(char,locale)
Don't use C-style arrays but std::array (compile time constant size) or std::vector (dynamic size)
You'll want to have it more like this:
#include <string>
#include <fstream>
#include <iostream>
#include <stdexcept>
#include <locale>
int main (void)
{
std::string input_filename;
std::cout << "Input file name: ";
std::getline(std::cin, input_filename);
unsigned int shift;
do
{
std::cout << "Enter a value between 1-26 to encrypt the text: ";
std::cin >> shift;
}
while ((shift == 0) || (shift > 26));
try
{
std::string filestring;
std::ifstream input(input_filename, std::ios_base::in);
if (input)
{
input.seekg(0, std::ios::end);
filestring.reserve(input.tellg());
input.seekg(0, std::ios::beg);
filestring.assign
(std::istreambuf_iterator<char>(input),
std::istreambuf_iterator<char>());
}
else
{
std::string error_string("Reading failed for: \"");
error_string.append(input_filename);
error_string.append("\"");
throw std::runtime_error(error_string);
}
std::string result;
result.reserve(filestring.size());
std::locale const loc;
for (auto character : filestring)
{
char const shifter(std::islower(character, loc) ? 'a' : 'A');
result.push_back((character-shifter+shift)%26+shifter);
}
std::cout << result << std::endl;
}
catch (std::exception & e)
{
std::cout << "Execution failed with an exception: " << std::endl;
std::cout << e.what() << std::endl;
}
}
This solution requires C++11 support. If you do not have C++11 you can replace the loop with:
size_t const N(filestring.length());
for (size_t i(0u); i<N; ++i)
{
char const shifter(std::islower(filestring[i], loc) ? 'a' : 'A');
result.push_back((filestring[i]-shifter+shift)%26+shifter);
}
From looking at your code, "character" is declared as a char which means it can only store one byte of information. Yet later on you start using it as if it was an array of characters.
You are also declare "cipher" as a char array that you manual manage like a string which is error prone. The real issue however is that you're mixing C-like code in C++. In other words, the way your code is written isn't considered idiomatic C++.
Pixelchemist already went over the important points so I'll just present a minimal refactored working example of your above code:
#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>
using namespace std;
int main()
{
string filename;
cout << "enter input file: ";
cin >> filename;
ifstream inputFile( filename.c_str() );
string plaintext;
do
{
plaintext += inputFile.get();
}while(inputFile);
cout << plaintext << endl;
string &ciphertext = plaintext;
//Caesar Cipher code...
int shift = rand() % 26 + 1;
for(size_t i = 0; i < ciphertext.size(); ++i)
{
if (islower(ciphertext[i])) {
ciphertext[i] = (ciphertext[i] - 'a' + shift) % 26 + 'a';
}
else if (isupper(ciphertext[i])) {
ciphertext[i] = (ciphertext[i] - 'A' + shift) % 26 + 'A';
}
}
cout << ciphertext << endl;
}
You'll notice in the refactor that I've done away with char and char[] arrays altogether and replaced it with std::string. I'm also performing the cipher operation inplace on the plaintext input. This is done by making a reference alias to plaintext called ciphertext for readability. Also in my example, the shift is done randomly for prototyping but you should change it to take it as a user input instead.
You are working with a single char, thats e.g. just one letter or a number. So the whole thing with size handling is useless, because the size is always 1. You probably should use const char*. But then you can't use filestream.get() at all, because it only returns a single char (not and cstring aka const char*).
And you can use fstream.get() as condition for the loop, so you don't need to ask for the eof flag.
char my_char;
std::ifstream infstream("filename.txt");
if(!infstream.isopen())
return -1;
while(infstream.get(my_char) {
//do some stuff
}
or
std::string my_string;
std::ifstream infstream("filename.txt");
if(!infstream.isopen())
return -1;
while(infstream >> my_string) {
//do some stuff
}
for dynamic arrays in C++ use std::vector or std::list or ... one of the other STL containers, so you don't have to waste your time on memory management and using static sized arrays.
And std::string is the way to go for strings in C++. It is something similar to the STL containers, but just for char's.

how to insert data from a text file into an array of struct

I need to read data from a text file, and insert the data in an array of struct. The data file is in the following format:
productname price quantity
my main concern is to read the product name, which consist of one, and two words. Should I approach product name as a c-string or as a string literal?
any help appreciated
#include <iostream>
#include <fstream>
using namespace std;
const int SIZE = 15; //drink name char size
const int ITEMS = 5; //number of products
struct drinks
{
char drinkName[SIZE];
float drinkPrice;
int drinkQuantity;
};
int main()
{
//array to store drinks
drinks softDrinks[ITEMS];
//opening file
ifstream inFile;
inFile.open("drinks.txt");
char ch;
int count = 0; //while loop counter
if(inFile)
{
while(inFile.get(ch))
{
//if(isalpha(ch)) { softDrinks[count].drinkName += ch; }
//if(isdigit(ch)) { softDrinks[count].drinkPrice += ch; }
cout << ch;
}
cout << endl;
count++;
}
else
{
cout << "Error opening file!\n";
system("pause");
exit(0);
}
system("pause");
return 0;
}
Since you ask for "any help", here's my view: Forget everything you wrote, and use C++:
#include <fstream> // for std::ifstream
#include <sstream> // for std::istringstream
#include <string> // for std::string and std::getline
int main()
{
std::ifstream infile("thefile.txt");
std::string line;
while (std::getline(infile, line))
{
std::istringstream iss(line);
std::string name;
double price;
int qty;
if (iss >> name >> price >> qty)
{
std::cout << "Product '" << name << "': " << qty << " units, " << price << " each.\n";
}
else
{
// error processing that line
}
}
}
You could store each line of data in a std::tuple<std::string, int, double>, for example, and then put those into a std::vector as you go along.