Invalid Arrary Assignment - c++

im doing a project for my C++ class and I am having problems with this one particular function. I keep getting the error "invalid array assigment and I dont know why. I am just trying to swap positions into a temp variable and swap back to display this information in descending order. the array dateAdded is an array with Chars. I appreciate the help guys
void repAge(){
cout << "You selected Listing by Age" << endl;
int i;
int pos;
string temp;
bool swap;
// Look for empty row
pos = -1;
// look for an empty book row (title[i][0] == '\0')
for (i = 0; i < 20; i++) {
if (bookTitle[i][0] == '\0') {
pos = i;
break;
}
}
// Now pos is last available value.
do
{
swap = false;
for (int count = 0; count < (pos - 1); count++)
{
if (dateAdded[count] < dateAdded[count+1])
{
temp = dateAdded[count];
dateAdded[count] = dateAdded[count+1];
dateAdded[count+1] = temp;
swap = true;
}
}
} while (swap);
for (i = 0; i< pos; i++) {
while (bookTitle[i] != '\0') {
// print it out
cout << "Title: " << bookTitle[i] << endl;
cout << "ISBN: " << isbn[i] << endl;
cout << "Quantity-On-Hand: " << qtyOnHand[i] << endl;
cout << "Wholesale Cost: " << wholesale[i] << endl;
cout << endl;
break;
}
}
The exact error messages that pop up are "invalid array assignment" or "invalid conversion from char* to char".
the array is declared as dateAdded[20][11] and the lines that do not work are the these
temp= dateAdded[count];
dateAdded[count] = dateAdded[count+1];
dateAdded[count+1] = temp;

You say dateAdded is an array of chars - then, at least the following line will fail since temp is declared as string:
dateAdded[count+1] = temp;
Use something like
dateAdded[count+1] = temp[0];
Probably it is even better to declare temp as char - there is no reason to use string to temporarily store an element of a char array.

Related

Parsing a structure in C++ and searching for a value in it

Hi I am working on class work and I am writing a function that shows the highest points as well as the player name that scored the highest points.
Here is what I have so far It works mostly but loops back and begins to print the next name in array. I tried using a while loop but could not get it to work correctly. Thank you in advance to anyone willing to help.
double temp = 0;
for (int i = 0; i < SIZE; i++)
{
if (player[i].pointsScored > temp)
{
temp = player[i].pointsScored;
}
}
for (int i = 0; i < SIZE; i++)
{
cout << player[i].playerName << ' ';
if (temp == player[i].pointsScored)
{
cout << "scored the highest points with " << temp << " points";
}
}
Don't use another loop to get the name of the player, get it in the
first loop itself.
double temp = 0;
String name="";
for (int i = 0; i <= SIZE-1; i++)
{
if (player[i].pointsScored > temp)
{
temp = player[i].pointsScored;
name = player[i].playerName;
}
}
cout << name <<" scored the highest points with " << temp << " points";
Alternate:(This better as it uses lesser space & is faster)
int temp = 0;
for (int i = 1; i < SIZE; i++)
{
if (player[i].pointsScored > player[temp].pointsScored)
{
temp =i;
}
}
cout << player[temp].playerName<<" scored the highest points with " << player[temp].pointsScored << " points";
Here is what I have so far It works mostly but loops back and begins to print the next name in array.
To avoid this, break from the loop once you find the player with the highest score. Also, you don't need to print the names of all the players while you search for the player with the highest score. Move the line that prints the player's name inside the if block.
double temp = 0;
for (int i = 0; i < SIZE; i++)
{
if (player[i].pointsScored > temp)
{
temp = player[i].pointsScored;
}
}
for (int i = 0; i < SIZE; i++)
{
cout << player[i].playerName << ' ';
if (temp == player[i].pointsScored)
{
cout
<< player[i].playerName << ' '
<< "scored the highest points with " << temp << " points";
// No need to loop any more.
// Break out of the loop.
break;
}
}
You can also store the index of the player with the highest score and just print the info of that player.
int highestScoreIndex = 0;
double temp = 0;
for (int i = 0; i < SIZE; i++)
{
if (player[i].pointsScored > temp)
{
temp = player[i].pointsScored;
highestScoreIndex = i;
}
}
cout
<< player[highestScoreIndex].playerName << ' '
<< "scored the highest points with " << temp << " points";
you should make changes in second loop where you are printing the name and the score..
for (int i = 0; i < SIZE; i++)
{
if (temp == player[i].pointsScored)
{
cout << player[i].playerName << " ";
cout << "scored the highest points with " << temp << " points";
break;
}
}
and The second solution is..
double temp = 0;
string tempPlayerName="";
for (int i = 0; i < SIZE; i++)
{
if (player[i].pointsScored > temp)
{
temp = player[i].pointsScored;
tempPlayerName=player[i].playerName;
}
}
cout<<"Player Name who has scored highest points "<<tempPlayerName;
cout<<" and points are "<<temp;

C++ adding extra, unwanted characters to a string

I am having a bug that I cannot find a fix for through google searching. I am attempting to make a text based version of the game Mastermind. I am using a string the is set from an array of chars as the criteria for a while loop. When the string is equal to "****" the game is supposed to tell the player that they won and exit, but for some reason a ^A is being added on to the end of the string that is being checked, even though it is not in the char array.
Here is the function that sets the char array and returns a string from that array:
string check(int guess[4], int num[4]) {
char hints[4];
cout << " ";
for (int i = 0; i < 4; i++) {
if (guess[i] == num[i]) {
hints[i] = '*';
cout << "*";
}
else {
for (int x = 0; x < 4; x++) {
if (guess[i] == num[x]) {
cout << "+";
}
}
}
if (guess[i] != num[i]) {
hints[i] = ' ';
}
}
string hint(hints);
cout << endl;
cout << hint << endl;
return hint;
}
And here is the function checking the value of the string:
while (hints.compare("****") != 0) {
if (guessCount == 5) {
break;
}
cout << "Guess?: ";
cin >> guess;
intToArray(guess, guessArr);
hints = check(guessArr, nums);
cout << hints << endl;
guessCount++;
}
if (hints.compare("****") == 0) {
cout << "You win! The number was: ";
for (int i = 0; i < 4; i++) {
cout << nums[i];
}
}
You haven't null-terminated the hints array, so you are getting extra garbage that is lying around on the stack in your string.
You could let the hint string know how long it is when you are constructing it.
string hint(hints, 4);
cout << endl;
cout << hint << endl;

error c2109: subscript requires array or pointer type 5

I've been running into a minor issue regarding a for loop and an array and I'm hoping I can get some help. In the first function, using the for loop to call each value of the function works just fine. However, in the second function, I get an error from Visual Studio stating "subscript requires array or pointer type". What am I doing wrong here that is causing this error?
The purpose of this program is to search through a txt file of books, skipping lines between entries, finding out how many entries in the file match and where they are, and printing out the details of each entry.
void bookSearch(string id) {
ifstream fbooks;
string item = " ", entry = " ";
int resultLocation[30];
int searchType = 0;
fbooks.open("books.txt");
cout << "Welcome to the Book Search System, " << id << ".\n"
<< "What do you wish to search the registry by?\n"
<< "1. ISBN Number\n" << "2. Author\n" << "3. Title\n";
while (searchType<1 || searchType>3) {
cin >> searchType;
if (searchType<1 || searchType>3) {
displayMessage(0);
}
}
getline(cin, item);
for (int x = 0; x <= 30; x++) {
for (int y = 0; y < searchType; y++)
getline(fbooks, entry);
if (entry == item)
resultLocation[x] = 1;
else
resultLocation[x] = 0;
for (int z = 0; z < 5; z++)
getline(fbooks, entry);
}
resultPrint(resultLocation, id);
}
void resultPrint(int resultLocation, string id){
int resultNum = 0;
string entry = "";
ifstream fbooks;
fbooks.open("books.txt");
for (int a = 0; a <= 30; a++) {
if (resultLocation == 1)
resultNum++;
}
if (resultNum > 0) {
cout << endl << "There are " << resultNum << " entries in the database matching that criteria.\n";
for (int a = 0; a <= 30; a++){
if (resultLocation[a] == 1) { //The a in this line is marked with the error
for (int b = 0; b <= 2; b++) {
getline(fbooks, entry);
cout << entry;
}
}
}
}
else
cout << endl << "There are no entries in the database matching that criteria.\n";
}
resultLocation is an integer, so you can't use operator[] on it (for other than the first "index"). Looks like you meant to make it an array:
void resultPrint(int resultLocation[], string id);

null terminated char array (c-string) not printing without for loop

**I can't use vectors, or any functions from the standard library with this program. Hence why I am writing it all myself.
Alright, this program is just about finished. All my user defined functions are working fine, except for the reverseCString function. When I run the program, and enter a string of "hello", I can select menu option "rev" to reverse the string. My main function then calls the reverseCString function, and uses the for loop in my main to print out my reversed c-string. The program works fine at this point, until the do-while loop continues..
After the rv function is called though, the program loops to continue to allow the user to modify their string, as it should. However, my c-string vanishes at this point. I can still operate on it if I use the other commands/funtions, but the c-string doesn't print to cout.
I don't understnad what is causing this, but I have isolated the problem down to the reverseCString function.
Here is my code so far:
#include<iostream>
#include<stdlib.h>
#include<cstring>
#include<string>
#include<math.h>
using namespace std;
void shiftLeft(char szString[], size_t shiftBy)
{
const char *p = szString;//
while (*p) ++p;//advance p to point to the the null terminator, found via personal research at http://stackoverflow.com/questions/12201815/what-difference-between-whilepp-while-p-and-whilep
size_t len = p - szString;//len is set to the size of our c-string
if (len > 1 && (shiftBy %= len))
{
char *ends[] = { szString+shiftBy, szString+len, szString+(len - shiftBy) };//create a temporary array for storage
for (size_t i = 0; i < 3; ++i)//use a for loop to flip the first three character
{
char *start = szString, *end = ends[i];
while (start < --end)//now flip the rest of the characters
{
char ch = *start;
*start++ = *end;
*end = ch;
}
}
}
}
void shiftRight (char szString[], int size, int shiftBy)
{
if(shiftBy > size){
shiftBy = shiftBy - size;
}
if(size == 1){
//do nothing, exit function with no change made to myarray
}
else{
char temp;
//for loop to print the array with indexes moved up (to the right) --> by 2
for (int i=0; i < size; i++)
{//EXAMPLE shift by 3 for a c-string of 5
temp = szString[size-shiftBy];//temp = myarray[2]
szString[size-shiftBy] = szString[i];//myarray[2] = myarray[i]
szString[i] = temp;//myarray[i] = temp(value previously at index 2)
}
}
}
void reverseCString(char szString[], const size_t& size){
char temp;
int i = 0;
int j = size-1;
//we can use a simple tep variable to flip everything
while(i < j)
{
temp = szString[i];
szString[i] = szString[j];
szString[j] = temp;
i++;
j--;
}
}
int main(){
string repeat = "";
string userInputString;
cout << "Please eneter your string: " << endl;
//cin >> ws;
getline(cin,userInputString);
char * szString = new char [userInputString.length()+1];
strcpy (szString, userInputString.c_str());
do {
cout << "Your c-string is: " << szString << endl;
string commandString = "";
cout << "Please enter a command: ";
getline(cin,commandString);
if (commandString[0] == 'L'){
cout << "You have chosen to shift your string left by " << commandString[1] << " characters." << endl;
const char * shiftLeftPtr = &commandString[1];
//convert this value to an int for our function
int shiftLeftBy = atoi(shiftLeftPtr);
//run our shifleft function
shiftLeft(szString,shiftLeftBy);
//print the results
cout << "Your c-string, shifted left by " << commandString[1] << endl;
cout << szString;
}
if (commandString[0] == 'R'){
cout << "You have chosen to shift your string right by " << commandString[1] << " characters." << endl;
const char * shiftRightPtr = &commandString[1];
//convert this value to an int for our function
int shiftRightBy = atoi(shiftRightPtr);
//run our shiftright function
shiftRight(szString,userInputString.length(),shiftRightBy);
//print the results
cout << "Your c-string, shifted right by " << commandString[1] << endl;
cout << szString;
}
if (commandString.compare("rev") == 0){
cout << "You have chosen to reverse your string. " << endl;
//run our reverseArray function
reverseCString(szString,userInputString.length()+1);
cout << "Your c-string, reversed: ";
for(int i = 0; i < userInputString.length()+1; i++){
///////////////////////////right her seems to be my issue
cout << szString[i];
}
}
if (!(commandString[0] == 'R' || commandString[0] == 'L' || commandString.compare("rev") == 0)){
cout << "You have entered an invalid selection." << endl;
}
cout << "\nEnter 'quit' to close the program, anything else to continue: ";
getline(cin,repeat);
}while(repeat.compare("quit") != 0);
return 0;
}
Your length logic is broken. Say the string contains "bar\0". You do this:
reverseCString(szString,userInputString.length()+1);
Now, length is 3, and you pass 4 to reverseCString. Then this happens:
void reverseCString(char szString[], const size_t& size){
char temp;
int i = 0;
int j = size-1;
Now, i is 0 and j is 3. So you swap items 0 and 3. Well, what are the items?
0 = b
1 = a
2 = r
3 = \0
When you swap items 0 and 3, you create a string that starts with a terminator, "\0rab". Of course printing that out won't produce anything.

How do I read an array of structs from a file and sort it?

Preface: Guidelines set by professor, I must use the array, not some other data structure. His psuedo code (which isn't very concise) of the method we should be following:
name and grade are read into a temporary location
loop from the end of the filled part of the array down to beginning {
if (new last name < current last name) {
copy current name and grade down
}
else if (new/current last names are equal and new first name < current first name) {
copy/assign current name and grade down
}
else {
found right place, break out of loop
}
}
now that you've made room, insert (copy) new name into correct sorted position
I see that I'm probably breaking array bounds by attempting to read array position [-1] but I can't think of a way to avoid that since I'm counting backwards from the number of items I have and have to compare them.
I'm reading lines from a text file and storing pieces of each line into a struct. Then I'm using an insertion-sort-esque algorithm to store the structs in alphabetical order. However, my array does not seem to populate past the first couple lines with the new lines simply overwriting the previous lines... It's as if one of my comparison tests is failing since my copy position never appears to change although that could be because the initial array populating is failing in some way. I feel foolish, I must be missing something simple... Also my DisplayList module apparently never gets an array that's been populated with anything. Am I altering the array in an incorrect manner?
Here is the module with the problem:
bool sortInput(ifstream &infile, StudentType students[], int size)
{
StudentType temp;
int copyToHere;
if(size == 0)
{
infile >> temp.last >> temp.first >> temp.grade;
strcpy(students[0].last, temp.last);
strcpy(students[0].first, temp.first);
students[0].grade = temp.grade;
size++;
}
while(infile)
{
infile >> temp.last >> temp.first >> temp.grade;
//cout << "TEST" << temp.last << temp.first << temp.grade << endl;
for(int i = size; i > 0; i--)
{
if(strcmp(temp.last, students[i-1].last) < 0)
{
students[i] = students[i-1];
students[i-1] = temp;
}
else if(strcmp(temp.last, students[i].last) == 0 && strcmp(temp.first, students[i].first) < 0)
{
students[i] = students[i-1];
}
else
{
break;
}
copyToHere = i;
}
cout << "Size = " << size << " and copy position = " << copyToHere << endl;
students[copyToHere] = temp;
size++;
//test to see if array is populated properly
for(int i = 0; i < size; i++)
{
cout << "Name is " << students[i].first << " " << students[i].last << " and grade is " << students[i].grade << endl;
}
cout << "DONE" << endl;
} //end while loop
return true;
}
Here is the full code (if necessary for whatever reason or further context):
// ----------------------------------------------------------------------------
// You write meaningful doxygen comments and assumptions
#include <string.h>
#include <iostream>
#include <iomanip>
#include <fstream>
using namespace std;
int const MAXSIZE = 100; // maximum number of records in total
int const MAXLENGTH = 31; // maximum string length
int const MAXGRADE = 100; // highest possible grade
int const LOWGRADE = 0; // lowest possible grade
int const GROUP = 10; // group amount
int const HISTOGRAMSIZE = (MAXGRADE-LOWGRADE)/GROUP + 1; // grouped by GROUP
struct StudentType { // information of one student
int grade; // the grade of the student
char last[MAXLENGTH]; // last name (MAXLENGTH-1 at most)
char first[MAXLENGTH]; // first name (MAXLENGTH-1 at most)
};
// prototypes go here
bool sortInput(ifstream &, StudentType [], int);
void displayList(StudentType [], int);
/*setHistrogram();
displayHistogram();
findAverage();*/
//------------------------------- main ----------------------------------------
int main() {
StudentType students[MAXSIZE]; // list of MAXSIZE number of students
int size = 0; // total number of students
int histogram[HISTOGRAMSIZE]; // grades grouped by GROUP
int average = 0; // average exam score, truncated
// creates file object and opens the data file
ifstream infile("data1.txt");
if (!infile) {
cout << "File could not be opened." << endl;
return 1;
}
// read and sort input by last then first name
bool successfulRead = sortInput(infile, students, size);
// display list, histogram, and class average
if (successfulRead) {
displayList(students, size);
// setHistogram(... you figure parameters ...);
// displayHistogram(... you figure parameters ...);
// average = findAverage(... you figure parameters ...);
cout << "Average grade: " << average << endl << endl;
}
return 0;
}
bool sortInput(ifstream &infile, StudentType students[], int size)
{
StudentType temp;
int copyToHere;
if(size == 0)
{
infile >> temp.last >> temp.first >> temp.grade;
strcpy(students[0].last, temp.last);
strcpy(students[0].first, temp.first);
students[0].grade = temp.grade;
size++;
}
while(infile)
{
infile >> temp.last >> temp.first >> temp.grade;
//cout << "TEST" << temp.last << temp.first << temp.grade << endl;
for(int i = size; i > 0; i--)
{
if(strcmp(temp.last, students[i-1].last) < 0)
{
students[i] = students[i-1];
students[i-1] = temp;
}
else if(strcmp(temp.last, students[i].last) == 0 && strcmp(temp.first, students[i].first) < 0)
{
students[i] = students[i-1];
}
else
{
break;
}
copyToHere = i;
}
cout << "Size = " << size << " and copy position = " << copyToHere << endl;
students[copyToHere] = temp;
size++;
//test to see if array is populated properly
for(int i = 0; i < size; i++)
{
cout << "Name is " << students[i].first << " " << students[i].last << " and grade is " << students[i].grade << endl;
}
cout << "DONE" << endl;
} //end while loop
return true;
}
void displayList(StudentType students[], int size)
{
cout << "List of names sorted:" << endl;
for(int i = 0; i < size; i++)
{
cout << " " << students[i].grade << " " << students[i].last << " " << students[i].first << endl;
}
}
// ----------------------------------------------------------------------------
// functions with meaningful doxygen comments and assumptions go here
Your insertion sort isn't really inserting properly. Let's look at one part of your main insertion loop:
if(strcmp(temp.last, students[i-1].last) < 0)
{
students[i] = students[i-1];
students[i-1] = temp;
}
The intention of this is obviously to insert temp into the array at position i-1. You're shifting the item at i-1 to i but what happened to the other elements in the array? You need to move them all up one position to make room for the inserted element. Something like:
memmove(students + i, students + i - 1, sizeof(students[0]) * size - i - 1);
You have other problems in your code too. copyToHere is potentially uninitialized. You are copying temp into the array multiple times (students[i-1] = temp; and students[copyToHere] = temp; aren't both needed). Once you have done the insertion in the inner loop you should break out. Your special handling for when the list is empty isn't really necessary, and so on.
Have a look at the pseudo-code for an insertion sort algorithm and see if you can simplify and rewrite yours to eliminate the problems.
Solution to my own problem haha. I was stupid for not having completed the else statement properly. Now I'm working to redo my first name comparisons as something appears wrong since it wont order same last names alphabetically.
LESSON LEARNED: Get it all down before thinking you're forked. Now I really do feel like an idiot, hopefully didn't waste many peeps time.
for(int i = size; i > 0; i--)
{
if(strcmp(temp.last, students[i-1].last) < 0)
{
students[i] = students[i-1];
students[i-1] = temp;
}
else if(strcmp(temp.last, students[i].last) == 0 && strcmp(temp.first, students[i].first) < 0)
{
students[i] = students[i-1];
students[i-1] = temp;
}
else
{
students[i] = temp;
break;
}
insertHere = i;
}