I am suppose to write a program that will read from a text file and store what is inside the text file using structures and regroup and print out the information in the text file. But I have encountered problems with getline. I have try to write getline like this
getline(infile, info.name)
but it doesn't work. I have also include <string> and <cstring> but I still encounter errors like
error C2664: 'std::basic_istream<_Elem,_Traits>
&std::basic_istream<_Elem,_Traits>::getline(_Elem *,std::streamsize)'
: cannot convert parameter 1 from 'int' to 'char *'
and
error C2664: 'std::basic_istream<_Elem,_Traits> &std::basic_istream<_Elem,_Traits>::getline(_Elem
*,std::streamsize,_Elem)' : cannot convert parameter 1 from 'char [10][80]' to 'char *'
The text file that I am suppose to print out is the below text
Isabella Chan Republic of Singapore Libra 23 - 10 -
1993 7 I wish to be good in c++ I wish that
christina grimmie will win the voice I wish that ......
Sorry for the noob question and thanks in advance!
#include <iomanip>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <fstream>
#include <string>
using namespace std;
const int MAX = 80;
const int MAXNO = 10;
enum Zodiac
{
Aquarius, Pisces, Aries, Taurus,
Gemini, Cancer, Leo, Virgo,
Libra, Scorpio, Sagittarius, Capricorn
};
struct Date
{
Zodiac sign;
int day;
int month;
int year;
};
struct Student
{
char name [MAX];
char nationality [MAX];
Date birthDate;
int no; // no of other messages
char wishMessage [MAXNO][MAX];
// Feel free to add in more features
};
void myInfo (fstream&, char [], Student&);
// The above function reads information from the text file
// and store the information in a structure reference parameter
void printOut(Student);
int main()
{
fstream infile;
char fName[MAX];
Student info;
cout << "Enter your info file name: "
cin >> fName;
cout << endl;
myInfo(infile, fName, info);
printOut(info);
}
void myInfo (fstream& infile, char fName[], Student& info)
{
infile.open(fName, ios::in);
if(!infile)
{
cout << "Error file not found!" << endl;
exit(0);
}
infile.getline(info.name, MAX);
infile.getline(info.nationality,MAX);
infile << info.birthDate.sign
<< info.birthDate.day
<< info.birthDate.month
<< info.birthDate.year;
infile.getline(info.no, MAX);
infile.getline(info.wishMessage, MAXNO, MAX);
infile.close();
cout << "Successfully readed!" << endl;
}
void printOut(Student info)
{
cout << "My name is " << info.name << endl;
cout << "My nationality is " << info.nationality << endl;
cout << "My date of birth is " << info.birthDate.day
<< " " << info.birthDate.month << " "
<< info.birthDate.year << endl;
cout << "I am " << info.birthDate.sign << endl;
cout << "\n I have " << info.no << " wishes:" << endl;
}
It seems that you are trying to read into non-strings with getline, whereas it is reading into strings as per documentation.
Extracts characters from the stream as unformatted input and stores them into s as a c-string, until either the extracted character is the delimiting character, or n characters have been written to s (including the terminating null character).
Here are two offending lines:
infile.getline(info.no, MAX);
and
infile.getline(info.wishMessage, MAXNO, MAX);
The former is reading into int, the latter is into a string array.
You will need to first read the strings in, and then make the corresponding conversion operations as desired.
Related
This is the code I'm using to attempt to read two columns of data from a csv file into a vector in
C++. I'm able to read in the headers, but when i continue into reading the actual data I'm getting
an error involing 'stof', which converts string to float. I'm pretty sure that this error
results from stof not being able to find any amount of string to convert to a float, but this makes no sense as the variable inside the parenthesis is indeed a string, that is holding digits.
#include <vector>
#include <iostream>
#include <sstream>
#include <fstream>
#include <string>
using namespace std;
int main(int argc, char** argv)
{
ifstream inFS;
string line;
string rm_in, medv_in;
const int MAX_LEN = 1000;
vector<double> rm(MAX_LEN);
vector<double> medv(MAX_LEN);
cout << "Opening file MyData.csv" << endl;
inFS.open("MyData.csv");
if(!inFS.is_open())
{
cout << "Could not open file MyData.csv" << endl;
return 1;
}
cout << "Reading line 1" << endl;
getline(inFS, line);
cout << "heading :" << line << endl;
int numObservations = 0;
while(inFS.good())
{
getline(inFS, rm_in , ',');
getline(inFS, medv_in , '\n');
rm.at(numObservations) = stof(rm_in);
medv.at(numObservations) = stof(medv_in);
numObservations++;
}
rm.resize(numObservations);
medv.resize(numObservations);
}
The error I'm getting is this:
error
I try to connect mysql and c++.
This is the process of trying to put the entered value into the DB.
An error occurs when g++ compiling.
I'm coding using c++98 in visual studio 2017 and CentOS7.
The Mysql Connector used is Mysql++ ver.8.0.
#include "[~ PATH]/mysql++/include/mysql++/cmdline.h"
#include "[~ PATH]/mysql++/include/mysql++/mysql++.h"
#include "[~ PATH]/mysql++/examples/printdata.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <stdio.h>
#include <cstdlib>
using namespace std;
int main(int argc, char *argv[])
{
char buffer[256];
string name;
string id;
string password;
string department;
cout << ">> Sign Up <<\n" << endl;
cout << "1.Name: "; cin >> name;
cout << "2.ID: "; cin >> id;
cout << "3.PASSWORD: "; cin >> pw;
cout << "4.Department: "; cin >> dpt;
mysqlpp::Connection conn(false);
if (conn.connect("member_list", "localhost", "user", "password1234"))
{
**mysqlpp::Query query
= conn.query(sprintf(buffer,"INSERT INTO signup_member (name,id,password,department)
VALUES ('%s','%s','%s','%s')",name.c_str(),id.c_str(),password.c_str(),department.c_str()));**
if (mysqlpp::StoreQueryResult res = query.store()) {
cout << "Sign up SUCCESS!" << endl;
}
else {
cerr << "Sign up FAIL. Try again." << '\n' << query.error() << endl;
return 1;
}
return 0;
}
else {
cerr << "DB connection failed: " << conn.error() << endl;
}
}
When I searched, it said to save the value in the buffer using 'sprintf' and then to save it in the DB. I expect it works well, but it's not.
sign_up.cpp:30:175: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
sprintf return an int which represents
On success, the total number of characters written is returned. This
count does not include the additional null-character automatically
appended at the end of the string. On failure, a negative number is
returned.
& not the char array you wrote your data in as you are expecting so basically you should do :
sprintf(buffer,"INSERT INTO signup_member (name,id,password,department)
VALUES ('%s','%s','%s','%s')",name.c_str(),id.c_str(),password.c_str(),department.c_str());
mysqlpp::Query query
= conn.query(buffer);
The output of the code show gibberish values for all the variables of the Student struct. When the display function is ran.
I've include the relevant code in each of the add and display function for the binary file.
For the second function, does the seekg pointer automatically move to read the the next record each time the for loop runs?
//Student struct
struct Student
{
char name [30];
float labTest;
float assignments;
float exam;
};
//Writing function
afile.open(fileName,ios::out|ios::binary);
Student S;
strcpy(S.name,"test");
S.labTest = rand()%100+1;
S.assignments = rand()%100+1;
S.exam = rand()%100+1;
afile.write(reinterpret_cast<char*>(&S),sizeof(S));
afile.close();
//Reading function
afile.open(fileName,ios::in|ios::binary);
afile.seekg(0,ios::end);
int nobyte = afile.tellg();
int recno = nobyte / sizeof(Student);
Student S;
//Loop and read every record
for(int i = 0;i<recno;i++)
{
afile.read(reinterpret_cast<char*>(&S),sizeof(S));
cout << "Name of Student: " << S.name << endl
<< "Lab mark: " << S.labTest << endl
<< "Assignment mark: " << S.assignments << endl
<< "Exam mark: " << S.exam << endl << endl;
}
afile.close();
There are a lot of problems with your code:
Calling your write function will permanently overwrite the last written data set. You have to add: ios::append, so that new data will be written behind the last data you wrote before.
After you move with afile.seekg(0,ios::end); to get with tellg the file size, you have to go back to the start of the file before reading with afile.seekg(0,ios::beg)
It looks that you use a char array to store a string. This is not c++ style! And it is dangerous how you use it. If you use strcpy, you can copy a string which is longer than the space you reserved for it. So you should prefer std::string for that. But you can't simply write a struct which constains std::string as binary! To get checked copy you can use strncpy, but that is still not c++ ;)
For the second function, does the seekg pointer automatically move to read the the next record each time the for loop runs?
Yes, the file position moves which each successful read and write.
A general remark writing binary data by simply dumping memory content:
That is not a good idea, because you can only read that data back, if you use the same machine type and the same compiler options. That means: A machine with different endianness will read data totally corrupted. Also a different integer type ( 32 bit vs 64 bit ) will break that code!
So you should invest some time how to serialize data in a portable way. There are a lot of libraries around which can be used to read/write also complex data types like std::string or container types.
A hint using SO:
Please provide code which everybody can simply cut and paste and compiled. I did not know what your Student struct is. So I take a lot of assumptions! Is your struct really using char[]? We don't know!
#include <iostream>
#include <fstream>
#include <cstring>
const char* fileName="x.bin";
struct Student
{
char name[100]; // not c++ style!
int labTest;
int assignments;
int exam;
};
// Writing function
void Write()
{
std::ofstream afile;
afile.open(fileName,std::ios::out|std::ios::binary|std::ios::app);
Student S;
strcpy(S.name,"test"); // should not be done this way!
S.labTest = rand()%100+1;
S.assignments = rand()%100+1;
S.exam = rand()%100+1;
afile.write(reinterpret_cast<char*>(&S),sizeof(S));
afile.close();
}
void Read()
{
//Reading function
std::ifstream afile;
afile.open(fileName,std::ios::in|std::ios::binary);
afile.seekg(0,std::ios::end);
int nobyte = afile.tellg();
int recno = nobyte / sizeof(Student);
afile.seekg(0, std::ios::beg);
Student S;
//Loop and read every record
for(int i = 0;i<recno;i++)
{
afile.read(reinterpret_cast<char*>(&S),sizeof(S));
std::cout << "Name of Student: " << S.name << std::endl
<< "Lab mark: " << S.labTest << std::endl
<< "Assignment mark: " << S.assignments << std::endl
<< "Exam mark: " << S.exam << std::endl << std::endl;
}
afile.close();
}
int main()
{
for ( int ii= 0; ii<10; ii++) Write();
Read();
}
EDIT. Apparently, I was a bit too late in responding. Klaus has compiled a better, more comprehensive response dwelling into other problems regarding C-style char [], std::string and the endianness of the platform.
You should append to the file opened for every record. In your code you don't have this, at all. Please write the code in a way we can copy and paste, and test. As a working example, you should write some code that can be compiled and run as below:
#include <algorithm>
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
// Student struct
struct Student {
char name[30];
float labTest;
float assignments;
float exam;
};
// Serializer
void serialize_student(const Student &s, const std::string &filename) {
// Append to the file, do not overwrite it
std::ofstream outfile(filename, std::ios::binary | std::ios::app);
if (outfile)
outfile.write(reinterpret_cast<const char *>(&s), sizeof(Student));
}
// Deserializer
std::vector<Student> deserialize_students(const std::string &filename) {
std::ifstream infile(filename, std::ios::binary);
std::vector<Student> students;
Student s;
while (infile.read(reinterpret_cast<char *>(&s), sizeof(Student)))
students.push_back(std::move(s));
return std::move(students);
}
int main(int argc, char *argv[]) {
// Generate records
std::vector<Student> mystudents;
std::generate_n(std::back_inserter(mystudents), 10, []() {
Student s;
std::strcpy(s.name, "test");
s.labTest = rand() % 100 + 1;
s.assignments = rand() % 100 + 1;
s.exam = rand() % 100 + 1;
return s;
});
// Print and write the records
for (const auto &student : mystudents) {
std::cout << student.name << ": [" << student.labTest << ','
<< student.assignments << ',' << student.exam << "].\n";
serialize_student(student, "students.bin");
}
// Read and print the records
auto records = deserialize_students("students.bin");
std::cout << "===\n";
for (const auto &student : records)
std::cout << student.name << ": [" << student.labTest << ','
<< student.assignments << ',' << student.exam << "].\n";
return 0;
}
i'm working on a program that uses a function and pointers to replace commas with spaces after a user inputs a sentence.
However when I run the program I receive the above error and another that says;
"C++ a value of type "const char *" cannot be used to initialize an entity of type "std::string *""
having trouble with this program and wondering if anyone here can give me a nudge in the right direction?
Thank you!
Heres the code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <stdio.h>
using namespace std;
void comma2blank(string* pString1);
int main()
{
string* String1 = " " ;
cout << "Tell me why you like programming" << endl;
getline(cin, *String1);
comma2blank(String1);
cout << " String 1 without comma is: " << *String1 << endl;
delete String1;
system("pause");
};
void comma2blank(string* pString1)
{
pString1->replace(pString1->find(','), 1, 1, ' ');
pString1->replace(pString1->find(','), 1, 1, ' ');
};
You don't need to create a string pointer in your main(). You need a full string object and you can pass its address (a pointer) to your function like this:
int main()
{
string String1; // NOT a pointer!
cout << "Tell me why you like programming" << endl;
getline(cin, String1);
comma2blank(&String1); // NOTE: pass by pointer using & (address of)
cout << " String 1 without comma is: " << String1 << endl;
// no need to delete anything here
system("pause");
};
My program worked like it was supposed to until I added the toupper part into my program. I've tried looking at my error code but it's not really helping. The errors are:
no matching function to call
2 arguments expected, one provided
So I know the error is in those two statements in my while loop. What did I do wrong?
I want to make a name like
john brown
go to
John Brown
#include <iostream>
#include <iomanip>
#include <fstream>
#include <string>
using namespace std;
int main(){
string firstname[5];
string lastname[5];
ifstream fin( "data_names.txt" );
if (!fin) {
cout << "There is no file" << endl;
}
int i = 0;
while( i < 5 && (fin >> firstname[i]) && (fin >> lastname[i]) ) {
firstname[0] = toupper(firstname[0]);
lastname[0] = toupper(lastname[0]);
i++;
}
cout << firstname[0] << " " << lastname [0] << endl;
cout << firstname[1] << " " << lastname [1] << endl;
cout << firstname[2] << " " << lastname [2] << endl;
cout << firstname[3] << " " << lastname [3] << endl;
cout << firstname[4] << " " << lastname [4] << endl;
return 0;
}
std::toupper works on individual characters, but you are trying to apply it to strings. Besides adding #include <cctype>, you need to modify your while loop's body:
firstname[i][0] = toupper(firstname[i][0]);
lastname[i][0] = toupper(lastname[i][0]);
i++;
Then it should work as expected. Live demo here
As M.M helpfully pointed out in the comments, you should also check that your strings aren't empty before accessing their first characters, i.e. something like
if (!firstname[i].empty()) firstname[i][0] = toupper(...);
is strongly recommended.
Mind you, you will probably need more sophisticated logic if you get names like McDonald :)
You need ctype.h to get the proper definition for toupper(). It is usually implemented not as a function, but an array mapping.
#include <ctype.h>
The program has several flaws: using a string array instead of a string, not iterating through the string correctly, not declaring but using the C definition of toupper(), not exiting when the file does not exist.
Use this instead:
#include <ctype.h>
#include <iostream>
#include <string>
using namespace std;
int main ()
{
ifstream fin ("data_names.txt");
if (!fin)
{
cerr << "File missing" << endl;
return 1;
}
// not sure if you were trying to process 5 lines or five words per line
// but this will process the entire file
while (!fin.eof())
{
string s;
fin >> s;
for (i = 0; i < s.length(); ++i)
s [i] = toupper (s [i]);
cout << s << endl;
}
return 0;
}