so i was having two types of issues from my code... the general forms are:
"left of ... must have class/struct/union " :
doc.id[j] = NULL;
doc.ISBN[j] = NULL;
doc.title[j] = NULL;
doc.year[j] = NULL;
and " 'doc' uses undefined struct 'main::m_doc'"
struct m_doc doc;
while the struct m_doc doc is included in the top of each function .
here is my struct :
struct m_doc{
char id[30];
int ISBN[30];
char title[50];
char author[50];
int year[30];
};
my fist function :
void menudoc()
{ struct m_doc doc;
int c = 0, a = 0, b;
cout << "1. Them tai lieu moi" << endl;
cout << "2. Xoa tai lieu" << endl;
cout << "3. Bao cao theo nam xuat ban" << endl;
cout << "0. Tro lai menu truoc" << endl;
cout << "Ban chon:";
cin >> b;
switch (b)
{
case 1:
{
for (int i = 0;; i++)
{
if (doc.id[i] == NULL && doc.ISBN[i] == NULL && doc.title[i] == NULL && doc.author[i] == NULL && doc.year[i] == NULL)
{
i = c; break;
}
else continue;
}
cin >> doc.author[c] ;
cin >> doc.id[c] ;
cin >> doc.ISBN[c] ;
cin >> doc.title[c];
cin >> doc.year[c];
for (int i = 0;; i++){
for (int j = 1;; j++){
if (doc.id[i] == doc.id[j]){
doc.author[j] = NULL;
doc.id[j] = NULL;
doc.ISBN[j] = NULL;
doc.title[j] = NULL;
doc.year[j] = NULL;
}
if (doc.year[i]<1000 || doc.year[i]>9999){
doc.author[i] = NULL;
doc.id[i] = NULL;
doc.ISBN[i] = NULL;
doc.title[i] = NULL;
doc.year[i] = NULL;
}
}
}
break;
}
case 2:
{
int x;
char docid[50];
cout << "IDDOC: ";
cin >> docid[50];
cout << "\n";
for (int i = 0;; i++){
if (docid[50] == doc.id[i]) {
doc.author[i] = NULL;
doc.id[i] = NULL;
doc.ISBN[i] = NULL;
doc.title[i] = NULL;
doc.year[i] = NULL;
x++;
}
}
if (x == 0) cout << "IDDOC khong ton tai." << endl;
break;
}
case 3:
{
int yeardoc[50];
cin >> yeardoc[50];
for (int i = 0;; i++){
if (yeardoc[50] == doc.year[i])
write_output(i, "report.scv");
}
break;
}
case 0:
{
menubegin();
break;
}
menudoc();
}
}
my second function :
int write_output(int i, char* filename){
ios::out;
struct m_doc doc;
// open file for output
ofstream fout(filename);
char * k, *h;
k = strchr(doc.title, ',');
h = strchr(doc.author, ',');
if (k != 0 && h != 0)fout << doc.id[i] << "\n" << doc.ISBN[i] << "\n" << '"' << doc.title[i] << '"' << "\n" << '"' << doc.author[i] << '"' << "\n" << doc.year[i] << endl;
if (k != 0) fout << doc.id[i] << "\n" << doc.ISBN[i] << "\n" << '"' << doc.title[i] << '"' << "\n" << doc.author[i] << "\n" << doc.year[i] << endl;
if (h != 0)fout << doc.id[i] << "\n" << doc.ISBN[i] << "\n" << doc.title[i] << "\n" << '"' << doc.author[i] << '"' << "\n" << doc.year[i] << endl;
// write informations
if (k == 0 && h == 0)fout << doc.id[i] << "\n" << doc.ISBN[i] << "\n" << doc.title[i] << "\n" << doc.author[i] << "\n" << doc.year[i] << endl;
// close file
fout.close();
return 0;
}
anybody im asked said that it was something about scope but none of them know the problem since everything looks fine... please help me , every help is much appreciated :)
I'm taking a guess that you are confused about when to use forward declarations and when to include the structure definition. Here are some guidelines.
Forward Declaration
A forward declaration of a structure is of the form:
struct m_doc doc;
This form is used to resolve definitions, any pointer or reference that refers to the symbol doc. Usually this is placed in a header file before other structure or function declarations to reduce the number of #include files.
Structure Definition
You need to have the structure definition present before any code that:
Creates an instance of the structure,
Or before anything that refers to the details of the structure
(members & methods).
Placing structures in #include files
Rather than typing the structure everywhere it is used, a convenient practice is to place it in a header file, usually ".h" for C language structures and ".hpp" or ".hh" for C++ classes and structures. So when you have a function in a source file that references the structure (or creates an instance of the structure), include the file with the definition before it is used by the function.
Most compilers issue the error
"left of ... must have class/struct/union "
when it can't find the definition or declaration of the structure.
Related
int main(int argc, char *argv[]) {
ifstream inFile;
int numOfLines = 0, numOfTokens = 0, numOfStrings = 0, maxStringLength = 0, l = 0, fileCount=0, mostCommonCount=0;
string inputFile, mostCommonList="", word;
for(int i = 1; i < argc; i++){
if(strpbrk(argv[i] , "-")){
if(flags.find(string(argv[i]))!=flags.end()) flags[string(argv[i])] = true;
else{
cerr << "INVALID FLAG " << argv[i] << endl;
exit(1);
}
}
else{
inFile.open(argv[i]);
fileCount++;
if(!inFile && fileCount==1){
cerr << "UNABLE TO OPEN " << argv[i] << endl;
exit(1);
}
else{
string line;
while(getline(inFile, line)) inputFile+=line+='\n';
if(fileCount>1){
cerr << "TOO MANY FILE NAMES" << endl;
exit(1);
}
}
}
}
int linenum = 0;
TType tt;
Token tok;
while((tok = getNextToken(&inFile, &linenum))!=DONE && tok != ERR){
tt = tok.GetTokenType();
word = tok.GetLexeme();
if(flags["-v"]==true){
(tt == ICONST||tt==SCONST||tt==IDENT) ? cout<<enumTypes[tok.GetTokenType()]<<"("<< tok.GetLexeme()<<")"<<endl : cout<< enumTypes[tok.GetTokenType()]<<endl;
}
if(flags["-mci"]==true){
if(tt==IDENT){
(identMap.find(word)!=identMap.end()) ? identMap[word]++ : identMap[word]=1;
if(identMap[word]>mostCommonCount) mostCommonCount = identMap[word];
}
}
if(flags["-sum"]==true){
numOfTokens++;
if(tt==SCONST){
numOfStrings++;
l = word.length();
if(l > maxStringLength) maxStringLength = l;
}
}
}
if(tok==ERR){
cout << "Error on line" << tok.GetLinenum()<<"("<<tok.GetLexeme()<<")"<<endl;
return 0;
}
if(flags["-mci"]==true){
cout << "Most Common Identifier: ";
if(!identMap.empty()){
word ="";
for(auto const& it : identMap){
if(it.second==mostCommonCount) word += it.first + ",";
}
word.pop_back();
cout << word << endl;
}
}
if(flags["-sum"]){
numOfLines = tok.GetLinenum();
numOfLines = tok.GetLinenum();
cout << "Total lines: " << numOfLines << endl;
cout << "Total tokens: " << numOfTokens << endl;
cout << "Total strings: " << numOfStrings << endl;
cout << "Length of longest string: " << maxStringLength << endl;
}
inFile.close();
return 0;
}
For some reason this code is running infinitely. I cannot figure out the source of error. I also do not know whether this file or the other linked file is causing this error so I posted the main program code. I think is one of the switch statements that causing this error but I am not sure. FYI: I am supposed to make a lexical analyzer so I had three files one lexigh.h (contains all the data types and all the functions), getToken.cpp(file that defines the functions from lexigh.h) and the main program which calls the methods and tests it.
I'm writing a modified version of 20 Questions for my CS2 class and I am having one heck of a time trying to figure out why I'm getting the error.
IC2664 cannot convert argument 1 from 'const char ' to 'Node'
Anyways, any assistance would be appreciated.
#include "LetMeGuess.h"
#include<iostream>
#include<memory>
#include<string>
#include<fstream>
#include<vector>
struct LetMeGuess::Node {
Node(std::string data) : data(data), no(nullptr), yes(nullptr) {};
std::string data;
std::shared_ptr<Node>no;
std::shared_ptr<Node>yes;
};
void LetMeGuess::letMeGuess() {
std::cout << "***Let Me Guess!***\nLoading questionArchive.txt ..." << std::endl;
readInFile();
std::cout << "Done!" << std::endl;
askQuestions();
std::cout << "Saving questionArchive.txt ..." << std::endl;
readOutFile(root);
std::cout << "Done! Goodbye!" << std::endl;
}
void LetMeGuess::readInFile() {
root = std::shared_ptr<Node>("Is it an animal?");
root->no = std::shared_ptr<Node>("Toaster");
root->yes = std::shared_ptr<Node>("Elephant");
//std::vector<Node> myStack;
//std::shared_ptr<Node> newNode;
//std::string nextInfo;
//std::string nextID;
//fin.open("questionArchive.txt");
//while (!fin.eof) {
// fin >> nextID;
// if (nextID == "A") {
// fin >> nextInfo;
// Node newNode(nextInfo);
// myStack.push_back(newNode);
// }
// else {
// fin >> nextInfo;
// Node newNode = Node(nextInfo);
// Node newNode->yes = myStack.back();
// }
//}
}
std::string LetMeGuess::readOutFile(std::shared_ptr<Node>curr) {
curr = root;
std::string outString;
fout.open("questionArchive.txt");
if (!curr) return outString;
outString += readOutFile(curr->no);
outString += readOutFile(curr->yes);
if (curr->no == nullptr || curr->yes == nullptr) {
outString += "A ";
}
else {
outString += "Q ";
}
outString += curr->data;
outString += "/n";
fout << outString;
return outString;
}
bool LetMeGuess::stillAsking(std::shared_ptr<Node> temp){
if (temp->no == nullptr || temp->yes == nullptr) return false;
else return true;
}
bool LetMeGuess::playAgain(char ans) {
switch (ans) {
case'Y':
case'y':
return true;
case'N':
case'n':
default:
std::cout << "y/n not selected, starting a new game anyways." << std::endl;
return true;
}
}
void LetMeGuess::insertNewQuestion(std::shared_ptr<Node>& curr, std::string newQuest, std::string objThought) {
curr->no = std::make_shared<Node>(curr->data);
curr->yes = std::make_shared<Node>(objThought);
curr->data = newQuest;
}
void LetMeGuess::askQuestions() {
std::shared_ptr<Node> current = root;
char answer;
char plyAgn = 'y';
std::string thoughtObject;
std::string newQuestion;
while (playAgain(plyAgn)) {
while (stillAsking(current)) {
std::cout << current->data;
std::cin >> answer;
switch (answer) {
case'y':
case'Y':
current = current->yes;
break;
case'n':
case'N':
current = current->no;
break;
default:
std::cout << "Please enter y/n." << std::endl;
break;
}
}
std::cout << "Let me guess, you're thinking of a(n)" << current->data << "?" << std::endl;
std::cin >> answer;
switch (answer) {
case 'y':
case'Y':
std::cout << "I win!" << std::endl;
break;
case'n':
case'N':
std::cout << "What where you thinking of?" << std::endl;
std::cin >> thoughtObject;
std::cout << "What could I have asked to know you were thinking of a(n) " + thoughtObject + " and not a(n) " + current->data + "?" << std::endl;
std::cin >> newQuestion;
insertNewQuestion(current, newQuestion, thoughtObject);
break;
default:
std::cout << "Please enter y/n." << std::endl;
break;
}
std::cout << "Would you like to play again? (y/n)" << std::endl;
std::cin >> plyAgn;
}
}
root = std::shared_ptr<Node>("Is it an animal?");
root->no = std::shared_ptr<Node>("Toaster");
root->yes = std::shared_ptr<Node>("Elephant");
is incorrect way of creating shared_ptr .
root = std::make_shared<Node>("Is it an animal?");
root->no = std::make_shared<Node>("Toaster");
root->yes = std::make_shared<Node>("Elephant");
is the correct way of constructing shared_ptr
I have the next function and i want to print some parameters separated by a comma, my problem is that the console didn't show anything when "parametro[i] = linea[i]" in the FOR iteration.
Example:
Parametro 1: []
void funcionSeparadora (string linea){
int numParametros = 1;
string parametro;
for (int unsigned i=0;i<linea.length();i++){
if (linea[i] == ','){
cout <<"Parámetro "<<numParametros<<": "<<"["<< parametro <<"]"<< '\n';
numParametros++;
}
else (parametro[i] = linea[i]);
}
}
Mostly the way you handle the filling of parametro was wrong. Fixed version:
void funcionSeparadora(string linea) {
int numParametros = 1;
string parametro;
for (int unsigned i = 0; i<linea.length(); i++) {
if (linea[i] == ',') {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << '\n';
numParametros++;
parametro.clear();
}
else {
parametro += linea[i];
}
}
if (!parametro.empty()) {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << '\n';
}
}
Points you missed
Use curly brackets in else condition
Use size_t instead of unsigned in in for loop
initialize the parametro variable with necessary length
Try this
#include <iostream>
#include <string>
using namespace std;
void funcionSeparadora(string linea) {
int numParametros = 1;
string parametro(linea.length(),' ');
for (size_t i = 0; i < linea.length(); i++) {
if (linea[i] == ',') {
cout << "Parámetro " << numParametros << ": " << "[" << parametro << "]" << endl;
numParametros++;
}
else {
parametro[i] = linea[i];
}
}
}
int main()
{
funcionSeparadora("what is this,");
system("pause");
return 0;
}
This is a part of my program while I run this program I get a segmentation fault. I've narrowed it down to the line:
checkBase(ptr1, ptr2)
i'm passing both of these as pointers. and they are declare as char* and its a runtime error not compile time.
file contains
< a href = "http://www.google.com"> www.spam.google.com < /a >
in this case ptr1 = www.google.com and ptr2 = spam.google.com
while(inf){
count++;
getline(inf, line);
//cout << "*******" << count << "*******" << endl <<line << endl;
p = new char[line.length()+1];
strcpy(p, line.c_str());
if(strstr(p, "href")){
ptr = strstr(p, "href");
while(ptr[0]!='\0'){
ptr += 1;
if(ptr[0] == 'w' && ptr[1] == 'w' && ptr[2] == 'w'){
cout << ptr << endl;
ptr = strtok(ptr, "\"");
cout << "add1 " << ptr << endl;
add1 = ptr;
ptr1 = ptr;
ptr = strtok(NULL, "> ");
add2 = ptr;
ptr2 = ptr;
cout << "ptr1: " << ptr1 << endl << "ptr2: " <<ptr2 << endl;
if(add1 == add2)
cout << "There is an exact match at line: " << count << endl << line << endl;
else{
cout << "in else" << endl;
checkBase(ptr1, ptr2); //THIS GIVES A SEGMENTATION FAULT
}
}
}
}
}
void checkBase(char *add1, char *add2){
cout << "here" << endl;
char *base1[1000000], *base2[1000000];
int count1 = 0, count2 = 0;
base1[count1] = strtok(add1, ".");
while(base1[count1] != NULL){
count1++;
base1[count1] = strtok(NULL, ".");
cout << base1[count1] << endl;
}
base2[count2] = strtok(add2, ".");
while(base2[count2] != NULL){
count2++;
base2[count2] = strtok(NULL, ".");
}
cout << base2[count2-1] << endl;
if(((strcmp(base1[count1-1],base2[count2-1])) != 0) && (strcmp(base1[count1-2], base2[count2-2]) != 0)){
//if((strcmp(base1[count1-1], base2[count2-1]) != 0)){
cout << "Bases do not match: " << endl
<< base1[count1-2] << "." << base1[count1-1] << " and "
<< base2[count2-2] << "." << base2[count2-1] << endl;
//}
}
else{
cout << "Bases match: " << endl
<< base1[count1-2] << "." << base1[count1-1] << " and "
<< base2[count2-2] << "." << base2[count2-1] << endl;
}
}
I have no idea why this is giving a segmenation fault.
char *base1[1000000], *base2[1000000];
No doubt this is causing stack overflow. The stack is limited in size, and creating arrays more than a few kb in size is a bad idea. Try allocating them on the heap, for example vector<char *> base1(1000000)
You should also calculate the exact size required and allocate that much, or push_back on the vector.
A couple of problems, beyond the stack overflow already mentioned by #Neil Kirkwell
Those shouldn't be while loops solely conditioned on base1[count1] != NULL; you should also make sure count1 is less than the number of elements in the array.
If either count2 or count1 is 0 or 1 you will be trying to reference index of -1 and -2... not so good.
use strrchr to search backwards and make your life easier
It's wasteful to build those arrays entirely, since you only seem to care about the last two tokens, you only need two pointers in each.
i.e.
char *one_a = NULL, *one_b = NULL, *two_a=NULL, *two_b = NULL;
char *temp = strtok(add1, ".");
while (temp) {
one_b = one_a;
one_a = temp
temp = strtok(NULL, ".");
}
char *temp = strtok(add2, ".");
while (temp) {
two_b = two_a;
two_a = temp
temp = strtok(NULL, ".");
}
//now just compare one_a with two_a and one_b with two_b and you're done.
I was trying to count the number of characters in a string class but for some reason the program is skipping over my function completely. This is just the test code from the main program, it still was giving me the same results. How come the counter function is skipped over?
#include <iostream>
#include <string>
using namespace std;
void prompt(string& dna)
{
cout << "Input: ";
getline(cin, dna);
}
void counter(const string DNA,
int* a_count, int* t_count, int* c_count, int* g_count)
{
for (int i = 0; i < DNA.size(); i++)
{
if (DNA.at(i) == 'a')
{
*a_count++;
}
else if (DNA.at(i) == 't')
{
*t_count++;
}
else if (DNA.at(i) == 'c')
{
*c_count++;
}
else if (DNA.at(i) == 'g')
{
*g_count++;
}
}
}
int main()
{
string dna;
int a = 0;
int t = 0;
int c = 0;
int g = 0;
prompt(dna);
if (! dna.empty())
{
cout << "Before:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
counter(dna, &a, &t, &c, &g);
cout << "\n\nAfter:\n"
<< "A: " << a << endl
<< "T: " << t << endl
<< "C: " << c << endl
<< "G: " << g << endl;
}
system("pause");
return 0;
}
You're applying operator ++ the wrong way. It should be:
if (DNA.at(i) == 'a')
{
(*a_count)++;
}
else if (DNA.at(i) == 't')
{
(*t_count)++;
}
else if (DNA.at(i) == 'c')
{
(*c_count)++;
}
else if (DNA.at(i) == 'g')
{
(*g_count)++;
}
You've got a priority problem between the ++ and * operators. You are incrementing the pointer address, not the value. (*a_count)++; would be correct.
You may find it easier to use reference parameters for the counts instead, since you don't actually need to do any pointer arithetic. ie:
void counter(const string DNA, int& a_count, int& t_count, int& c_count, int& g_count)
And, yes a switch statement would be neater.