As part of a research project, I was testing some hash functions that I found on Eternally Confuzzled here. The project has to do with page caching algorithms and the hash behavior itself never seemed important until now, but this is still more for my own curiosity. To test, I'm using the following code:
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
unsigned oat_hash(void *key, int len);
int main()
{
string name;
cout << "Enter a name: ";
getline(cin, name);
cout << "Hash: " << oat_hash(&name, sizeof(string)) << endl << endl;
cout << "Enter the name again: ";
getline(cin, name);
cout << "Hash: " << oat_hash(&name, sizeof(string)) << endl << endl;
return 0;
}
unsigned oat_hash(void *key, int len)
{
unsigned char *p = (unsigned char*) key;
unsigned h = 0;
for (int i = 0; i < len; i++) {
h += p[i];
h += (h << 10);
h ^= (h >> 6);
}
h += (h << 3);
h ^= (h >> 11);
h += (h << 15);
return h;
}
Program execution 1 output:
Enter a name: John Doe
Hash: 4120494494
Enter the name again: John Doe
Hash: 4120494494
Program execution 2 output:
Enter a name: John Doe
Hash: 3085275063
Enter the name again: John Doe
Hash: 3085275063
I entered the same string and got the same hash value during the same program execution, but why would the values be different for different program executions? Wouldn't different hash values indicate different data?
Implementations of std::string contain a pointer. You are hashing the internals of the std::string and not the actual text of the std::string. On modern systems, the stack location is randomized and also the freestore allocations are randomized, resulting into different internals of std::string each time you run it.
You probably might want to change the code like this:
unsigned oat_hash(void const *key, int len)
{
unsigned char const *p = static_cast<unsigned char const *>(key);
// etc.
}
//...
cout << "Hash: " << oat_hash(name.c_str(), name.size()) << endl << endl;
Related
I am working on a program that has the user input a letter then a string. Once the string is inputted the program should traverse the string and return the amount of the specific letter within the string. Here is the code I have so far:
#include <iostream>
using namespace std;
void countLetters(char letter[]);
/**********************************************************************
* Prompts the user for a line of input (using getline),
* calls countLetters(), and displays the number of letters.
***********************************************************************/
int main()
{
char letter[256];
countLetters(letter);
return 0;
}
/**********************************************************************
* Function to return the number of letters in a string.
***********************************************************************/
void countLetters(char Letter[])
{
char text[] = " ";
int count = 0;
cout << "Enter a letter: ";
cin >> letter;
cout << "Enter text: ";
cin >> text;
cin.getline(text, 256);
for (int i = (sizeof(text) / sizeof(text[0]) - 2); i >=0; i--)
{
if(text[i])
{
count++;
}
cout << "Number of '" << letter << "'s: " << count << endl;
}
}
/*
The output should be:
Enter a number: e
Enter a string: Hello, programming is fun
Number of 'e's: 1
*/
I have tried researching this and have found no help through this method of counting the amount of letters within the string the user inputs. Any help is appreciated, thank you.
Most issues have been pointed out in the comments. Here's a fixed version:
#include <iostream>
using namespace std;
void countLetters();
/**********************************************************************
* Prompts the user for a line of input (using getline),
* calls countLetters(), and displays the number of letters.
***********************************************************************/
int main()
{
// You create an array in the function, don't need one here, too
// char letter[256];
countLetters();
return 0;
}
/**********************************************************************
* Function to return the number of letters in a string.
***********************************************************************/
void countLetters()
{
// Your method creates an array of only 2 bytes
//char text[] = " ";
char text[256];
int count = 0;
// You forgot to declare letter
char letter;
cout << "Enter a letter: ";
cin >> letter;
// Reading the char leaves a new line. Consume. cin.ignore is another way
cin.getline(text, 256);
cout << "Enter text: ";
cin.getline(text, 256);
// Overly complicated
//for (int i = (sizeof(text) / sizeof(text[0]) - 2); i >=0; i--)
for (int i = 0; text[i]; i++)
{
// Compare to letter
if (text[i] == letter)
{
count++;
}
// This needs to be outside the loop
//cout << "Number of '" << letter << "'s: " << count << endl;
}
cout << "Number of '" << letter << "'s: " << count << endl;
}
In C++, it's almost always better to use std::string instead of raw char arrays, but I'll assume this is an assignment and arrays are required.
forum!
I have a project where we are supposed to add numbers that are length 14 or greater. I did some digging and realized that there is no current type that takes numbers this big. So, I have the user enter the numbers as a string and the numbers they would like to add are stored in a static string array.
I would like to add the numbers from the static array together. The issue is I have no idea how to deal with numbers this large. I am assuming you would have to convert the string values into int's and add them up one by one? I am having a big issue coming up with the logic for this. Any help would be appreciated.
If not, if you can provide some context which could help me come up with some logic.
The only library functions I can use is iostream and string.
Here is my code if you'll like to see my logic! I have some test cases I am trying to figure out so please ignore the comment outs. But, if you run the code you should get a better sense of what I am trying to get out. I am trying to sum up the numbers the user enters.
#include <iostream>
#include <string>
using namespace std;
void amountOfNumbers(string &userAmount, int MIN_AMOUNT, int MAX_AMOUNT){
//string alpha = "abcdefghijklmnopqrstuvwxyz";
cout << "How many numbers? -> ";
cin >> userAmount;
cout << endl;
while(!userAmount.find("abcdefghijklmnopqrstuvwxyz")){
cout << "ERROR: must be a number, try again ->";
cout << userAmount;
//cin.clear();
//cin.ignore(1000, '\n');
cin >> userAmount;
cout << endl;
}
int temp = stoi(userAmount);
while((temp < MIN_AMOUNT) or (temp > MAX_AMOUNT)){
cout << "ERROR: Program can only take in " << MIN_AMOUNT << " - "<< MAX_AMOUNT << " numbers. Try again ->";
cin >> userAmount;
cout << endl;
temp = stoi(userAmount);
}
}
void takeNumbers(string &userAmount, string (&numberArray)[11]){
int temp = stoi(userAmount);
for (int i = 0; i < temp; i++){
cout << "Input number #" << i+1 << " ->";
cin >> numberArray[i];
cout << endl;
}
}
void display(string &userAmount, string (&numberArray)[11]){
int temp = stoi(userAmount);
for (int i = 0; i < temp; i++){
cout << numberArray[i];
cout << endl;
}
}
void addNumber(string &userAmount, string (&numberArray)[11]){
}
int main() {
const int MIN_AMOUNT = 2, MAX_AMOUNT = 11, MAX_INPUT = 14;
string userAmount = "0";
string numberInput;
// static array
string numberArray [MAX_AMOUNT];
amountOfNumbers(userAmount, MIN_AMOUNT, MAX_AMOUNT);
takeNumbers(userAmount, numberArray);
display(userAmount, numberArray);
}
so I am beginner to C++ and I am trying to make a Class that contains functions for getting Data, calculating average sum and dividing them by how much grades there are(5) and the final function is for displaying the data about the student.Here's what I get in the console : Click for image
I would be happy to get some advice from you guys.
Here is the code :
class Students{
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
public:
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
cout << "Enter name of the student: "; cin.getline(Name, 20);
cout << "Enter his faculty number: "; cin >> fakn;
cout << "specialty: "; cin.getline(spec, 10);
cout << "Enter grades : ";
for (i = 0; i < 5; i++){
cout << "Enter his grades(5 classes): "; cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
cout << "Name of student: " << Name;
cout << "Student faculty number: " << fakn;
cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
cout << "His " << i << " grade: " << grades[i];
}
cout << "His avarage grade: " << avarage();
}
void main(){
Students in,out;
in.takingdata();
out.displaydata();
_getch();
}
As a result I want the program to display the entered information about the student.
First of all:
Students in,out;
in.takingdata();
out.displaydata();
How is this supposed to work? You have two objects here, writing into the first and reading from the second.
It should be something like:
Students students;
students.takingdata();
students.displaydata();
Still, it's important to understand what really happens in your version of the code. As we have just established, everything you read from std::cin into in is discarded later on. Which bears the question of what exactly you read from out. Let's look at the relevant portion of your class definition again:
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
All of these member variables are of so-called primitive type. This means, among other things, that if you don't initialize them explictly, they will be left uninitialized. For example, br does not "start at 0". It is, strictly speaking, nothing until you assign it something.
Any attempt to output these uninitialized values yields undefined behaviour. Undefined behaviour means that the C++ language specification "gives up" and does not say what the resulting program should do.
What often happens in practice in a situation like yours here is that your program reads a more or less random value that happened to be at the location in memory represented by the variable, and prints that one. The dangerous thing about this is that it may seem to work correctly for a long while because the memory location just happens to contain a zero value, luring you into thinking that your program is bug-free, and then it suddenly crashes or prints garbage values.
So the obvious first fix we should apply to your code is making sure that all the member variables are initialized. While we do that, I'll also:
Add #include <iostream> on top.
Add std:: in front of all standard-library features (that's good practice).
Change the illegal void main to int main.
Remove the unnecessary _getch call.
Here's the result afer the first iteration of fixes:
#include <iostream>
class Students{
int br;
char Name[30];
int fakn,i;
float grades[5],sum;
char spec[25];
public:
Students() :
br(0),
Name(),
fakn(0),
i(0),
grades(),
sum(0.0),
spec()
{}
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
std::cout << "Enter name of the student: "; std::cin.getline(Name, 20);
std::cout << "Enter his faculty number: "; std::cin >> fakn;
std::cout << "specialty: "; std::cin.getline(spec, 10);
std::cout << "Enter grades : ";
for (i = 0; i < 5; i++){
std::cout << "Enter his grades(5 classes): "; std::cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
std::cout << "Name of student: " << Name;
std::cout << "Student faculty number: " << fakn;
std::cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
std::cout << "His " << i << " grade: " << grades[i];
}
std::cout << "His avarage grade: " << avarage();
}
int main(){
Students students;
students.takingdata();
students.displaydata();
}
Note: If you use Visual C++, you should read the following about array-member initialization:
https://msdn.microsoft.com/en-us/library/1ywe7hcy.aspx
But that's not yet very satisfactory. Why should a student's name not be longer than 29 characters (your array consists of a maximum of 29 visible characters plus a terminating '\0' for C-style strings)? And why should it take 30 characters in memory when it turns out to be much shorter?
In fact, what happens if you enter more than 29 characters? Let's give it a try:
Enter name of the student: Long name that does not fit any more in 30 characters
Enter his faculty number: specialty: Enter grades : Enter his grades(5 classes): Enter his grades(5 classes): Enter his grades(5 classes): Enter his grades(5 cl
asses): Enter his grades(5 classes): Name of student: Long name that doesStudent faculty number: 0Student specialty: His 0 grade: 0His 1 grade: 0His 2 grade: 0H
is 3 grade: 0His 4 grade: 0His avarage grade: 0
That's not good. std::istream::getline attempts to write more than 30 characters into a 30-element array. This already yields undefined behaviour. Even if it magically stopped after 30 elements, you'd end up with an array without the terminating '\0', so later outputting code would again leave the array's bounds looking for it. In addition to that, all attempts at reading numbers via std::cin fail because the stream contents after the 30th character cannot be interpreted as numbers, leaving the variables it's supposed to write into in their previous state.
As you can see, reading into a fixed-size char array the way you did is an almost hopeless undertaking. Fortunately, C++ does not force you to keep up with all of that. It offers std::string for dynamically sized strings, and a free-standing std::getline function to read safely into them.
Here's the second iteration of fixes. Note that std::string is not a primitive type, so it knows how to correctly initialize itself. I still added the two variables to the initializer list to be consistent with the other members.
#include <iostream>
#include <string>
class Students{
int br;
std::string Name;
int fakn,i;
float grades[5],sum;
std::string spec;
public:
Students() :
br(0),
Name(),
fakn(0),
i(0),
grades(),
sum(0.0),
spec()
{}
void takingdata();
float avarage();
void displaydata();
};
void Students::takingdata(){
std::cout << "Enter name of the student: "; std::getline(std::cin, Name);
std::cout << "Enter his faculty number: "; std::cin >> fakn;
std::cout << "specialty: "; std::getline(std::cin, spec);
std::cout << "Enter grades : ";
for (i = 0; i < 5; i++){
std::cout << "Enter his grades(5 classes): "; std::cin >> grades[i];
}
}
float Students::avarage(){
sum = 0;
br = 0;
for (i = 0; i < 5; i++){
sum = sum + grades[i];
}
return sum / 5;
}
void Students::displaydata(){
std::cout << "Name of student: " << Name;
std::cout << "Student faculty number: " << fakn;
std::cout << "Student specialty: " << spec;
for (i = 0; i < 5; i++){
std::cout << "His " << i << " grade: " << grades[i];
}
std::cout << "His avarage grade: " << avarage();
}
int main(){
Students students;
students.takingdata();
students.displaydata();
}
The program could take a lot more fixes. For example, you will want to replace the float array with std::vector<float>, and also generally use double instead of float.
In short: You should just use more C++ and less C if you want to program in C++.
#include <iostream>
#include <cstdio>
using namespace std;
class Students {
private:
static const int CLASSES = 5;
static const int NAME = 30;
static const int SPEC = 15;
char name[NAME], spec[SPEC];
int fakn;
float grades[CLASSES],sum;
public:
Students();
void takingdata();
void avarage();
void displaydata();
};
//constructor
Students::Students(){
takingdata();
avarage();
displaydata();
}
//user innput
void Students::takingdata(){
cout << "Enter name of the student: ";
cin.getline(name, NAME);
cout << "Enter his faculty number: ";
cin >> fakn;
cin.ignore();
cout << "specialty: ";
cin.getline(spec, SPEC);
printf("\nEnter Grades (%u classes)\n", CLASSES);
for (int i = 0; i < CLASSES; i++){
printf("Grade 0%u: ", i+1);
cin >> grades[i];
}
}
//calculations
void Students::avarage(){
sum = 0;
for (int i = 0; i < CLASSES; i++){
sum = sum + grades[i];
}
sum /= CLASSES;
}
//display
void Students::displaydata(){
printf("\n\nStudent Name: %s\nFaculty Number: %u\nSpecialty: %s\nGrade Average: %f", name, fakn, spec, sum);
for (int i = 0; i < CLASSES; i++){
printf("\nGrade 0%u: %f", i+1, grades[i]);
}
}
//main
int main(){
//all other functions now called in constructor
Students in;
return 0;
}
I'm a C++ newbie, I'm trying to put in practice pointers with strings. The program I have made is just to store strings the user types in the command line. But I'm getting segfault, not sure why.
This is the code:
#include <cstdio>
#include <cstdlib>
#include <iostream>
using namespace std;
//This code is meant to learn how to use pointers and strings
//Ask the user for who are they in the family and save it in string array!
void print_string (string* Value, int const nSize);
int get_names(string* Family_input);
int main ( int nNumberofArgs, char* pszArgs[])
{
cout << "Tis program stores your family members\n";
cout<< "Type the names and write 0 to exit\n";
string familia_string;
string* familia = &familia_string;
int family_number;
family_number=get_names(familia);
cout << "The family members are: ";
print_string(familia, family_number);
cout << endl;
return 0;
}
int get_names(string* Family_input)
{
int i=0;
string input="";
string old_input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
//cin >> *(Family_input+i);
//input=*(Family_input+i);
cin >> input;
*(Family_input + old_input.length()) = input;
old_input=input;
i++;
}
return i;
}
void print_string (string* Value, int const nSize)
{// I don't want to &psValue to be changed!
for (int i=0; i<nSize; i++)
{
cout << *(Value+i) << " ";
//&psValue++;
}
}
I'm not sure if it's because I'm not taking correctly the size of the string, or I'm not using correctly the pointer or is that I have to allocate memory before using the offset.
As #kleszcz pointed out already, the line
*(Family_input + old_input.length()) = input;
is wrong. You are accessing memory that you are not supposed to.
The easiest fix is to change get_names slightly:
int get_names(string* Family_input)
{
int i=0;
string input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
cin >> input;
*Family_input += input; // Just keep on appending to the input argument.
*Family_input += "\n"; // Add a newline to separate the inputs.
i++;
}
return i;
}
Also change print_string to:
void print_string (string* Value)
{
cout << *Value;
}
Of course, print_string has become so simple, you don't need to have it at all.
You could change get_names to use a reference argument instead of a pointer argument. This is a better practice.
int get_names(string& Family_input)
{
int i=0;
string input="";
while (input!="0")
{
cout << "type " << i <<" member\n";
cin >> input;
Family_input += input; // Just keep on appending to the input argument.
Family_input += "\n"; // Add a newline to separate the inputs.
i++;
}
return i;
}
Then, change the call to get_names. Instead of using
family_number=get_names(familia);
use
family_number=get_names(familia_string);
You get seg fault because you haven't allocate memory for an array of strings.
*(Family_input + old_input.length()) = input;
This is total nonsense. If you'd have an array you increment index only by one not by length of string.
If you want to save different names in different string objects I would suggest:
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
void print_string(string** Value, int const nSize);
void get_names(string** Family_input, int count);
int main(int nNumberofArgs, char* pszArgs[]) {
cout << "This program stores your family members\n";
int family_number;
cout << "Types the number of family members";
cin >> family_number;
/*allocate the number of string pointers that you need*/
string** familia = new string*[family_number];
cout << "Type the names\n";
get_names(familia, family_number);
cout << "The family members are: ";
print_string(familia, family_number);
cout << endl;
return 0;
}
void get_names(string** Family_input, int count) {
for(int i = 0 ; i < count; i++){
cout << "type " << i << " member\n";
/*create a string obj in the heap memory*/
string *input = new string ("");
// using that way you get only a single word
cin >> *input;
/*create a string object on the stack and put its pointer in the family_array*/
Family_input[i] = input;
}
}
void print_string(string** Value, int const nSize) {
for (int i = 0; i < nSize; i++) {
cout << *(Value[i]) << " ";
}
}
I've just started learning C++ and decided to give myself a challenge by creating a simple Christmas Tree program. Everything has been working so far although the code doesn't produce what I expect. I've spent a decent amount of time trying to figure out what's wrong but can't seem to figure out why it doesn't work.
So far, the code looks like this:
#include <iostream>
#include <string>
int main(){
char cTree;
int iSize, iSpace;
std::cout << "Christmas Tree Application" << std::endl;
std::cout << "Enter the size of your christmas tree: ";
std::cin >> iSize;
std::cout << "Enter the character you would like to use for your tree: ";
std::cin >> cTree;
iSpace = iSize / 2;
for(int i = 0; i < iSize; i++){
std::string sTree(i, cTree);
//std::string sSpace(iSpace, ' ');
std::cout << sTree << std::endl;
//iSpace -= 1;
}
return 0;
}
I've also commented out the 'spacing' part because whenever I execute it, it creates an error that I have no clue why it is says that. I know I can do the spacings in a different manner but I'd like to use the std::string way. Any help?
iSpace is set to iSize / 2, yet you run the loop iSize times, decreasing iSpace by one every time. Eventually, iSpace will be negative, which is why you have the error. Try this:
iSpace = iSize;
for(int i = 0; i < iSize; i++){
std::string sTree(i, cTree);
std::string sSpace(iSpace, ' ');
std::cout << sSpace << sTree << sTree << std::endl;
iSpace -= 1;
}
You are looping on the wrong value for iSpace, as it remains constant throughout execution rather than changing like a variable does.
Also, your code can be tidied up a bit. I've posted the updated code below. I've deliberately replaced spaces with underscore characters to provide a better graphical representation of my logic.
Good luck!
Code Listing
#include <iostream>
#include <string>
using namespace std;
int main(void) {
char cTree;
int iSize;
int iSpace;
int iChars;
cout << "Christmas Tree Application" << endl;
cout << "Enter the height of your christmas tree: ";
cin >> iSize;
cout << "Enter the character you would like to use for your tree: ";
cin >> cTree;
for(int i = 0; i < iSize; i++){
iSpace = (iSize-i)-1;
iChars = (2*i)+1;
string sSpace(iSpace, '_');
string sTree(iChars, cTree);
cout << sSpace << sTree << sSpace << endl;
}
return 0;
}
Sample Run
Christmas Tree Application
Enter the height of your christmas tree: 10
Enter the character you would like to use for your tree: #
_________#_________
________###________
_______#####_______
______#######______
_____#########_____
____###########____
___#############___
__###############__
_#################_
###################
awesomeyi is right about the error, however if you'd like it to look more "tree-like" you'll need to double your loop.
i.e.
#include <iostream>
#include <string>
int main(){
char cTree;
int iSize, iSpace;
std::cout << "Christmas Tree Application" << std::endl;
std::cout << "Enter the size of your christmas tree: ";
std::cin >> iSize;
std::cout << "Enter the character you would like to use for your tree: ";
std::cin >> cTree;
iSpace = iSize;
for (int i = 0; i < iSize*2; i+=2){
std::string sTree(i, cTree);
std::string sSpace(iSpace, ' ');
std::cout << sSpace + sTree + sSpace<< std::endl;
iSpace -= 1;
}
return 0;
}
Just for fun, here's a recursive implementation:
#include <iostream>
#include <string>
#include <cstdio>
void drawTree(int level, int height, char c) {
if(level > 0)
drawTree(level-1, height, c);
std::cout << std::string(height-level, ' ') << std::string((2*level)+1, c) << std::endl;
}
int main(){
char cTree;
int iSize;
std::cout << "Christmas Tree Application" << std::endl;
std::cout << "Enter the size of your christmas tree: ";
std::cin >> iSize;
std::cout << "Enter the character you would like to use for your tree: ";
std::cin >> cTree;
drawTree(iSize, iSize, cTree);
return 0;
}