I am having a problem with the program I am trying to code. It's just a Windows console program and I am very new to C++. It's only my 4th program.
The problem I am having is that when I run my program I have no errors but a lot of warnings that say "comparison with string literal results in unspecified behaviour" in the lines that I will highlight below.
When the program runs instead of adding the numbers I want it to it just gives me a random huge number no matter what I put in for my inputs.
Here is the code:
#include <iostream>
using namespace std;
int main()
{
int hold;
int i;
int n;
i = 6;
int result;
int * price;
char items[100][100];
if (items == 0)
cout << "No items can be stored";
else
{
for (n=0; n<i; n++)
{
cout << "Item#" << n << ": ";
cin >> items[n];
}
cout << "\nYou Entered: \n";
for (n=0; n<i; n++)
cout << items[n] << ", ";
}
for (n=0; n<i; n++)
{
if (items[n] == "ab"){
price[n] = 2650;
}
else if (items[n] == "ae"){
price[n] = 1925;
}
else if (items[n] == "ie"){
price[n] = 3850;
}
else if (items[n] == "bt"){
price[n] = 3000;
}
else if (items[n] == "pd"){
price[n] = 2850;
}
else if (items[n] == "ga"){
price[n] = 2600;
}
}
for (n=0; n<i; n++)
{
result = result + price[n];
}
cout << "\nTotal gold for this build: " << result;
cin >> hold;
return 0;
}
Any help is appreciated. There is probably something big that I've done wrong. The names in the if statements are all currently placeholders and I'll be adding a lot more if statements when I can get it to work with the bare 6 which is what it needs to work.
In C++ == only implemented internally for primitive types and array is not a primitive type, so comparing char[100] and string literal will only compare them as 2 char* or better to say as 2 pointers and since this 2 pointers can't be equal then items[n] == "ae" can never be true, instead of this you should either use std::string to hold string as:
std::string items[100];
// initialize items
if( items[n] == "ae" ) ...
or you should use strcmp to compare strings, but remeber strcmp return 0 for equal strings, so your code will be as:
char items[100][100];
// initialize items
if( strcmp(items[n], "ae") == 0 ) ...
And one extra note is if (items == 0) is useless, since items allocated on stack and not in the heap!
First, int * price; is a dangling pointer - you never initialize it. You have to do:
int * price = new int[i];
Second, usually, i denotes an iterator index so I suggest you stick with that - so
for (i=0; i<n; i++) //some more refactoring needed
Third, you need to compare char arrays using strncmp in your case.
Fourth and most important - use std::string and std::vector instead. This is C++, not C.
Just a little thing that got me stumbling for a bit, is the difference between single and double quotes, see: Single quotes vs. double quotes in C or C++
I was comparing the first character of a string with double quotes and not single quotes - which resulted in above's error message.
You're comparing pointers, not the actual strings. Use C++ string class instead of char* (or check how C strings work).
Related
The program works fine, although the fist printed number is always "3452816845". I have tried initializing "str[i]" by adding curly brackets when defining the array, or by giving it NULL value, but then the first printed number is always "zero", and only then it prints what I entered. Please take a look below:
#include <iostream>
using namespace std;
int main() {
unsigned* str = new unsigned[1000];
int cnt = 0;
char ch;
int a;
cout << "Please enter text: ";
do {
cin.get(ch);
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
} while (ch != '\n');
cout << "The entered numbers are: ";
for (int i = 0; i <= cnt; i++) {
cout << str[i] << " "; // here is where the error appears
}
delete[] str;
return 0;
}
Do not using namespace std;. Especially not in headers, but try to not use it in plain .cpp files either. It's more convenient to debug code that unambiguously tells you which namespace an identifier came from right where that identifier is being used.
unsigned* str = new unsigned[1000];
Since the advent of C++11, "naked" memory allocation like that is frowned upon, and is definitely not necessary here.
You could just use a static array (unsigned str[1000];).
You could use smart pointers (auto str = std::make_unique<char[]>(1000);).
Best choice, use C++ containers, like <vector>, <string>, or (if overhead really bothers you) <array>.
if (ch <=57 && ch >=48) {
int a = ch - '0';
Do not use "magic numbers" in your code. If you want to know if the character entered is a digit, use isdigit, which is more expressive and works even for non-ASCII encodings that might have their digits at a different location in the code table.
int a = ch - '0';
This isn't wrong, as the standard guarantees this to work for digits. Note that similar arithmetic on characters (the infamous ... - 'a') is frowned upon though, and will break as soon as you leave the realm of strict ASCII-7 encoding.
cnt++;
str[cnt] = a;
C/C++ start counting at zero. You just left the first item in the array uninitialized. The beauty of the post-increment is that you can do it right there where you use the index, i.e. str[cnt++] = a;.
for (int i = 0; i <= cnt; i++)
cout << str[i] << " "; // here is where the error appears
}
Very C, and also wrong. You didn't initialize str[0], so the first round through that loop accesses uninitialized memory. If you had initialized str[0] (by incrementing cnt only after using it as an index), i <= cnt would go one item beyond what you wrote into str[], again accessing uninitialized memory. A loop should run from 0 to < cnt (not <=).
If you took my earlier advice to use <vector> or <string>, there's a much better way to loop through the items stored in it, the range-for.
#include <iostream>
#include <vector>
int main()
{
char ch;
std::vector< int > digits;
std::cout << "Please enter text: ";
do
{
std::cin.get( ch );
if ( std::isdigit( ch ) )
{
digits.push_back( ch - '0' );
}
} while (ch != '\n');
std::cout << "The entered numbers are: ";
for ( auto & i : digits )
{
std::cout << i << " ";
}
std::cout << std::endl;
return 0;
}
You never initialize str[0], but you output it.
The problem is here:
...
if (ch <=57 && ch >=48) {
int a = ch - '0';
cnt++;
str[cnt] = a;
}
...
You are incrementing cnt too early, leaving str[0] uninitialized. You should do:
if (ch <=57 && ch >=48) {
int a = ch - '0';
str[cnt++] = a;
}
Also you do have a problem in your for loop; You should start from 0 till the last initialized element in the string which is at index cnt - 1. It should be like this:
for (int i = 0; i < cnt; i++) {
cout << str[i] << " ";
}
or
for (int i = 0; i <= cnt - 1; i++) {
cout << str[i] << " ";
}
I've been struggling with a homework assignment that counts the amount of instances a uppercase letters, lowercase letters, and numbers in a string. appears in a string.
I'm using a one-dimensional array with a constant size of 132 to store the entered string, and I need to use two functions. One needs to count the amount of letter occurrences in the string and the other function will execute the output something similar to above. I'm struggling most with the letter counting aspect of the program itself.
Currently, this is what my current homework resembles for the most part. It's a work in progress (of course) so errors in the code are very likely.
void LetterCount(char c_input[], int l_count)
{
// code to count letters
}
void CountOut(//not sure what should go here yet until counting gets figured out)
{
// code that handles output
}
int main()
{
const int SIZE = 132;
char CharInput[SIZE];
int LetterCount = 0;
cout << "Enter a string of up to 132 characters in size: ";
cin.getline(CharInput, SIZE);
cout << "You entered: " << CharInput << endl;
Count(CharInput);
CountOut(//not sure what goes here yet);
return 0;
}
The output would look something like:
a - 2
b - 1
c - 1
d - 0
e - 1
etc...
I've tried some experimentation with for loops to count the letters and have seen some examples of the function gcount(), but I haven't gotten anything to work. Does anyone have a suggestion as to how I would count the letters in an inputted string?
map is a very efficient data structure here
#include <iostream>
#include <map>
using namespace std;
int main(){
string str = "a boy caught 2 fireflies";
map<char, int> str_map;
for(auto x : str) ++str_map[x];
for(auto x : str_map) cout << x.first << ' ' << x.second << '\n';
}
What you want is to build a simple histogram, and it's pretty easy to do. Since what you're looking at is chars, and there can be 256 possible values of an 8-bit char (in practice your input string probably uses less, but we'll be conservative here because memory is cheap), you'll want to start with an array of 256 ints, all of them initialized to zero. Then iterate over the chars your string, and for each char in your string, use that char-value as an offset into the array(*), and simply increment that item in the array.
When you're done, all that remains is to iterate over the ints in the array and print out the ones that are non-zero, and you're done.
(*) you may want to cast the char to unsigned char before using it as an offset into the array, just to avoid any chance of it being interpreted as a negative array-index, which would result in undefined behavior (this is only an issue if your input string contains ASCII characters 128 and higher, so it may not matter in your case, but it's always good form to make code that does the right thing in all cases if you can)
As Jeremy frisner said you're building a histogram, but I disagree with the types used.
You'll want to declare your histogram like so:
size_t histogram[sizeof(char)*CHAR_BIT] = {0};
The size_t because you might overflow without it, and you need enough space if it's a nonstandard byte size.
As for printing it out. You should take a look at an ASCII table and examine which values you need to print out.
You could do it by comparing c-strings with other c-strings. But with chars and strings you can get errors like: "const *char cant be compared with strings". So you'll have to compare each c string(array) index with other c string indexes. In this program I use if statements to look for certain vowels. The way it works is that each "string alphabet_letter" is equal to it's respective lowercase and capital letters (for comparison). this is a very redundant way to do it and, if you want to count all total letters, perhaps you should try a different way, but this method doesn't use very complicated methods that require deeper understanding.
using namespace std;
int main(){
int vowel;
string A = "aA";
string E = "eE";
string I = "iI";
string O = "oO";
string U = "uU";
string str;
string str1;
bool userLength = true;
int restart = 0;
do{
cout << "Enter a string." <<endl;
getline(cin, str);
int VowelA = 0;
int VowelE = 0;
int VowelI = 0;
int VowelO = 0;
int VowelU = 0;
for(int x = 0; x < 100; x++){
if(restart == 1){
restart = 0;
x = 0;
}
if(A[0] == str[x]){
VowelA = VowelA + 1;
}
if(E[0] == str[x]){
VowelE = VowelE + 1;
}
if(I[0] == str[x]){
VowelI = VowelI + 1;
}
if(O[0] == str[x]){
VowelO = VowelO + 1;
}
if(U[0] == str[x]){
VowelU = VowelU + 1;
}
if(A[1] == str[x]){
VowelA = VowelA + 1;
}
if(E[1] == str[x]){
VowelE = VowelE + 1;
}
if(I[1] == str[x]){
VowelI = VowelI + 1;
}
if(O[1] == str[x]){
VowelO = VowelO + 1;
}
if(U[1] == str[x]){
VowelU = VowelU + 1;
}
int strL = str.length();
if(x == strL){
cout << "The original string is: " << str << endl;
cout << "Vowel A: "<< VowelA << endl;
cout << "Vowel E: "<< VowelE << endl;
cout << "Vowel I: "<< VowelI << endl;
cout << "Vowel O: "<< VowelO << endl;
cout << "Vowel U: "<< VowelU << endl;
cout << " " << endl;
}
}
char choice;
cout << "Again? " << endl;
cin >> choice;
if(choice == 'n' || choice == 'N'){userLength = false;}
if(choice == 'y' || choice =='Y')
{
restart = 1; userLength = true;
cin.clear();
cin.ignore();
}
//cout << "What string?";
//cin.get(str, sizeof(str),'\n');
}while(userLength == true);
}
/*
Sources:
printf help
http://www.cplusplus.com/reference/cstdio/printf/
This helped me with the idea of what's a vowel and whats not.
http://www.cplusplus.com/forum/general/71805/
understanding gets()
https://www.programiz.com/cpp-programming/library-function/cstdio/gets
Very important functional part of my program...Logic behind my if statements, fixed my issues with string comparison
What i needed to do was compare each part of one cstring with another c string
strstr compares two strings to see if they are alike to one another this source includes that idea-> https://www.youtube.com/watch?v=hGrKX0edRFg
so I got the idea: What is one c string was all e's, I could then compare each index for similarities with a c string whos definition was all e's.
At this point, why not just go back to standard comparison with strings? But you cant compare const chars to regular chars, so I needed to compare const chars to const chars
hence the idea sparked about the c strings that contained both e and E.
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
Fixed Error with using incremented numbers outside of involved forloop.
https://stackoverflow.com/questions/24117264/error-name-lookup-of-i-changed-for-iso-for-scoping-fpermissive
understanding the use of getline(cin, str_name)
https://stackoverflow.com/questions/5882872/reading-a-full-line-of-input
http://www.cplusplus.com/reference/istream/istream/getline/
http://www.cplusplus.com/forum/beginner/45169/
cin.clear - cin.ignore --fixing issue with cin buffer not accepting new input.
https://stackoverflow.com/questions/46204672/getlinecin-string-not-giving-expected-output
*/
My goal is to make a program that inputs a phone number and outputs it in a standard format. It skips over any non-number characters, will output if there are not enough digits, and will also skip over any digits after the first ten digits. My raptor worked without a hitch, but it's been difficult to translate it to C++.
I am using Microsoft Visual Studio.
The problem is it is not running. If I put in anything more then one number in, I receive a fail error.
I am having some difficulty running this code.
Any and all help and advice would be greatly appreciated.
#include <iostream>
#include <string>
using namespace std;
void format(char outArray[], string inNumber)
{
outArray[0] = '(';
outArray[4] = ')';
outArray[5] = ' ';
outArray[9] = '-';
outArray[1] = inNumber[0];
outArray[2] = inNumber[1];
outArray[3] = inNumber[2];
outArray[6] = inNumber[3];
outArray[7] = inNumber[4];
outArray[8] = inNumber[5];
outArray[10] = inNumber[6];
outArray[11] = inNumber[7];
outArray[12] = inNumber[8];
outArray[13] = inNumber[9];
}
int main()
{
string phone, inNumber;
cout << "Please enter a phone number: ";
cin >> phone;
int index = 0;
int num = 0;
char outArray[14];
for (index; phone[index] >= '0' && phone[index] <= '9'; index++)
{
inNumber[num] = phone[index];
num++;
}
if (inNumber.size() > 10)
{
format(outArray, inNumber);
cout << "The properly formatted number is: ";
cout << outArray;
}
else {
cout << "Input must contain at least 10 digits." << endl;
}
system("pause");
return 0;
}
A few things to note:
Use std::string instead array of char array.
You do not need to check charters using a for loop unless you are not sure about the input(phone). However, if that's the case, use std::getline() to get the input and parse as follows using a range-based for loop.
You can use std::isdigit to check the character is a digit.
My goal is to make a program that inputs a phone number and outputs it
in a standard format. It skips over any non-number characters, will
output if there are not enough digits, and will also skip over any
digits after the first ten digits.
That means the number should have a minimum length of 10. Then the
if statement should be if (inNumber.size() >= 10)
Need a pass by ref call in the function format(), since you want to change the content of outArray. Additionally, inNumber could be a
const ref, since we do not change this string.
Updated code: (See a sample code online)
#include <iostream>
#include <string>
#include <cstddef> // std::isdigit, std::size_t
void format(std::string& outArray, const std::string& inNumber) /* noexcept */
{
for (std::size_t index = 0; index < 10; ++index)
{
if (index == 0) outArray += '(';
else if (index == 3) outArray += ") ";
else if (index == 6) outArray += '-';
outArray += inNumber[index];
}
}
int main()
{
std::string phone;
std::cout << "Please enter a phone number: ";
std::getline(std::cin, phone);
std::string inNumber;
for (char letter : phone)
if (std::isdigit(static_cast<unsigned char>(letter))) // check the letter == digits
inNumber += letter;
if (inNumber.size() >= 10)
{
std::string outArray;
format(outArray, inNumber);
std::cout << "The properly formatted number is: ";
std::cout << outArray;
}
else {
std::cout << "Input must contain at least 10 digits." << std::endl;
}
return 0;
}
inNumber[num] = phone[index]; //undefined behavior.
You cannot subscript inNumber now, since its capacity is 0, thus it can not store or access any element here.
You may need to use string's constructor whose parameter has a size_t type or string::reserve or string::resize.
And I'm happy to see cppreference get more complete now, learn to use it: http://en.cppreference.com/w/cpp/string/basic_string
BTW, this function won't do anything you want to:
void format(char outArray[], string inNumber)
maybe you'd like to have an signature like this?
void format(char outArray[], string& inNumber)
The program runs smoothly and I have no errors or warnings when its compiled its just when it gets the end result I just get a load of random letters and numbers no matter what I put in.
Here is the code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int hold;
int n;
int * result = new int;
int * price = new int;
std::string items[6];
for (n=0; n<6; n++)
{
cout << "Item#" << n+1 << ": ";
cin >> items[n];
}
cout << "\nYou Entered: ";
for (int n=0; n<6; n++)
cout << items[n] << ", ";
for (n=0; n<6; n++)
{
if (items[n] == "ab"){
price[n] = 2650;
}
else if (items[n] == "ae"){
price[n] = 1925;
}
else if (items[n] == "ie"){
price[n] = 3850;
}
else if (items[n] == "bt"){
price[n] = 3000;
}
else if (items[n] == "pd"){
price[n] = 2850;
}
else if (items[n] == "ga"){
price[n] = 2600;
}
}
for (n=0; n<6; n++)
{
result += price[n];
}
cout << "\nTotal gold for this build: " << result;
cin >> hold;
return 0;
}
int * price = new int;
and
int * result = new int;
allocate a single int respectively. You probably meant new int[6].
But then again, you should be using std::vector instead.
I'm disappointed really that you took no advice from - https://stackoverflow.com/a/12868164/673730 - if you had, you wouldn't have this problem now. This is not a good way to learn.
With this declaration: int * price = new int; you only allocate space for a single int, but you go on to use price as an array of int.
To declare an array, use: int *price = new int[5];
As for result, you declare that as a pointer to int also, but you later use it as an int: result += price[n];. No need to result to be a pointer. Also note that you need to initialize your variables explicitly: set result to zero before you begin using it.
just give some comments:
new operater should be used with delete.
"int *result" you declared is a point to int, so you should dereference this point to get the result you want.
exceptions should be taken into consideration, what if the input letter is not in your given list?
Well, result is an int *. This kind of variable usually stores the address of another integer variable, which you get with new int in this specific case. However, with
result += price[n];
you'll modify that address, which would lead to segmentation faults if you were to actually write/read from *result. This is also the reason why you output is strange:
cout << "\nTotal gold for this build: " << result;
This prints the adress stored in result, not the value. Make result an integer and it should work.
Please note that price should be changed too, see Luchian's answer.
Exercise
Change your code so that there is no use of new.
Your program could still fail. What is the initial value of result?
What happens if the user provides a code which is not in your list?
Change the line:
cout << "\nTotal gold for this build: " << result;
to
cout << "\nTotal gold for this build: " << *result;
Result is a pointer, so you need to dereference it, using the * operator;
Edit: Change the declaration of the price array to
int *price = new int[6];
The previous declaration declared a variable, not an array
How can I write a program that reads in, a collection of characters from the key board and outputs them to the console. Data is input at random, but output selectively. Only unique characters are displayed at the console. Therefore, every character should be displayed once, no matter how many times it appears in the array.
For example, if an array
Char letterArray[ ] = {B,C,C,X,Y,U,U,U};
The output should be:
B,C,X,Y,U
This is what I have done so far...
char myArray [500];
int count = 0;
int entered = 0;
char num;
while (entered < 8)
{
cout << "\nEnter a Character:";
cin >> num;
bool duplicate = false;
entered++;
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
}
I believe you could make use of std::set<>.
"Sets are a kind of associative container that stores unique elements <...> elements in a set are always sorted from lower to higher following a specific strict weak ordering criterion set"
Looking through your code...
char myArray [500];
Why 500? You never use more than 8.
char num;
Confusing naming. Most programmers would expect a variable named num to be a numeric type (e.g. int or float).
while (entered < 8)
Consider replacing 8 with a constant (e.g. const int kMaxEntered = 8;).
cin >> num;
cin might be line-buffered; i.e. it does nothing until a whole line is entered.
for (int i = 0; i < 8; i++)
{
if (myArray[i] == num)
duplicate=true;
}
You're accessing uninitialized elements of myArray. Hint: your loop size should not be 8.
Consider using continue; if you find a duplicate.
if (!duplicate)
{
myArray[count] = num;
count++;
} // end if
else
cout << num << " character has already been entered\n\n";
Your // end if comment is incorrect. The if isn't ended until the else is done.
You may want to add braces around the else clause, or remove the braces from the if clause by combining its two lines into the one-line myArray[count++] = num;.
// prints the list of values
cout<<"The final Array Contains:\n";
for (int i = 0; i < count; i++)
{
cout << myArray[i] << " ";
}
You're printing the list every time you get a single input?
Don't use \n in text to cout unless you specifically want to micromanage buffering. Instead, use endl. Also, always put spaces around binary operators like << and don't randomly capitalize words:
cout << "The final array contains:" << endl;
for (int i = 0; i < count; i++)
cout << myArray[i] << " ";
cout << endl;
It would be much more efficient to create an array of size 128 (assuming you are dealing with ASCII) that is initialized with false. Every time you get a character, check its ASCII value and if the array is true on that value you don't print it. After that, update the value of the array on the character value to true. Something like:
bool *seenArray = new bool[128]();
void onkey(char input) {
if(((int)input) < 0) return;
if (!seenArray[(int)input]) {
myArray[count] = input;
count++;
seenArray[(int)input] = true;
}
}